diff --git a/.Rbuildignore b/.Rbuildignore index fcb397c48..8eb10b69e 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -106,3 +106,7 @@ src/ta-lib/Makefile.in ^codegen$ ^CRAN-SUBMISSION$ ^tests/testthat/test-parity.R + +## Claude.md +^src/ta-lib/CLAUDE.md +^src/ta-lib/.claude \ No newline at end of file diff --git a/.github/workflows/pkgdown.yaml b/.github/workflows/pkgdown.yaml index 40aaf994c..7020247ee 100644 --- a/.github/workflows/pkgdown.yaml +++ b/.github/workflows/pkgdown.yaml @@ -35,13 +35,18 @@ jobs: - uses: r-lib/actions/setup-r-dependencies@v2 with: - extra-packages: any::pkgdown any::devtools any::roxygen2 + extra-packages: any::pkgdown any::devtools any::roxygen2 any::rsvg any::magick needs: website - name: Render documentation and NAMESPACE run: devtools::document() shell: Rscript {0} + # realfavicongenerator.net rejects SVG logos (HTTP 500), so build + # the favicons locally; pkgdown skips the API when they exist + - name: Build favicons + run: Rscript dev/favicons.R + - name: Build site run: pkgdown::build_site_github_pages(new_process = FALSE, install = TRUE, clean = TRUE) shell: Rscript {0} 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/CLAUDE.md b/CLAUDE.md index 6ab74b093..99795d10c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -9,7 +9,7 @@ R package (`talib`) providing an interface to the TA-Lib C library for technical ## Build Commands ```bash -make build # Full build: gen-code → document → install +make build # Full build: clean → fmt → document → install (does NOT run gen-code) make check # R CMD check --as-cran make check-full # R CMD check with valgrind make test # Run testthat suite @@ -25,21 +25,19 @@ Single test file: `Rscript -e "testthat::test_file('tests/testthat/test-ta_APO.R ### Code Generation (Most Source Files Are Generated) -Most R wrappers (`R/ta_*.R`), C wrappers (`src/ta_*.c`), and tests (`tests/testthat/test-ta_*.R`) are **auto-generated**. Do not edit these directly — modify the generation infrastructure in `codegen/` instead: +Most R wrappers (`R/ta_*.R`), the C X-macro header (`src/TA-Lib.h`), and tests (`tests/testthat/test-ta_*.R`) are **auto-generated** by the zero-dependency Rust crate in `codegen/` — see `codegen/README.md` for the full architecture. Do not edit generated files directly — modify the generation infrastructure instead: -- `codegen/gen_code/indicators.R` — Unified metadata for all 128 indicators -- `codegen/gen_code/generate.R` — Single driver script that generates R, C, and test files -- `codegen/gen_code/utils.R` — `impl_generate_indicator()` and `impl_generate_test()` helpers -- `codegen/generate_indicator.sh`, `generate_API.sh`, `generate_FFI.sh` — Shell scripts for template-driven generation -- `src/api.h` and `src/init.c` — Auto-generated (function prototypes and R registration) +- `codegen/src/` — `main.rs` (driver), `c_header.rs` (C X-macro lines from ta_func.h), `metadata.rs` (XML mining), `render.rs` (template rendering + splice preservation), `testthat.rs` (test files), `tables.rs` (the hand-maintained per-indicator lookup tables: names, chart types, classifications, exclusions) +- `codegen/templates/` — plain R files with `${...}` placeholders; the `chart_*` templates are dual-backend (one file renders both the `.plotly` and `.ggplot` method) +- Hand-edited content between `## splice::start` / `## splice::end` markers in generated files survives regeneration -Run `make gen-code` after changing any generation logic. +Run `make gen-code` after changing any generation logic (`cargo test` inside `codegen/` tests the generator itself). ### R ↔ C Binding Uses `.Call()` (R's native C interface), not Rcpp. Each indicator has: -1. **C wrapper** (`src/ta_*.c`): Converts R SEXP → C arrays, calls TA-Lib, returns SEXP matrix +1. **C wrapper**: one X-macro line in the generated `src/TA-Lib.h`, expanded by the hand-written `src/wrapper.h`/`src/init.c` macros into a function that converts R SEXP → C arrays, calls TA-Lib, and returns a SEXP matrix (there are no per-indicator `.c` files) 2. **R wrapper** (`R/ta_*.R`): S3 generic with methods for `default`, `data.frame`, and `plotly` C memory management uses manual `PROTECT`/`UNPROTECT` with protection counters. @@ -87,8 +85,8 @@ isolated without depending on those packages. `chart()` and its - `R/helper.R` — Operators (`%nn%`, `%or%`), chart helpers (`plotly_init`, `plotly_line`, `ggplot_init`, `ggplot_line`, `modify_traces`, `add_idx`, `rebuild_formula`) - `R/BTC.R`, `R/NVDA.R`, `R/SPY.R`, `R/ATOM.R` — Built-in OHLCV datasets (docs only; `.rda` files in `data/`) - `R/talib-package.R` — `generate_returns_section()` used at roxygen-render time by `man-roxygen/returns.R` -- `src/dataframe.c` — Matrix↔data.frame conversion (`map_dfr`) -- `src/container.h`, `src/shift.h`, `src/names.h` — Shared C utilities +- `src/data-frame.c` — Matrix↔data.frame conversion (`map_dfr`) +- `src/shift.h`, `src/names.h` — Shared C utilities ### TA-Lib Submodule 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..6ba30c983 100644 --- a/Makefile +++ b/Makefile @@ -15,30 +15,114 @@ help: | sed -E 's/^[[:space:]]*//' \ | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[1;34m%-15s\033[m \xE2\x80\x94 %s\n", $$1, $$2}' -document: ## Build R documentation +## This target are mainly included to +## ease the the development process of {talib} +## - The configure will always prefer system-level +## TA-Lib, which means that downstream installs/checks +## will be faster if pre-installed. +## +## NOTE: It currently only works UNIX. +.PHONY: TA-Lib +TA-Lib: ## Install TA-Lib on system (Requires sudo) + @if ! pkg-config --exists ta-lib; then \ + cd src/ta-lib; \ + sudo chmod +x ./autogen.sh; \ + ./autogen.sh && ./configure; \ + make; \ + sudo make install; \ + sudo ldconfig; \ + fi + +## This target is a precursor to all +## targets either directly or recursively +## and its a good idea to run to prevent shenanigans +## when creating new S3 functions or similar. +.PHONY: document +document: fmt ## Document R package using {devtools} @Rscript --verbose -e "devtools::document()" -build: clean fmt ## Build the R package - @codegen/generate_API.sh src/ src/api.h && codegen/generate_FFI.sh src/api.h src/init.c && $(MAKE) fmt +## pkgdown +## Build the online documentation +## and preview the built site +.PHONY: pkgdown +pkgdown: ## Build {pkgdown} documentation @$(MAKE) document - @R CMD build . --no-build-vignettes && R CMD INSTALL $(tarball_location) - @rm -rf README.md - @Rscript -e "rmarkdown::render('dev/README.Rmd', output_dir = '.', output_format = rmarkdown::github_document(html_preview = FALSE), clean = TRUE)" - -check: fmt document build parity-prepare ## Check the R package - @TALIB_PARITY_SNAPSHOT_DIR=$$(pwd)/tests/parity/snapshot \ - TALIB_STRICT_WARNINGS=1 \ - R CMD check --as-cran $(tarball_location) + @Rscript -e "pkgdown::clean_site()" + @Rscript dev/favicons.R + @Rscript -e "pkgdown::init_site()" + @Rscript -e "pkgdown::build_site()" + @rm -rf pkgdown/favicon + @rmdir pkgdown 2>/dev/null || true + @Rscript -e "pkgdown::preview_site()" -check-full: fmt document build parity-prepare ## Check the R package with valgrind - @TALIB_PARITY_SNAPSHOT_DIR=$$(pwd)/tests/parity/snapshot \ - TALIB_STRICT_WARNINGS=1 \ - R CMD check --as-cran --use-valgrind $(tarball_location) +.PHONY: build +build: document + @R CMD build . --no-build-vignettes --no-manual + +.PHONY: install +install: build ## Install the R package + @R CMD INSTALL $(tarball_location) --no-multiarch + +## benchmarking +## This target runs the full benchmark suite +## against {TTR} - if there is a need for modifying +## plots and such do it in the folder +.PHONY: bench +bench: ## Run benchmark(s) against {TTR} + @echo -e "Running full benchmark suite (overhead + TTR comparison)..." + @echo -e "" + @Rscript ./benchmark/run-all.R + @echo -e "" + @echo -e "Rendering benchmark/README.Rmd..." + @cd benchmark && Rscript -e "rmarkdown::render('README.Rmd', output_format = rmarkdown::github_document(html_preview = FALSE), clean = TRUE)" -test: fmt parity-prepare ## Run tests (incl. parity) +## Checks +## check: +## This target is for R CMD checks during +## local development +## check-cran: +## This target is for full R CMD checks +## that uses the vendored TA-Lib primarily +## meant to be run before CRAN submissions +## or pushes to Github +## +## NOTE: There is no need to install the package +## before checks. +.PHONY: check +check: build ## Check R package + @R CMD check --no-multiarch --ignore-vignettes --no-manual $(tarball_location) + @$(MAKE) README + +.PHONY: check-cran +check-cran: document ## Check R package (CRAN) + @R CMD build . + @R CMD check --install-args=--configure-args="--force-vendor" --as-cran --use-valgrind $(tarball_location) + @$(MAKE) README + +## Test +## This target runs the unit-tests including +## the parity tests without conducting the full check suite +.PHONY: test +test: install parity-prepare ## Run unit-tests @TALIB_PARITY_SNAPSHOT_DIR=$$(pwd)/tests/parity/snapshot \ Rscript --verbose -e "library(talib); testthat::test_dir('tests/testthat', stop_on_failure = TRUE)" + @rm -f codegen/parity/parity_gen + @rm -f tests/testthat/test-parity.R + @rm -rf tests/parity/snapshot +## Janitor +## clean: +## Deletes simple build artifacts +## purge: +## Uninstalls TA-Lib and restores the +## vendored folder to its original state +## +## NOTE: +## If the system library is installed, and the +## unistall fails, its no longer possible to uninstall +## but it can be fixed by reinstalling TA-Lib and then +## running purge again! +.PHONY: clean clean: ## Remove artifacts @rm -rf src/*.o @rm -rf src/*.so @@ -46,15 +130,19 @@ clean: ## Remove artifacts @rm -rf src/Makevars @rm -rf $(package_name).Rcheck @rm -rf docs - @rm -f tests/testthat/test-parity.R -purge: clean ## Remove TA-Lib arifacts +.PHONY: purge +purge: clean ## Remove TA-Lib arifacts and system libraries + @if pkg-config --exists ta-lib; then \ + (cd src/ta-lib && sudo $(MAKE) uninstall); \ + fi @git -C src/ta-lib restore --staged --worktree . @git -C src/ta-lib clean -fdx @Rscript -e "try(remove.packages('$(package_name)'))" @rm -rf tests/parity/snapshot @rm -f codegen/parity/parity_gen +.PHONY: fmt fmt: ## Format code @clang-format \ -style='{ @@ -69,68 +157,50 @@ fmt: ## Format code @air format R @air format tests/testthat @rm -rf ./.clang-format - -pkgdown-build: ## Build {pkgdown} documentation - @$(MAKE) document - @Rscript -e "pkgdown::clean_site()" - @Rscript -e "pkgdown::init_site()" - @Rscript -e "pkgdown::build_site()" - -pkgdown-preview: ## Preview {pkgdown} documetation - @Rscript -e "pkgdown::preview_site()" - -bench: ## Run benchmark(s) - @echo -e "Running benchmark..." - @echo -e "" - @Rscript ./benchmark/benchmark-overhead.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" - @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) - -validate: ## Validate R output against TA-Lib core - @PKG_CFLAGS="-Isrc/ta-lib/local/include -Isrc/ta-lib/local/include/ta-lib" \ - PKG_LIBS="src/ta-lib/local/lib/libta-lib.a -lm" \ - R CMD SHLIB codegen/validation/validate.c - @Rscript codegen/validation/validate.R - @rm -f codegen/validation/validate.o codegen/validation/validate.so - -parity-gen: ## Build the standalone parity_gen exe (pure C, no R linkage) - @CC=$${CC:-gcc}; \ - $$CC -O2 -Wall -Wextra \ - -Isrc/ta-lib/local/include -Isrc/ta-lib/local/include/ta-lib \ - codegen/parity/parity_gen.c \ - src/ta-lib/local/lib/libta-lib.a -lm \ - -o codegen/parity/parity_gen - -## Internal helper: build the C exe, regenerate the upstream snapshot, -## and stage tests/testthat/test-parity.R from the template. Invoked -## by `make parity`, `make test`, `make check`, `make check-full`. -parity-prepare: parity-gen - @TMPDIR=$$(mktemp -d); \ - trap 'rm -rf "$$TMPDIR"' EXIT; \ - mkdir -p "$$TMPDIR/csv" tests/parity/snapshot; \ - Rscript codegen/parity/btc_to_csv.R "$$TMPDIR/btc.csv"; \ - ./codegen/parity/parity_gen "$$TMPDIR/btc.csv" "$$TMPDIR/csv"; \ + @cargo fmt --manifest-path codegen/Cargo.toml + +.PHONY: codegen +codegen: ## Generate R wrappers and unit-tests + @cargo run --manifest-path codegen/Cargo.toml + $(MAKE) fmt + +## Make helpers +## +## These helpers are not really meant to be run +## directly but are used internally to support the +## development in one form or the other + +## Parity against upstream +## This target is an internal helper +## used for the test target which compares +## the output against upstream +.PHONY: parity-prepare +parity-prepare: + @CC=$${CC:-gcc}; \ + if pkg-config --exists ta-lib; then \ + $$CC -O2 -Wall -Wextra \ + $$(pkg-config --cflags ta-lib) \ + codegen/parity/parity_gen.c \ + $$(pkg-config --libs ta-lib) -lm \ + -o codegen/parity/parity_gen; \ + else \ + $$CC -O2 -Wall -Wextra \ + -Isrc/ta-lib/local/include -Isrc/ta-lib/local/include/ta-lib \ + codegen/parity/parity_gen.c \ + src/ta-lib/local/lib/libta-lib.a -lm \ + -o codegen/parity/parity_gen; \ + fi + @TMPDIR=$$(mktemp -d); \ + trap 'rm -rf "$$TMPDIR"' EXIT; \ + mkdir -p "$$TMPDIR/csv" tests/parity/snapshot; \ + Rscript codegen/parity/btc_to_csv.R "$$TMPDIR/btc.csv"; \ + ./codegen/parity/parity_gen "$$TMPDIR/btc.csv" "$$TMPDIR/csv"; \ Rscript codegen/parity/csv_to_rds.R "$$TMPDIR/csv" tests/parity/snapshot @cp codegen/parity/test_parity_template.R tests/testthat/test-parity.R -parity: parity-prepare ## Regenerate the upstream snapshot and run the parity test only - @TALIB_PARITY_SNAPSHOT_DIR=$$(pwd)/tests/parity/snapshot \ - Rscript -e "library(talib); testthat::test_file('tests/testthat/test-parity.R', stop_on_failure = TRUE)" - -parity-clean: ## Remove parity build artifacts and the generated test file - @rm -f codegen/parity/parity_gen - @rm -f tests/testthat/test-parity.R - @rm -rf tests/parity/snapshot - -gen-code: ## Generate R wrappers and unit-tests - @Rscript --verbose ./codegen/gen_code/generate.R - $(MAKE) fmt \ No newline at end of file +## README +## Rebuild README +.PHONY: README +README: + @rm -rf README.md + @Rscript -e "rmarkdown::render('dev/README.Rmd', output_dir = '.', output_format = rmarkdown::github_document(html_preview = FALSE), clean = TRUE)" \ No newline at end of file diff --git a/NAMESPACE b/NAMESPACE index 0175c495d..1755e10cd 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -33,6 +33,13 @@ S3method(aroon_oscillator,default) S3method(aroon_oscillator,ggplot) S3method(aroon_oscillator,matrix) S3method(aroon_oscillator,plotly) +S3method(as.maType,double) +S3method(as.maType,integer) +S3method(as.maType,maType) +S3method(average_deviation,data.frame) +S3method(average_deviation,default) +S3method(average_deviation,matrix) +S3method(average_deviation,numeric) S3method(average_directional_movement_index,data.frame) S3method(average_directional_movement_index,default) S3method(average_directional_movement_index,ggplot) @@ -322,9 +329,17 @@ S3method(mesa_adaptive_moving_average,ggplot) S3method(mesa_adaptive_moving_average,matrix) S3method(mesa_adaptive_moving_average,numeric) S3method(mesa_adaptive_moving_average,plotly) +S3method(midpoint_period,data.frame) +S3method(midpoint_period,default) +S3method(midpoint_period,ggplot) +S3method(midpoint_period,matrix) +S3method(midpoint_period,numeric) +S3method(midpoint_period,plotly) S3method(midpoint_price,data.frame) S3method(midpoint_price,default) +S3method(midpoint_price,ggplot) S3method(midpoint_price,matrix) +S3method(midpoint_price,plotly) S3method(minus_directional_indicator,data.frame) S3method(minus_directional_indicator,default) S3method(minus_directional_indicator,ggplot) @@ -411,12 +426,6 @@ S3method(plus_directional_movement,matrix) S3method(plus_directional_movement,plotly) S3method(print,talib_chart) S3method(print,talib_gg_chart) -S3method(rate_of_change,data.frame) -S3method(rate_of_change,default) -S3method(rate_of_change,ggplot) -S3method(rate_of_change,matrix) -S3method(rate_of_change,numeric) -S3method(rate_of_change,plotly) S3method(ratio_of_change,data.frame) S3method(ratio_of_change,default) S3method(ratio_of_change,ggplot) @@ -443,10 +452,10 @@ S3method(rolling_beta,default) S3method(rolling_beta,numeric) S3method(rolling_correlation,default) S3method(rolling_correlation,numeric) -S3method(rolling_max,default) -S3method(rolling_max,numeric) -S3method(rolling_min,default) -S3method(rolling_min,numeric) +S3method(rolling_maximum,default) +S3method(rolling_maximum,numeric) +S3method(rolling_minimum,default) +S3method(rolling_minimum,numeric) S3method(rolling_standard_deviation,default) S3method(rolling_standard_deviation,numeric) S3method(rolling_sum,default) @@ -636,6 +645,12 @@ S3method(upside_gap_2_crows,default) S3method(upside_gap_2_crows,ggplot) S3method(upside_gap_2_crows,matrix) S3method(upside_gap_2_crows,plotly) +S3method(variable_moving_average_period,data.frame) +S3method(variable_moving_average_period,default) +S3method(variable_moving_average_period,ggplot) +S3method(variable_moving_average_period,matrix) +S3method(variable_moving_average_period,numeric) +S3method(variable_moving_average_period,plotly) S3method(weighted_close_price,data.frame) S3method(weighted_close_price,default) S3method(weighted_close_price,matrix) @@ -664,6 +679,7 @@ export(APO) export(AROON) export(AROONOSC) export(ATR) +export(AVGDEV) export(AVGPRICE) export(BBANDS) export(BETA) @@ -747,9 +763,11 @@ export(MACD) export(MACDEXT) export(MACDFIX) export(MAMA) +export(MAVP) export(MAX) export(MEDPRICE) export(MFI) +export(MIDPOINT) export(MIDPRICE) export(MIN) export(MINUS_DI) @@ -760,7 +778,6 @@ export(OBV) export(PLUS_DI) export(PLUS_DM) export(PPO) -export(ROC) export(ROCR) export(RSI) export(SAR) @@ -783,112 +800,213 @@ export(VOLUME) export(WCLPRICE) export(WILLR) export(WMA) +export(abandonedBaby) export(abandoned_baby) +export(absolutePriceOscillator) export(absolute_price_oscillator) +export(accelerationBands) export(acceleration_bands) +export(advanceBlock) export(advance_block) export(aroon) +export(aroonOscillator) export(aroon_oscillator) +export(averageDeviation) +export(averageDirectionalMovementIndex) +export(averageDirectionalMovementIndexRating) +export(averagePrice) +export(averageTrueRange) +export(average_deviation) export(average_directional_movement_index) export(average_directional_movement_index_rating) export(average_price) export(average_true_range) +export(balanceOfPower) export(balance_of_power) +export(beltHold) export(belt_hold) +export(bollingerBands) export(bollinger_bands) +export(breakAway) export(break_away) +export(chaikinAccumulationDistributionLine) +export(chaikinAccumulationDistributionOscillator) export(chaikin_accumulation_distribution_line) export(chaikin_accumulation_distribution_oscillator) +export(chandeMomentumOscillator) export(chande_momentum_oscillator) export(chart) +export(closingMarubozu) export(closing_marubozu) +export(commodityChannelIndex) export(commodity_channel_index) +export(concealingBabySwallow) export(concealing_baby_swallow) +export(counterAttack) export(counter_attack) +export(darkCloudCover) export(dark_cloud_cover) +export(directionalMovementIndex) export(directional_movement_index) export(doji) +export(dojiStar) export(doji_star) +export(dominantCyclePeriod) +export(dominantCyclePhase) export(dominant_cycle_period) export(dominant_cycle_phase) +export(doubleExponentialMovingAverage) export(double_exponential_moving_average) +export(dragonflyDoji) export(dragonfly_doji) export(engulfing) +export(eveningDojiStar) +export(eveningStar) export(evening_doji_star) export(evening_star) +export(exponentialMovingAverage) export(exponential_moving_average) +export(extendedMovingAverageConvergenceDivergence) +export(extendedParabolicStopAndReverse) export(extended_moving_average_convergence_divergence) export(extended_parabolic_stop_and_reverse) +export(fastStochastic) export(fast_stochastic) +export(fixedMovingAverageConvergenceDivergence) export(fixed_moving_average_convergence_divergence) +export(gapsSideWhite) export(gaps_side_white) +export(gravestoneDoji) export(gravestone_doji) export(hammer) +export(hangingMan) export(hanging_man) export(harami) +export(haramiCross) export(harami_cross) +export(highWave) export(high_wave) export(hikakke) +export(hikakkeMod) export(hikakke_mod) +export(homingPigeon) export(homing_pigeon) +export(inNeck) export(in_neck) export(indicator) +export(intradayMovementIndex) export(intraday_movement_index) +export(invertedHammer) export(inverted_hammer) +export(kaufmanAdaptiveMovingAverage) export(kaufman_adaptive_moving_average) export(kicking) +export(kickingBabyLength) export(kicking_baby_length) +export(ladderBottom) export(ladder_bottom) +export(longLeggedDoji) +export(longLine) export(long_legged_doji) export(long_line) +export(lookback) export(marubozu) +export(matHold) export(mat_hold) +export(matchingLow) export(matching_low) +export(medianPrice) export(median_price) +export(mesaAdaptiveMovingAverage) export(mesa_adaptive_moving_average) +export(midpointPeriod) +export(midpointPrice) +export(midpoint_period) export(midpoint_price) +export(minusDirectionalIndicator) +export(minusDirectionalMovement) export(minus_directional_indicator) export(minus_directional_movement) export(momentum) +export(moneyFlowIndex) export(money_flow_index) +export(morningDojiStar) +export(morningStar) export(morning_doji_star) export(morning_star) +export(movingAverageConvergenceDivergence) export(moving_average_convergence_divergence) +export(normalizedAverageTrueRange) export(normalized_average_true_range) +export(onBalanceVolume) +export(onNeck) export(on_balance_volume) export(on_neck) +export(parabolicStopAndReverse) export(parabolic_stop_and_reverse) +export(percentagePriceOscillator) export(percentage_price_oscillator) +export(phasorComponents) export(phasor_components) export(piercing) +export(plusDirectionalIndicator) +export(plusDirectionalMovement) export(plus_directional_indicator) export(plus_directional_movement) -export(rate_of_change) +export(ratioOfChange) export(ratio_of_change) +export(relativeStrengthIndex) export(relative_strength_index) +export(rickshawMan) export(rickshaw_man) +export(riseFall3Methods) export(rise_fall_3_methods) +export(rollingBeta) +export(rollingCorrelation) +export(rollingMaximum) +export(rollingMinimum) +export(rollingStandardDeviation) +export(rollingSum) +export(rollingVariance) export(rolling_beta) export(rolling_correlation) -export(rolling_max) -export(rolling_min) +export(rolling_maximum) +export(rolling_minimum) export(rolling_standard_deviation) export(rolling_sum) export(rolling_variance) +export(separatingLines) export(separating_lines) export(set_theme) +export(shootingStar) export(shooting_star) +export(shortLine) export(short_line) +export(simpleMovingAverage) export(simple_moving_average) +export(sineWave) export(sine_wave) +export(spinningTop) export(spinning_top) +export(stalledPattern) export(stalled_pattern) +export(stickSandwich) export(stick_sandwich) export(stochastic) +export(stochasticRelativeStrengthIndex) export(stochastic_relative_strength_index) +export(t3ExponentialMovingAverage) export(t3_exponential_moving_average) export(takuri) +export(tasukiGap) export(tasuki_gap) +export(threeBlackCrows) +export(threeIdenticalCrows) +export(threeInside) +export(threeLineStrike) +export(threeOutside) +export(threeStarsInTheSouth) +export(threeWhiteSoldiers) export(three_black_crows) export(three_identical_crows) export(three_inside) @@ -898,21 +1016,37 @@ export(three_stars_in_the_south) export(three_white_soldiers) export(thrusting) export(trading_volume) +export(trendCycleMode) export(trend_cycle_mode) export(trendline) +export(triangularMovingAverage) export(triangular_moving_average) +export(tripleExponentialAverage) +export(tripleExponentialMovingAverage) export(triple_exponential_average) export(triple_exponential_moving_average) export(tristar) +export(trueRange) export(true_range) +export(twoCrows) export(two_crows) +export(typicalPrice) export(typical_price) +export(ultimateOscillator) export(ultimate_oscillator) +export(unique3River) export(unique_3_river) +export(upsideGap2Crows) export(upside_gap_2_crows) +export(variableMovingAveragePeriod) +export(variable_moving_average_period) +export(weightedClosePrice) +export(weightedMovingAverage) export(weighted_close_price) export(weighted_moving_average) +export(williamsOscillator) export(williams_oscillator) +export(xsideGap3Methods) export(xside_gap_3_methods) importFrom(utils,.DollarNames) useDynLib(talib, .registration = TRUE, .fixes = "C_") diff --git a/NEWS.md b/NEWS.md index 3ef42aab3..e6a89c34d 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,143 @@ +# version 0.9-3 + +This version brings *many* changes to the R package. +The entire code generating backend have been rewritten so it *closely* follows the upstream naming of parameters and it uses X-macros so it also installs way fastert than before - but it also means that there is alot of breaking changes. +The update is a big leap towards a stable release. + +## 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}. + +* The source code have been re-written so it generates the underlying TA-Lib wrappers using preprocessors and X-Macros, which compiles much faster than before. + +* _**MAVP:** Moving Average Variable Periods_—The function calculates a moving average with variable periods between candles. See below: + +```R +talib::variable_moving_average_period( + x = 1:10, + periods = c(1, 1, 1, 2, 2, 2, 3, 4, 4, 4), + minimumPeriod = 2, + maximumPeriod = 4 +) + +#> [1] NA NA NA 3.5 4.5 5.5 6.0 6.5 7.5 8.5 +#> attr(,"lookback") +``` + +* _**AVGDEV:** Averge deviation_—The function calculates the average deviation of a series. See below: + +```R +talib::average_deviation( +x = 1:10, +periods = c(1, 1, 1, 2, 2, 2, 3, 4, 4, 4), +timePeriod = 5 +) +#> [1] NA NA NA NA 1.2 1.2 1.2 1.2 1.2 1.2 +#> attr(,"lookback") +#> [1] 4 +``` + +* All indicators have gotten a `camelCase` alias to introduce a form of consistency across R's finance ecosystem and oldschool coding schemes. +The indicators below produces the same output: + +```R +talib::bollinger_bands() +talib::BBANDS() +talib::bollingerBands() +``` + +Each `UPPERCASE` and `camelCase` function is an alias of its underlying `snake_case` function, so the functions behaves the same. + +## breaking changes + +* **General:** All functions now follows the naming convention of TA-Lib. All function signatures are on the following form: + +```R +indicator( + x, ## unchanged + cols, ## unchanged + ## additional/optional TA-Lib parameters + ## are now camelCase mined upstream + timePeriod, ## was 'n' before + fooBar, ## was 'foo_bar' or 'foobar' before + fooBaz, ## was 'foo_baz' or 'foobaz' before + na.bridge = FALSE ## unchanged +) +``` + +This has the benefit of being transparent when comparing or reading the source code. + +* **MATypes:** Functions that used MATypes in the indicator function are now significantly different. See the `bollinger_bands()` below: + +```R +talib::bollinger_bands( + talib::BTC, + timePeriod = 20, + maType = talib::EMA() +) +``` + +Prior to this update, the correct call was: + +```R +talib::bollinger_bands( + talib::BTC, + ma = talib::EMA(n = 20) +) +``` + +While the above function call is aestethically pleasing, it did introduce some ambigiuites in other calls. See, for example, `APO()` (v0.9.2) below: + +```R +absolute_price_oscillator( + x, + cols, + fast = 12, + slow = 26, + ma = SMA(n = 9), + na.bridge = FALSE, + ... +) +``` + +In this specific case the function has three different `n` - the underlying function were discarding `n = 9` while keeping the MAType. +The new call is given as: + +```R +absolute_price_oscillator( + x, + cols, + fastPeriod = 12, + slowPeriod = 26, + maType = 0, + na.bridge = FALSE, + ... +) +``` + +In this call the role of each argument is *should* be clearer than before. + +## bug-fixes + +* _**CCI:** Incorrect charting_—The indicator were incorrectly classified as a main chart indicator— + +* _**One-dimensional indicators:** incorrect return \_—Indicators that returns a one-dimensional indicator (MA, RSI, etc.) were returning a \ or \ instead of \. + +* _**Merged indicators:** overlapping last-values_—On the plotly backend, merging indicators onto one panel stacked every last-value label on the panel's top-right corner. The labels are now collapsed into a single evenly spaced label, mirroring the merged subtitle of the ggplot2 backend. + +* _**Merged indicators:** indistinguishable last-values_—Merged last-value labels used the bare output column name, so merging the same indicator with different parameters displayed identical labels. The labels now carry the full indicator specification, including its parameters, as the ggplot2 backend already did. + # version 0.9-2 ## improvements diff --git a/R/chart_elements.R b/R/chart_elements.R index 23df2cab9..74ba585b3 100644 --- a/R/chart_elements.R +++ b/R/chart_elements.R @@ -43,10 +43,15 @@ add_limit_ly <- function( ## add OHLC last-value annotation ## displayed at the top-right corner of the main chart +## +## when name is provided it is stored as metadata +## on the plot so merge_subchart_plotly() can build +## a combined spec-named label for multi-indicator panels add_last_value_ly <- function( p, data, - values_to_extract = c("open", "high", "low", "close") + values_to_extract = c("open", "high", "low", "close"), + name = NULL ) { ## extract the last row for the ## relevant OHLC columns @@ -76,7 +81,7 @@ add_last_value_ly <- function( collapse = " " ) - plotly::add_annotations( + p <- plotly::add_annotations( p = p, text = value_text, x = 1, @@ -94,6 +99,17 @@ add_last_value_ly <- function( ) ) ) + + ## store metadata for merge_subchart_plotly() + ## to reconstruct a combined spec-named label + if (!is.null(name)) { + attr(p, "talib_last_value") <- list( + name = name, + values = values + ) + } + + p } ## ---- ggplot2 elements ---- diff --git a/R/chart_indicator.R b/R/chart_indicator.R index f647afa64..9496fe408 100644 --- a/R/chart_indicator.R +++ b/R/chart_indicator.R @@ -383,13 +383,47 @@ indicator_multi <- function(exprs, envir) { merge_subchart_plotly <- function(from, to) { state <- .chart_state() + ## rewrite a built panel's last-value annotation to the spec name + ## stored by add_last_value_ly() (RSI(10): 45.32 instead of + ## RSI: 45.32) so merged indicators stay distinguishable - + ## mirrors the spec-named subtitle of the ggplot2 backend + ## single output: RSI(10): 45.32 + ## multi output: MACD(12,26,9): 0.50 / 0.30 / 0.20 + relabel_last_value <- function(built, panel) { + lv <- attr(panel, "talib_last_value") + if (is.null(lv)) { + return(built) + } + anns <- built$x$layout$annotations + for (j in seq_along(anns)) { + if ( + identical(anns[[j]]$xanchor, "right") && + identical(anns[[j]]$yanchor, "bottom") + ) { + built$x$layout$annotations[[j]]$text <- sprintf( + "%s: %s", + lv$name, + paste(sprintf("%.2f", lv$values), collapse = " / ") + ) + break + } + } + built + } + ## build the base panel - base <- plotly::plotly_build(state$sub[[from]]) + base <- relabel_last_value( + plotly::plotly_build(state$sub[[from]]), + state$sub[[from]] + ) ## merge traces and annotations ## from subsequent panels for (i in seq(from + 1L, to)) { - other <- plotly::plotly_build(state$sub[[i]]) + other <- relabel_last_value( + plotly::plotly_build(state$sub[[i]]), + state$sub[[i]] + ) base$x$data <- c(base$x$data, other$x$data) ## merge annotations like subchart @@ -402,6 +436,34 @@ merge_subchart_plotly <- function(from, to) { } } + ## the per-panel last-value labels all sit at the panel's + ## top-right corner (x = 1, y = 1, paper) and would overlap - + ## collapse them into one evenly spaced right-aligned label, + ## mirroring the merged subtitle of the ggplot2 backend + ## opt-out via options(talib.chart.merged_last_value = FALSE) + anns <- base$x$layout$annotations + is_last_value <- vapply( + anns, + function(a) { + identical(a$xanchor, "right") && + identical(a$yanchor, "bottom") + }, + logical(1) + ) + if (any(is_last_value)) { + if (getOption("talib.chart.merged_last_value", TRUE)) { + keep <- which(is_last_value)[1L] + anns[[keep]]$text <- paste( + vapply(anns[is_last_value], `[[`, character(1), "text"), + collapse = "  " + ) + anns <- anns[!is_last_value | seq_along(anns) == keep] + } else { + anns <- anns[!is_last_value] + } + base$x$layout$annotations <- anns + } + ## remove explicit y-range so plotly ## auto-scales for the combined data base$x$layout$yaxis$range <- NULL diff --git a/R/lookback.R b/R/lookback.R new file mode 100644 index 000000000..267670db5 --- /dev/null +++ b/R/lookback.R @@ -0,0 +1,158 @@ +#' @export +#' @family Utility +#' +#' @title 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, +#' 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)]] + } + + ## validate input arguments + ## to avoid downstream shenanigans + ## talib::BBANDS with non-existing arguments + ## like 'n' will break stuff + passed_arguments <- names(c( + as.list( + environment() + ), + list(...) + ))[-c(1:2)] + + actual_arguments <- names( + formals( + as.character(FUN) + ) + ) + + ## stop the function early instead + ## of silently modifying the underlying + ## call - this seems to be the optimal choice + ## as the lookback function is a development function + ## more than a "regular user"-function, so it is + ## expected that the developer knows what its doing. + if (!all(passed_arguments %in% actual_arguments)) { + stop( + sprintf( + "The `lookback()` is strictly typed. + \rArguments passed into ... has to match that of `%s()` with no additional phantom variables.", + as.character(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..8ed41cb75 100644 --- a/R/ta_ACCBANDS.R +++ b/R/ta_ACCBANDS.R @@ -1,22 +1,23 @@ #' @export -#' @family Overlap Study +#' @family Overlap Studies #' #' @title Acceleration Bands #' @templateVar .title Acceleration Bands #' @templateVar .author Serkan Korkmaz #' @templateVar .fun acceleration_bands -#' @templateVar .family Overlap Study -#' @templateVar .formula ~ high + low + close +#' @templateVar .family Overlap Studies +#' @templateVar .formula ~high + low + close #' ## splice:documentation:start ## splice:documentation:end #' #' @template description +#' #' @template returns acceleration_bands <- function( x, cols, - n = 20, + timePeriod = 20, na.bridge = FALSE, ... ) { @@ -30,6 +31,13 @@ acceleration_bands <- function( #' @aliases acceleration_bands ACCBANDS <- acceleration_bands +#' @export +#' @usage NULL +#' @rdname acceleration_bands +#' +#' @aliases acceleration_bands +accelerationBands <- acceleration_bands + #' @usage NULL #' @aliases acceleration_bands #' @@ -37,7 +45,7 @@ ACCBANDS <- acceleration_bands acceleration_bands.default <- function( x, cols, - n = 20, + timePeriod = 20, na.bridge = FALSE, ... ) { @@ -64,12 +72,10 @@ acceleration_bands.default <- function( ## return as data.frame x <- .Call( C_impl_ta_ACCBANDS, - ## splice:call:start constructed_series[[1]], constructed_series[[2]], constructed_series[[3]], - as.integer(n), - ## splice:call:end + as.integer(timePeriod), as.logical(na.bridge) ) @@ -87,7 +93,7 @@ acceleration_bands.default <- function( acceleration_bands.data.frame <- function( x, cols, - n = 20, + timePeriod = 20, na.bridge = FALSE, ... ) { @@ -95,7 +101,7 @@ acceleration_bands.data.frame <- function( acceleration_bands.default( x = x, cols = cols, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge, ... ) @@ -109,19 +115,32 @@ acceleration_bands.data.frame <- function( acceleration_bands.matrix <- function( x, cols, - n = 20, + timePeriod = 20, na.bridge = FALSE, ... ) { acceleration_bands.default( x = x, cols = cols, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge, ... ) } +#' @usage NULL +ACCBANDS_lookback <- accelerationBands_lookback <- acceleration_bands_lookback <- function( + x, + cols, + timePeriod = 20, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_ACCBANDS_lookback, + as.integer(timePeriod) + ) +} #' @usage NULL #' @aliases acceleration_bands @@ -130,7 +149,7 @@ acceleration_bands.matrix <- function( acceleration_bands.plotly <- function( x, cols, - n = 20, + timePeriod = 20, na.bridge = FALSE, ## splice:optional-plotly:start color = "steelblue", @@ -164,7 +183,7 @@ acceleration_bands.plotly <- function( cols = rebuild_formula( names(constructed_series) ), - n = n, + timePeriod = timePeriod, na.bridge = TRUE ) @@ -177,7 +196,7 @@ acceleration_bands.plotly <- function( ## splice:plotly-assembly:start name <- label( "Acceleration Bands", - n + timePeriod ) traces <- list( @@ -235,7 +254,7 @@ acceleration_bands.plotly <- function( acceleration_bands.ggplot <- function( x, cols, - n = 20, + timePeriod = 20, na.bridge = FALSE, ## splice:optional-ggplot:start ## splice:optional-ggplot:end @@ -266,7 +285,7 @@ acceleration_bands.ggplot <- function( cols = rebuild_formula( names(constructed_series) ), - n = n, + timePeriod = timePeriod, na.bridge = TRUE ) @@ -288,7 +307,7 @@ acceleration_bands.ggplot <- function( y_lower = "LowerBand" ) ) - name <- label("ACCBANDS", n) + name <- label("ACCBANDS", timePeriod) ## splice:ggplot-assembly:end state <- .chart_state() diff --git a/R/ta_AD.R b/R/ta_AD.R index e0198b404..df8a4f373 100644 --- a/R/ta_AD.R +++ b/R/ta_AD.R @@ -1,17 +1,18 @@ #' @export -#' @family Volume Indicator +#' @family Volume Indicators #' #' @title Chaikin A/D Line #' @templateVar .title Chaikin A/D Line #' @templateVar .author Serkan Korkmaz #' @templateVar .fun chaikin_accumulation_distribution_line -#' @templateVar .family Volume Indicator -#' @templateVar .formula ~high+low+close+volume +#' @templateVar .family Volume Indicators +#' @templateVar .formula ~high + low + close + volume #' ## splice:documentation:start ## splice:documentation:end #' #' @template description +#' #' @template returns chaikin_accumulation_distribution_line <- function( x, @@ -29,6 +30,13 @@ chaikin_accumulation_distribution_line <- function( #' @aliases chaikin_accumulation_distribution_line AD <- chaikin_accumulation_distribution_line +#' @export +#' @usage NULL +#' @rdname chaikin_accumulation_distribution_line +#' +#' @aliases chaikin_accumulation_distribution_line +chaikinAccumulationDistributionLine <- chaikin_accumulation_distribution_line + #' @usage NULL #' @aliases chaikin_accumulation_distribution_line #' @@ -62,12 +70,10 @@ chaikin_accumulation_distribution_line.default <- function( ## return as data.frame x <- .Call( C_impl_ta_AD, - ## splice:call:start constructed_series[[1]], constructed_series[[2]], constructed_series[[3]], constructed_series[[4]], - ## splice:call:end as.logical(na.bridge) ) @@ -116,6 +122,17 @@ chaikin_accumulation_distribution_line.matrix <- function( ) } +#' @usage NULL +AD_lookback <- chaikinAccumulationDistributionLine_lookback <- chaikin_accumulation_distribution_line_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_AD_lookback + ) +} #' @usage NULL #' @aliases chaikin_accumulation_distribution_line @@ -199,7 +216,8 @@ chaikin_accumulation_distribution_line.plotly <- function( } ), data = constructed_indicator[, values_to_extract, drop = FALSE], - values_to_extract = values_to_extract + values_to_extract = values_to_extract, + name = get0(x = "name", ifnotfound = NULL) ) state <- .chart_state() @@ -216,9 +234,9 @@ chaikin_accumulation_distribution_line.ggplot <- function( x, cols, na.bridge = FALSE, + title, ## splice:optional-ggplot:start ## splice:optional-ggplot:end - title, ... ) { ## check ggplot2 availability diff --git a/R/ta_ADOSC.R b/R/ta_ADOSC.R index 953c06a71..74c7d8694 100644 --- a/R/ta_ADOSC.R +++ b/R/ta_ADOSC.R @@ -1,25 +1,25 @@ #' @export -#' @family Volume Indicator +#' @family Volume Indicators #' #' @title Chaikin A/D Oscillator #' @templateVar .title Chaikin A/D Oscillator #' @templateVar .author Serkan Korkmaz #' @templateVar .fun chaikin_accumulation_distribution_oscillator -#' @templateVar .family Volume Indicator -#' @templateVar .formula ~high+low+close+volume +#' @templateVar .family Volume Indicators +#' @templateVar .formula ~high + low + close + volume #' ## splice:documentation:start -#' @param fast ([integer]). Period for the fast Moving Average (MA). -#' @param slow ([integer]). Period for the slow Moving Average (MA). ## splice:documentation:end #' #' @template description +#' @param fastPeriod ([integer]). Number of period for the fast MA. Defaults to `3`. +#' @param slowPeriod ([integer]). Number of period for the slow MA. Defaults to `10`. #' @template returns chaikin_accumulation_distribution_oscillator <- function( x, cols, - fast = 3, - slow = 10, + fastPeriod = 3, + slowPeriod = 10, na.bridge = FALSE, ... ) { @@ -33,6 +33,13 @@ chaikin_accumulation_distribution_oscillator <- function( #' @aliases chaikin_accumulation_distribution_oscillator ADOSC <- chaikin_accumulation_distribution_oscillator +#' @export +#' @usage NULL +#' @rdname chaikin_accumulation_distribution_oscillator +#' +#' @aliases chaikin_accumulation_distribution_oscillator +chaikinAccumulationDistributionOscillator <- chaikin_accumulation_distribution_oscillator + #' @usage NULL #' @aliases chaikin_accumulation_distribution_oscillator #' @@ -40,8 +47,8 @@ ADOSC <- chaikin_accumulation_distribution_oscillator chaikin_accumulation_distribution_oscillator.default <- function( x, cols, - fast = 3, - slow = 10, + fastPeriod = 3, + slowPeriod = 10, na.bridge = FALSE, ... ) { @@ -68,14 +75,12 @@ chaikin_accumulation_distribution_oscillator.default <- function( ## return as data.frame x <- .Call( C_impl_ta_ADOSC, - ## splice:call:start constructed_series[[1]], constructed_series[[2]], constructed_series[[3]], constructed_series[[4]], - as.integer(fast), - as.integer(slow), - ## splice:call:end + as.integer(fastPeriod), + as.integer(slowPeriod), as.logical(na.bridge) ) @@ -93,8 +98,8 @@ chaikin_accumulation_distribution_oscillator.default <- function( chaikin_accumulation_distribution_oscillator.data.frame <- function( x, cols, - fast = 3, - slow = 10, + fastPeriod = 3, + slowPeriod = 10, na.bridge = FALSE, ... ) { @@ -102,8 +107,8 @@ chaikin_accumulation_distribution_oscillator.data.frame <- function( chaikin_accumulation_distribution_oscillator.default( x = x, cols = cols, - fast = fast, - slow = slow, + fastPeriod = fastPeriod, + slowPeriod = slowPeriod, na.bridge = na.bridge, ... ) @@ -117,21 +122,36 @@ chaikin_accumulation_distribution_oscillator.data.frame <- function( chaikin_accumulation_distribution_oscillator.matrix <- function( x, cols, - fast = 3, - slow = 10, + fastPeriod = 3, + slowPeriod = 10, na.bridge = FALSE, ... ) { chaikin_accumulation_distribution_oscillator.default( x = x, cols = cols, - fast = fast, - slow = slow, + fastPeriod = fastPeriod, + slowPeriod = slowPeriod, na.bridge = na.bridge, ... ) } +#' @usage NULL +ADOSC_lookback <- chaikinAccumulationDistributionOscillator_lookback <- chaikin_accumulation_distribution_oscillator_lookback <- function( + x, + cols, + fastPeriod = 3, + slowPeriod = 10, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_ADOSC_lookback, + as.integer(fastPeriod), + as.integer(slowPeriod) + ) +} #' @usage NULL #' @aliases chaikin_accumulation_distribution_oscillator @@ -140,8 +160,8 @@ chaikin_accumulation_distribution_oscillator.matrix <- function( chaikin_accumulation_distribution_oscillator.plotly <- function( x, cols, - fast = 3, - slow = 10, + fastPeriod = 3, + slowPeriod = 10, na.bridge = FALSE, ## splice:optional-plotly:start ## splice:optional-plotly:end @@ -174,8 +194,8 @@ chaikin_accumulation_distribution_oscillator.plotly <- function( cols = rebuild_formula( names(constructed_series) ), - fast = fast, - slow = slow, + fastPeriod = fastPeriod, + slowPeriod = slowPeriod, na.bridge = TRUE ) @@ -192,7 +212,7 @@ chaikin_accumulation_distribution_oscillator.plotly <- function( ## construct {plotly}-object ## splice:plotly-assembly:start - name <- sprintf("ADOSC(%d, %d)", fast, slow) + name <- sprintf("ADOSC(%d, %d)", fastPeriod, slowPeriod) decorators <- list() traces <- list( list(y = ~ADOSC) @@ -219,7 +239,8 @@ chaikin_accumulation_distribution_oscillator.plotly <- function( } ), data = constructed_indicator[, values_to_extract, drop = FALSE], - values_to_extract = values_to_extract + values_to_extract = values_to_extract, + name = get0(x = "name", ifnotfound = NULL) ) state <- .chart_state() @@ -235,12 +256,12 @@ chaikin_accumulation_distribution_oscillator.plotly <- function( chaikin_accumulation_distribution_oscillator.ggplot <- function( x, cols, - fast = 3, - slow = 10, + fastPeriod = 3, + slowPeriod = 10, na.bridge = FALSE, + title, ## splice:optional-ggplot:start ## splice:optional-ggplot:end - title, ... ) { ## check ggplot2 availability @@ -268,8 +289,8 @@ chaikin_accumulation_distribution_oscillator.ggplot <- function( cols = rebuild_formula( names(constructed_series) ), - fast = fast, - slow = slow, + fastPeriod = fastPeriod, + slowPeriod = slowPeriod, na.bridge = TRUE ) @@ -290,7 +311,7 @@ chaikin_accumulation_distribution_oscillator.ggplot <- function( setdiff(colnames(constructed_indicator), "idx"), function(col) list(y = col) ) - name <- sprintf("ADOSC(%d, %d)", fast, slow) + name <- sprintf("ADOSC(%d, %d)", fastPeriod, slowPeriod) ## splice:ggplot-assembly:end ggplot_object <- add_last_value_gg( diff --git a/R/ta_ADX.R b/R/ta_ADX.R index 9e0b41026..83af497dc 100644 --- a/R/ta_ADX.R +++ b/R/ta_ADX.R @@ -1,22 +1,23 @@ #' @export -#' @family Momentum Indicator +#' @family Momentum Indicators #' #' @title Average Directional Movement Index #' @templateVar .title Average Directional Movement Index #' @templateVar .author Serkan Korkmaz #' @templateVar .fun average_directional_movement_index -#' @templateVar .family Momentum Indicator -#' @templateVar .formula ~ high + low + close +#' @templateVar .family Momentum Indicators +#' @templateVar .formula ~high + low + close #' ## splice:documentation:start ## splice:documentation:end #' #' @template description +#' #' @template returns average_directional_movement_index <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -30,6 +31,13 @@ average_directional_movement_index <- function( #' @aliases average_directional_movement_index ADX <- average_directional_movement_index +#' @export +#' @usage NULL +#' @rdname average_directional_movement_index +#' +#' @aliases average_directional_movement_index +averageDirectionalMovementIndex <- average_directional_movement_index + #' @usage NULL #' @aliases average_directional_movement_index #' @@ -37,7 +45,7 @@ ADX <- average_directional_movement_index average_directional_movement_index.default <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -64,12 +72,10 @@ average_directional_movement_index.default <- function( ## return as data.frame x <- .Call( C_impl_ta_ADX, - ## splice:call:start constructed_series[[1]], constructed_series[[2]], constructed_series[[3]], - as.integer(n), - ## splice:call:end + as.integer(timePeriod), as.logical(na.bridge) ) @@ -87,7 +93,7 @@ average_directional_movement_index.default <- function( average_directional_movement_index.data.frame <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -95,7 +101,7 @@ average_directional_movement_index.data.frame <- function( average_directional_movement_index.default( x = x, cols = cols, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge, ... ) @@ -109,19 +115,32 @@ average_directional_movement_index.data.frame <- function( average_directional_movement_index.matrix <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { average_directional_movement_index.default( x = x, cols = cols, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge, ... ) } +#' @usage NULL +ADX_lookback <- averageDirectionalMovementIndex_lookback <- average_directional_movement_index_lookback <- function( + x, + cols, + timePeriod = 14, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_ADX_lookback, + as.integer(timePeriod) + ) +} #' @usage NULL #' @aliases average_directional_movement_index @@ -130,7 +149,7 @@ average_directional_movement_index.matrix <- function( average_directional_movement_index.plotly <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ## splice:optional-plotly:start lower_bound = 25, @@ -166,7 +185,7 @@ average_directional_movement_index.plotly <- function( cols = rebuild_formula( names(constructed_series) ), - n = n, + timePeriod = timePeriod, na.bridge = TRUE ) @@ -185,7 +204,7 @@ average_directional_movement_index.plotly <- function( ## splice:plotly-assembly:start name <- sprintf( "ADX(%d)", - n + timePeriod ) decorators <- list( @@ -220,7 +239,8 @@ average_directional_movement_index.plotly <- function( } ), data = constructed_indicator[, values_to_extract, drop = FALSE], - values_to_extract = values_to_extract + values_to_extract = values_to_extract, + name = get0(x = "name", ifnotfound = NULL) ) state <- .chart_state() @@ -236,11 +256,11 @@ average_directional_movement_index.plotly <- function( average_directional_movement_index.ggplot <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, + title, ## splice:optional-ggplot:start ## splice:optional-ggplot:end - title, ... ) { ## check ggplot2 availability @@ -268,7 +288,7 @@ average_directional_movement_index.ggplot <- function( cols = rebuild_formula( names(constructed_series) ), - n = n, + timePeriod = timePeriod, na.bridge = TRUE ) @@ -294,7 +314,7 @@ average_directional_movement_index.ggplot <- function( ggplot_line(75), list(y = "ADX") ) - name <- sprintf("ADX(%d)", n) + name <- sprintf("ADX(%d)", timePeriod) ## splice:ggplot-assembly:end ggplot_object <- add_last_value_gg( diff --git a/R/ta_ADXR.R b/R/ta_ADXR.R index 1022b36c4..df7790c60 100644 --- a/R/ta_ADXR.R +++ b/R/ta_ADXR.R @@ -1,22 +1,23 @@ #' @export -#' @family Momentum Indicator +#' @family Momentum Indicators #' #' @title Average Directional Movement Index Rating #' @templateVar .title Average Directional Movement Index Rating #' @templateVar .author Serkan Korkmaz #' @templateVar .fun average_directional_movement_index_rating -#' @templateVar .family Momentum Indicator -#' @templateVar .formula ~ high + low + close +#' @templateVar .family Momentum Indicators +#' @templateVar .formula ~high + low + close #' ## splice:documentation:start ## splice:documentation:end #' #' @template description +#' #' @template returns average_directional_movement_index_rating <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -30,6 +31,13 @@ average_directional_movement_index_rating <- function( #' @aliases average_directional_movement_index_rating ADXR <- average_directional_movement_index_rating +#' @export +#' @usage NULL +#' @rdname average_directional_movement_index_rating +#' +#' @aliases average_directional_movement_index_rating +averageDirectionalMovementIndexRating <- average_directional_movement_index_rating + #' @usage NULL #' @aliases average_directional_movement_index_rating #' @@ -37,7 +45,7 @@ ADXR <- average_directional_movement_index_rating average_directional_movement_index_rating.default <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -64,12 +72,10 @@ average_directional_movement_index_rating.default <- function( ## return as data.frame x <- .Call( C_impl_ta_ADXR, - ## splice:call:start constructed_series[[1]], constructed_series[[2]], constructed_series[[3]], - as.integer(n), - ## splice:call:end + as.integer(timePeriod), as.logical(na.bridge) ) @@ -87,7 +93,7 @@ average_directional_movement_index_rating.default <- function( average_directional_movement_index_rating.data.frame <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -95,7 +101,7 @@ average_directional_movement_index_rating.data.frame <- function( average_directional_movement_index_rating.default( x = x, cols = cols, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge, ... ) @@ -109,19 +115,32 @@ average_directional_movement_index_rating.data.frame <- function( average_directional_movement_index_rating.matrix <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { average_directional_movement_index_rating.default( x = x, cols = cols, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge, ... ) } +#' @usage NULL +ADXR_lookback <- averageDirectionalMovementIndexRating_lookback <- average_directional_movement_index_rating_lookback <- function( + x, + cols, + timePeriod = 14, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_ADXR_lookback, + as.integer(timePeriod) + ) +} #' @usage NULL #' @aliases average_directional_movement_index_rating @@ -130,7 +149,7 @@ average_directional_movement_index_rating.matrix <- function( average_directional_movement_index_rating.plotly <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ## splice:optional-plotly:start lower_bound = 25, @@ -166,7 +185,7 @@ average_directional_movement_index_rating.plotly <- function( cols = rebuild_formula( names(constructed_series) ), - n = n, + timePeriod = timePeriod, na.bridge = TRUE ) @@ -185,7 +204,7 @@ average_directional_movement_index_rating.plotly <- function( ## splice:plotly-assembly:start name <- sprintf( "ADXR(%d)", - n + timePeriod ) decorators <- list( @@ -220,7 +239,8 @@ average_directional_movement_index_rating.plotly <- function( } ), data = constructed_indicator[, values_to_extract, drop = FALSE], - values_to_extract = values_to_extract + values_to_extract = values_to_extract, + name = get0(x = "name", ifnotfound = NULL) ) state <- .chart_state() @@ -236,11 +256,11 @@ average_directional_movement_index_rating.plotly <- function( average_directional_movement_index_rating.ggplot <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, + title, ## splice:optional-ggplot:start ## splice:optional-ggplot:end - title, ... ) { ## check ggplot2 availability @@ -268,7 +288,7 @@ average_directional_movement_index_rating.ggplot <- function( cols = rebuild_formula( names(constructed_series) ), - n = n, + timePeriod = timePeriod, na.bridge = TRUE ) @@ -294,7 +314,7 @@ average_directional_movement_index_rating.ggplot <- function( ggplot_line(75), list(y = "ADXR") ) - name <- sprintf("ADXR(%d)", n) + name <- sprintf("ADXR(%d)", timePeriod) ## splice:ggplot-assembly:end ggplot_object <- add_last_value_gg( diff --git a/R/ta_APO.R b/R/ta_APO.R index 907ac26ed..7ea62dded 100644 --- a/R/ta_APO.R +++ b/R/ta_APO.R @@ -1,27 +1,27 @@ #' @export -#' @family Momentum Indicator +#' @family Momentum Indicators #' #' @title Absolute Price Oscillator #' @templateVar .title Absolute Price Oscillator #' @templateVar .author Serkan Korkmaz #' @templateVar .fun absolute_price_oscillator -#' @templateVar .family Momentum Indicator +#' @templateVar .family Momentum Indicators #' @templateVar .formula ~close #' ## splice:documentation:start -#' @param fast ([integer]). Period for the fast Moving Average (MA). -#' @param slow ([integer]). Period for the slow Moving Average (MA). -#' @param ma ([list]). The type of Moving Average (MA) used for the `fast` and `slow` MA. [SMA] by default. ## splice:documentation:end #' #' @template description +#' @param fastPeriod ([integer]). Number of period for the fast MA. Defaults to `12`. +#' @param slowPeriod ([integer]). Number of period for the slow MA. Defaults to `26`. +#' @param maType ([integer]). Type of Moving Average. Defaults to `0` ([SMA]). Can also be passed as talib::SMA. #' @template returns absolute_price_oscillator <- function( x, cols, - fast = 12, - slow = 26, - ma = SMA(n = 9), + fastPeriod = 12, + slowPeriod = 26, + maType = 0, na.bridge = FALSE, ... ) { @@ -35,6 +35,13 @@ absolute_price_oscillator <- function( #' @aliases absolute_price_oscillator APO <- absolute_price_oscillator +#' @export +#' @usage NULL +#' @rdname absolute_price_oscillator +#' +#' @aliases absolute_price_oscillator +absolutePriceOscillator <- absolute_price_oscillator + #' @usage NULL #' @aliases absolute_price_oscillator #' @@ -42,9 +49,9 @@ APO <- absolute_price_oscillator absolute_price_oscillator.default <- function( x, cols, - fast = 12, - slow = 26, - ma = SMA(n = 9), + fastPeriod = 12, + slowPeriod = 26, + maType = 0, na.bridge = FALSE, ... ) { @@ -71,12 +78,10 @@ absolute_price_oscillator.default <- function( ## return as data.frame x <- .Call( C_impl_ta_APO, - ## splice:call:start constructed_series[[1]], - as.integer(fast), - as.integer(slow), - ma$maType, - ## splice:call:end + as.integer(fastPeriod), + as.integer(slowPeriod), + as.maType(maType), as.logical(na.bridge) ) @@ -94,9 +99,9 @@ absolute_price_oscillator.default <- function( absolute_price_oscillator.data.frame <- function( x, cols, - fast = 12, - slow = 26, - ma = SMA(n = 9), + fastPeriod = 12, + slowPeriod = 26, + maType = 0, na.bridge = FALSE, ... ) { @@ -104,9 +109,9 @@ absolute_price_oscillator.data.frame <- function( absolute_price_oscillator.default( x = x, cols = cols, - fast = fast, - slow = slow, - ma = ma, + fastPeriod = fastPeriod, + slowPeriod = slowPeriod, + maType = maType, na.bridge = na.bridge, ... ) @@ -120,23 +125,40 @@ absolute_price_oscillator.data.frame <- function( absolute_price_oscillator.matrix <- function( x, cols, - fast = 12, - slow = 26, - ma = SMA(n = 9), + fastPeriod = 12, + slowPeriod = 26, + maType = 0, na.bridge = FALSE, ... ) { absolute_price_oscillator.default( x = x, cols = cols, - fast = fast, - slow = slow, - ma = ma, + fastPeriod = fastPeriod, + slowPeriod = slowPeriod, + maType = maType, na.bridge = na.bridge, ... ) } +#' @usage NULL +APO_lookback <- absolutePriceOscillator_lookback <- absolute_price_oscillator_lookback <- function( + x, + cols, + fastPeriod = 12, + slowPeriod = 26, + maType = 0, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_APO_lookback, + as.integer(fastPeriod), + as.integer(slowPeriod), + as.maType(maType) + ) +} #' @usage NULL #' @aliases absolute_price_oscillator @@ -145,9 +167,9 @@ absolute_price_oscillator.matrix <- function( absolute_price_oscillator.numeric <- function( x, cols, - fast = 12, - slow = 26, - ma = SMA(n = 9), + fastPeriod = 12, + slowPeriod = 26, + maType = 0, na.bridge = FALSE, ... ) { @@ -163,31 +185,20 @@ absolute_price_oscillator.numeric <- function( ## to 'C' x <- .Call( C_impl_ta_APO, - ## splice:numeric:start as.double(x), - as.integer(fast), - as.integer(slow), - ma$maType, - ## splice:numeric:end + as.integer(fastPeriod), + as.integer(slowPeriod), + as.maType(maType), 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 #' @aliases absolute_price_oscillator #' @@ -195,9 +206,9 @@ absolute_price_oscillator.numeric <- function( absolute_price_oscillator.plotly <- function( x, cols, - fast = 12, - slow = 26, - ma = SMA(n = 9), + fastPeriod = 12, + slowPeriod = 26, + maType = 0, na.bridge = FALSE, ## splice:optional-plotly:start ## splice:optional-plotly:end @@ -230,9 +241,9 @@ absolute_price_oscillator.plotly <- function( cols = rebuild_formula( names(constructed_series) ), - fast = fast, - slow = slow, - ma = ma, + fastPeriod = fastPeriod, + slowPeriod = slowPeriod, + maType = maType, na.bridge = TRUE ) @@ -251,8 +262,8 @@ absolute_price_oscillator.plotly <- function( ## splice:plotly-assembly:start name <- sprintf( "APO(%d, %d)", - slow, - fast + slowPeriod, + fastPeriod ) decorators <- list() @@ -283,7 +294,8 @@ absolute_price_oscillator.plotly <- function( } ), data = constructed_indicator[, values_to_extract, drop = FALSE], - values_to_extract = values_to_extract + values_to_extract = values_to_extract, + name = get0(x = "name", ifnotfound = NULL) ) state <- .chart_state() @@ -299,13 +311,13 @@ absolute_price_oscillator.plotly <- function( absolute_price_oscillator.ggplot <- function( x, cols, - fast = 12, - slow = 26, - ma = SMA(n = 9), + fastPeriod = 12, + slowPeriod = 26, + maType = 0, na.bridge = FALSE, + title, ## splice:optional-ggplot:start ## splice:optional-ggplot:end - title, ... ) { ## check ggplot2 availability @@ -333,9 +345,9 @@ absolute_price_oscillator.ggplot <- function( cols = rebuild_formula( names(constructed_series) ), - fast = fast, - slow = slow, - ma = ma, + fastPeriod = fastPeriod, + slowPeriod = slowPeriod, + maType = maType, na.bridge = TRUE ) @@ -356,7 +368,7 @@ absolute_price_oscillator.ggplot <- function( ggplot_line(0), list(y = "APO") ) - name <- sprintf("APO(%d, %d)", slow, fast) + name <- sprintf("APO(%d, %d)", slowPeriod, fastPeriod) ## splice:ggplot-assembly:end ggplot_object <- add_last_value_gg( diff --git a/R/ta_AROON.R b/R/ta_AROON.R index 0cedc7c0f..e9cbb8da1 100644 --- a/R/ta_AROON.R +++ b/R/ta_AROON.R @@ -1,22 +1,23 @@ #' @export -#' @family Momentum Indicator +#' @family Momentum Indicators #' #' @title Aroon #' @templateVar .title Aroon #' @templateVar .author Serkan Korkmaz #' @templateVar .fun aroon -#' @templateVar .family Momentum Indicator -#' @templateVar .formula ~ high + low +#' @templateVar .family Momentum Indicators +#' @templateVar .formula ~high + low #' ## splice:documentation:start ## splice:documentation:end #' #' @template description +#' #' @template returns aroon <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -37,7 +38,7 @@ AROON <- aroon aroon.default <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -64,11 +65,9 @@ aroon.default <- function( ## return as data.frame x <- .Call( C_impl_ta_AROON, - ## splice:call:start constructed_series[[1]], constructed_series[[2]], - as.integer(n), - ## splice:call:end + as.integer(timePeriod), as.logical(na.bridge) ) @@ -86,7 +85,7 @@ aroon.default <- function( aroon.data.frame <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -94,7 +93,7 @@ aroon.data.frame <- function( aroon.default( x = x, cols = cols, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge, ... ) @@ -108,19 +107,32 @@ aroon.data.frame <- function( aroon.matrix <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { aroon.default( x = x, cols = cols, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge, ... ) } +#' @usage NULL +AROON_lookback <- aroon_lookback <- function( + x, + cols, + timePeriod = 14, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_AROON_lookback, + as.integer(timePeriod) + ) +} #' @usage NULL #' @aliases aroon @@ -129,7 +141,7 @@ aroon.matrix <- function( aroon.plotly <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ## splice:optional-plotly:start ## splice:optional-plotly:end @@ -162,7 +174,7 @@ aroon.plotly <- function( cols = rebuild_formula( names(constructed_series) ), - n = n, + timePeriod = timePeriod, na.bridge = TRUE ) @@ -181,7 +193,7 @@ aroon.plotly <- function( ## splice:plotly-assembly:start name <- sprintf( "Aroon(%d)", - n + timePeriod ) decorators <- list( @@ -225,7 +237,8 @@ aroon.plotly <- function( } ), data = constructed_indicator[, values_to_extract, drop = FALSE], - values_to_extract = values_to_extract + values_to_extract = values_to_extract, + name = get0(x = "name", ifnotfound = NULL) ) state <- .chart_state() @@ -241,11 +254,11 @@ aroon.plotly <- function( aroon.ggplot <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, + title, ## splice:optional-ggplot:start ## splice:optional-ggplot:end - title, ... ) { ## check ggplot2 availability @@ -273,7 +286,7 @@ aroon.ggplot <- function( cols = rebuild_formula( names(constructed_series) ), - n = n, + timePeriod = timePeriod, na.bridge = TRUE ) @@ -297,7 +310,7 @@ aroon.ggplot <- function( list(y = "AroonDown", name = "AroonDown"), list(y = "AroonUp", name = "AroonUp") ) - name <- sprintf("Aroon(%d)", n) + name <- sprintf("Aroon(%d)", timePeriod) ## splice:ggplot-assembly:end ggplot_object <- add_last_value_gg( diff --git a/R/ta_AROONOSC.R b/R/ta_AROONOSC.R index 81452a9d0..e1c68b01a 100644 --- a/R/ta_AROONOSC.R +++ b/R/ta_AROONOSC.R @@ -1,22 +1,23 @@ #' @export -#' @family Momentum Indicator +#' @family Momentum Indicators #' #' @title Aroon Oscillator #' @templateVar .title Aroon Oscillator #' @templateVar .author Serkan Korkmaz #' @templateVar .fun aroon_oscillator -#' @templateVar .family Momentum Indicator -#' @templateVar .formula ~ high + low +#' @templateVar .family Momentum Indicators +#' @templateVar .formula ~high + low #' ## splice:documentation:start ## splice:documentation:end #' #' @template description +#' #' @template returns aroon_oscillator <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -30,6 +31,13 @@ aroon_oscillator <- function( #' @aliases aroon_oscillator AROONOSC <- aroon_oscillator +#' @export +#' @usage NULL +#' @rdname aroon_oscillator +#' +#' @aliases aroon_oscillator +aroonOscillator <- aroon_oscillator + #' @usage NULL #' @aliases aroon_oscillator #' @@ -37,7 +45,7 @@ AROONOSC <- aroon_oscillator aroon_oscillator.default <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -64,11 +72,9 @@ aroon_oscillator.default <- function( ## return as data.frame x <- .Call( C_impl_ta_AROONOSC, - ## splice:call:start constructed_series[[1]], constructed_series[[2]], - as.integer(n), - ## splice:call:end + as.integer(timePeriod), as.logical(na.bridge) ) @@ -86,7 +92,7 @@ aroon_oscillator.default <- function( aroon_oscillator.data.frame <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -94,7 +100,7 @@ aroon_oscillator.data.frame <- function( aroon_oscillator.default( x = x, cols = cols, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge, ... ) @@ -108,19 +114,32 @@ aroon_oscillator.data.frame <- function( aroon_oscillator.matrix <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { aroon_oscillator.default( x = x, cols = cols, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge, ... ) } +#' @usage NULL +AROONOSC_lookback <- aroonOscillator_lookback <- aroon_oscillator_lookback <- function( + x, + cols, + timePeriod = 14, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_AROONOSC_lookback, + as.integer(timePeriod) + ) +} #' @usage NULL #' @aliases aroon_oscillator @@ -129,7 +148,7 @@ aroon_oscillator.matrix <- function( aroon_oscillator.plotly <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ## splice:optional-plotly:start ## splice:optional-plotly:end @@ -162,7 +181,7 @@ aroon_oscillator.plotly <- function( cols = rebuild_formula( names(constructed_series) ), - n = n, + timePeriod = timePeriod, na.bridge = TRUE ) @@ -179,7 +198,7 @@ aroon_oscillator.plotly <- function( ## construct {plotly}-object ## splice:plotly-assembly:start - name <- sprintf("AroonOsc(%d)", n) + name <- sprintf("AroonOsc(%d)", timePeriod) decorators <- list( function(p) add_limit_ly(p, y_range = c(0, 100)) @@ -211,7 +230,8 @@ aroon_oscillator.plotly <- function( } ), data = constructed_indicator[, values_to_extract, drop = FALSE], - values_to_extract = values_to_extract + values_to_extract = values_to_extract, + name = get0(x = "name", ifnotfound = NULL) ) state <- .chart_state() @@ -227,11 +247,11 @@ aroon_oscillator.plotly <- function( aroon_oscillator.ggplot <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, + title, ## splice:optional-ggplot:start ## splice:optional-ggplot:end - title, ... ) { ## check ggplot2 availability @@ -259,7 +279,7 @@ aroon_oscillator.ggplot <- function( cols = rebuild_formula( names(constructed_series) ), - n = n, + timePeriod = timePeriod, na.bridge = TRUE ) @@ -283,7 +303,7 @@ aroon_oscillator.ggplot <- function( ggplot_line(0), list(y = "AROONOSC") ) - name <- sprintf("AroonOsc(%d)", n) + name <- sprintf("AroonOsc(%d)", timePeriod) ## splice:ggplot-assembly:end ggplot_object <- add_last_value_gg( diff --git a/R/ta_ATR.R b/R/ta_ATR.R index 9c1dbbd60..f0566f42e 100644 --- a/R/ta_ATR.R +++ b/R/ta_ATR.R @@ -1,22 +1,23 @@ #' @export -#' @family Volatility Indicator +#' @family Volatility Indicators #' #' @title Average True Range #' @templateVar .title Average True Range #' @templateVar .author Serkan Korkmaz #' @templateVar .fun average_true_range -#' @templateVar .family Volatility Indicator +#' @templateVar .family Volatility Indicators #' @templateVar .formula ~high + low + close #' ## splice:documentation:start ## splice:documentation:end #' #' @template description +#' #' @template returns average_true_range <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -30,6 +31,13 @@ average_true_range <- function( #' @aliases average_true_range ATR <- average_true_range +#' @export +#' @usage NULL +#' @rdname average_true_range +#' +#' @aliases average_true_range +averageTrueRange <- average_true_range + #' @usage NULL #' @aliases average_true_range #' @@ -37,7 +45,7 @@ ATR <- average_true_range average_true_range.default <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -64,12 +72,10 @@ average_true_range.default <- function( ## return as data.frame x <- .Call( C_impl_ta_ATR, - ## splice:call:start constructed_series[[1]], constructed_series[[2]], constructed_series[[3]], - as.integer(n), - ## splice:call:end + as.integer(timePeriod), as.logical(na.bridge) ) @@ -87,7 +93,7 @@ average_true_range.default <- function( average_true_range.data.frame <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -95,7 +101,7 @@ average_true_range.data.frame <- function( average_true_range.default( x = x, cols = cols, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge, ... ) @@ -109,19 +115,32 @@ average_true_range.data.frame <- function( average_true_range.matrix <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { average_true_range.default( x = x, cols = cols, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge, ... ) } +#' @usage NULL +ATR_lookback <- averageTrueRange_lookback <- average_true_range_lookback <- function( + x, + cols, + timePeriod = 14, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_ATR_lookback, + as.integer(timePeriod) + ) +} #' @usage NULL #' @aliases average_true_range @@ -130,7 +149,7 @@ average_true_range.matrix <- function( average_true_range.plotly <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ## splice:optional-plotly:start ## splice:optional-plotly:end @@ -163,7 +182,7 @@ average_true_range.plotly <- function( cols = rebuild_formula( names(constructed_series) ), - n = n, + timePeriod = timePeriod, na.bridge = TRUE ) @@ -180,7 +199,7 @@ average_true_range.plotly <- function( ## construct {plotly}-object ## splice:plotly-assembly:start - name <- sprintf("ATR(%d)", n) + name <- sprintf("ATR(%d)", timePeriod) decorators <- list() traces <- list( list(y = ~ATR) @@ -207,7 +226,8 @@ average_true_range.plotly <- function( } ), data = constructed_indicator[, values_to_extract, drop = FALSE], - values_to_extract = values_to_extract + values_to_extract = values_to_extract, + name = get0(x = "name", ifnotfound = NULL) ) state <- .chart_state() @@ -223,11 +243,11 @@ average_true_range.plotly <- function( average_true_range.ggplot <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, + title, ## splice:optional-ggplot:start ## splice:optional-ggplot:end - title, ... ) { ## check ggplot2 availability @@ -255,7 +275,7 @@ average_true_range.ggplot <- function( cols = rebuild_formula( names(constructed_series) ), - n = n, + timePeriod = timePeriod, na.bridge = TRUE ) @@ -276,7 +296,7 @@ average_true_range.ggplot <- function( setdiff(colnames(constructed_indicator), "idx"), function(col) list(y = col) ) - name <- sprintf("ATR(%d)", n) + name <- sprintf("ATR(%d)", timePeriod) ## splice:ggplot-assembly:end ggplot_object <- add_last_value_gg( diff --git a/R/ta_AVGDEV.R b/R/ta_AVGDEV.R new file mode 100644 index 000000000..eefd4249a --- /dev/null +++ b/R/ta_AVGDEV.R @@ -0,0 +1,176 @@ +#' @export +#' @family Price Transform +#' +#' @title Average Deviation +#' @templateVar .title Average Deviation +#' @templateVar .author Serkan Korkmaz +#' @templateVar .fun average_deviation +#' @templateVar .family Price Transform +#' @templateVar .formula ~close +#' +## splice:documentation:start +## splice:documentation:end +#' +#' @template description +#' +#' @template returns +average_deviation <- function( + x, + cols, + timePeriod = 14, + na.bridge = FALSE, + ... +) { + UseMethod("average_deviation") +} + +#' @export +#' @usage NULL +#' @rdname average_deviation +#' +#' @aliases average_deviation +AVGDEV <- average_deviation + +#' @export +#' @usage NULL +#' @rdname average_deviation +#' +#' @aliases average_deviation +averageDeviation <- average_deviation + +#' @usage NULL +#' @aliases average_deviation +#' +#' @export +average_deviation.default <- function( + x, + cols, + timePeriod = 14, + na.bridge = FALSE, + ... +) { + ## 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, + ... + ) + + ## extract rownames + ## for later attachment + x_names <- rownames(constructed_series) + + ## calculate indicator and + ## return as data.frame + x <- .Call( + C_impl_ta_AVGDEV, + constructed_series[[1]], + as.integer(timePeriod), + as.logical(na.bridge) + ) + + ## readd rownames + set_rownames(x, x_names) + + ## return indicator + x +} + +#' @usage NULL +#' @aliases average_deviation +#' +#' @export +average_deviation.data.frame <- function( + x, + cols, + timePeriod = 14, + na.bridge = FALSE, + ... +) { + map_dfr( + average_deviation.default( + x = x, + cols = cols, + timePeriod = timePeriod, + na.bridge = na.bridge, + ... + ) + ) +} + +#' @usage NULL +#' @aliases average_deviation +#' +#' @export +average_deviation.matrix <- function( + x, + cols, + timePeriod = 14, + na.bridge = FALSE, + ... +) { + average_deviation.default( + x = x, + cols = cols, + timePeriod = timePeriod, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +AVGDEV_lookback <- averageDeviation_lookback <- average_deviation_lookback <- function( + x, + cols, + timePeriod = 14, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_AVGDEV_lookback, + as.integer(timePeriod) + ) +} + +#' @usage NULL +#' @aliases average_deviation +#' +#' @export +average_deviation.numeric <- function( + x, + cols, + timePeriod = 14, + na.bridge = FALSE, + ... +) { + ## warn if 'cols' have been + ## passed just to make sure + ## the user knows its not possible + ## or relevant + if (!missing(cols)) { + warning("'cols' is passed but is unused for vectors.") + } + + ## pass the argument directly + ## to 'C' + x <- .Call( + C_impl_ta_AVGDEV, + as.double(x), + as.integer(timePeriod), + as.logical(na.bridge) + ) + + if (dim(x)[2] == 1L) { + dim(x) <- NULL + } + + x +} diff --git a/R/ta_AVGPRICE.R b/R/ta_AVGPRICE.R index 666fd0c66..17162dc7a 100644 --- a/R/ta_AVGPRICE.R +++ b/R/ta_AVGPRICE.R @@ -12,6 +12,7 @@ ## splice:documentation:end #' #' @template description +#' #' @template returns average_price <- function( x, @@ -29,6 +30,13 @@ average_price <- function( #' @aliases average_price AVGPRICE <- average_price +#' @export +#' @usage NULL +#' @rdname average_price +#' +#' @aliases average_price +averagePrice <- average_price + #' @usage NULL #' @aliases average_price #' @@ -62,12 +70,10 @@ average_price.default <- function( ## return as data.frame x <- .Call( C_impl_ta_AVGPRICE, - ## splice:call:start constructed_series[[1]], constructed_series[[2]], constructed_series[[3]], constructed_series[[4]], - ## splice:call:end as.logical(na.bridge) ) @@ -115,3 +121,15 @@ average_price.matrix <- function( ... ) } + +#' @usage NULL +AVGPRICE_lookback <- averagePrice_lookback <- average_price_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_AVGPRICE_lookback + ) +} diff --git a/R/ta_BBANDS.R b/R/ta_BBANDS.R index a02d74e4c..b8b7a067e 100644 --- a/R/ta_BBANDS.R +++ b/R/ta_BBANDS.R @@ -1,29 +1,28 @@ #' @export -#' @family Overlap Study +#' @family Overlap Studies #' #' @title Bollinger Bands #' @templateVar .title Bollinger Bands #' @templateVar .author Serkan Korkmaz #' @templateVar .fun bollinger_bands -#' @templateVar .family Overlap Study +#' @templateVar .family Overlap Studies #' @templateVar .formula ~close #' ## splice:documentation:start -#' @param ma ([list]). The type of Moving Average (MA) used for the `MiddleBand`. [SMA] by default. -#' @param sd ([double]). Deviation multiplier for the upper and lower band. -#' @param sd_up ([double]). Optional. Deviation multiplier for upper band -#' @param sd_down ([double]). Optional. Deviation multiplier for lower band ## splice:documentation:end #' #' @template description +#' @param deviationsUp ([double]). Deviation multiplier for upper band. Defaults to `2`. +#' @param deviationsDown ([double]). Deviation multiplier for lower band. Defaults to `2`. +#' @param maType ([integer]). Type of Moving Average. Defaults to `0` ([SMA]). Can also be passed as talib::SMA. #' @template returns bollinger_bands <- function( x, cols, - ma = SMA(n = 5), - sd = 2, - sd_down, - sd_up, + timePeriod = 5, + deviationsUp = 2, + deviationsDown = 2, + maType = 0, na.bridge = FALSE, ... ) { @@ -37,6 +36,13 @@ bollinger_bands <- function( #' @aliases bollinger_bands BBANDS <- bollinger_bands +#' @export +#' @usage NULL +#' @rdname bollinger_bands +#' +#' @aliases bollinger_bands +bollingerBands <- bollinger_bands + #' @usage NULL #' @aliases bollinger_bands #' @@ -44,10 +50,10 @@ BBANDS <- bollinger_bands bollinger_bands.default <- function( x, cols, - ma = SMA(n = 5), - sd = 2, - sd_down, - sd_up, + timePeriod = 5, + deviationsUp = 2, + deviationsDown = 2, + maType = 0, na.bridge = FALSE, ... ) { @@ -74,13 +80,11 @@ bollinger_bands.default <- function( ## return as data.frame x <- .Call( C_impl_ta_BBANDS, - ## splice:call:start constructed_series[[1]], - ma$n, - as.double(sd_up %or% sd), - as.double(sd_down %or% sd), - ma$maType, - ## splice:call:end + as.integer(timePeriod), + as.double(deviationsUp), + as.double(deviationsDown), + as.maType(maType), as.logical(na.bridge) ) @@ -98,10 +102,10 @@ bollinger_bands.default <- function( bollinger_bands.data.frame <- function( x, cols, - ma = SMA(n = 5), - sd = 2, - sd_down, - sd_up, + timePeriod = 5, + deviationsUp = 2, + deviationsDown = 2, + maType = 0, na.bridge = FALSE, ... ) { @@ -109,10 +113,10 @@ bollinger_bands.data.frame <- function( bollinger_bands.default( x = x, cols = cols, - ma = ma, - sd = sd, - sd_down = sd_down, - sd_up = sd_up, + timePeriod = timePeriod, + deviationsUp = deviationsUp, + deviationsDown = deviationsDown, + maType = maType, na.bridge = na.bridge, ... ) @@ -126,25 +130,44 @@ bollinger_bands.data.frame <- function( bollinger_bands.matrix <- function( x, cols, - ma = SMA(n = 5), - sd = 2, - sd_down, - sd_up, + timePeriod = 5, + deviationsUp = 2, + deviationsDown = 2, + maType = 0, na.bridge = FALSE, ... ) { bollinger_bands.default( x = x, cols = cols, - ma = ma, - sd = sd, - sd_down = sd_down, - sd_up = sd_up, + timePeriod = timePeriod, + deviationsUp = deviationsUp, + deviationsDown = deviationsDown, + maType = maType, na.bridge = na.bridge, ... ) } +#' @usage NULL +BBANDS_lookback <- bollingerBands_lookback <- bollinger_bands_lookback <- function( + x, + cols, + timePeriod = 5, + deviationsUp = 2, + deviationsDown = 2, + maType = 0, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_BBANDS_lookback, + as.integer(timePeriod), + as.double(deviationsUp), + as.double(deviationsDown), + as.maType(maType) + ) +} #' @usage NULL #' @aliases bollinger_bands @@ -153,10 +176,10 @@ bollinger_bands.matrix <- function( bollinger_bands.numeric <- function( x, cols, - ma = SMA(n = 5), - sd = 2, - sd_down, - sd_up, + timePeriod = 5, + deviationsUp = 2, + deviationsDown = 2, + maType = 0, na.bridge = FALSE, ... ) { @@ -172,32 +195,21 @@ bollinger_bands.numeric <- function( ## to 'C' x <- .Call( C_impl_ta_BBANDS, - ## splice:numeric:start as.double(x), - ma$n, - as.double(sd_up %or% sd), - as.double(sd_down %or% sd), - ma$maType, - ## splice:numeric:end + as.integer(timePeriod), + as.double(deviationsUp), + as.double(deviationsDown), + as.maType(maType), 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 #' @aliases bollinger_bands #' @@ -205,10 +217,10 @@ bollinger_bands.numeric <- function( bollinger_bands.plotly <- function( x, cols, - ma = SMA(n = 5), - sd = 2, - sd_down, - sd_up, + timePeriod = 5, + deviationsUp = 2, + deviationsDown = 2, + maType = 0, na.bridge = FALSE, ## splice:optional-plotly:start color = "steelblue", @@ -242,10 +254,10 @@ bollinger_bands.plotly <- function( cols = rebuild_formula( names(constructed_series) ), - ma = ma, - sd = sd, - sd_down = sd_down, - sd_up = sd_up, + timePeriod = timePeriod, + deviationsUp = deviationsUp, + deviationsDown = deviationsDown, + maType = maType, na.bridge = TRUE ) @@ -258,19 +270,19 @@ bollinger_bands.plotly <- function( ## splice:plotly-assembly:start ## standard deviations - sd_down <- as.double(sd_down %or% sd) - sd_up <- as.double(sd_up %or% sd) + sd_down <- as.double(deviationsDown) + sd_up <- as.double(deviationsUp) if (sd_down == sd_up) { name <- label( "Bollinger Bands", - ma$n, + timePeriod, sd_up ) } else { name <- label( "Bollinger Bands", - ma$n, + timePeriod, sd_up, sd_down ) @@ -284,7 +296,17 @@ bollinger_bands.plotly <- function( ), list( y = ~MiddleBand, - name = sub("\\(.*$", "", input_name(substitute(ma)), perl = TRUE), + name = c( + "SMA", + "EMA", + "WMA", + "DEMA", + "TEMA", + "TRIMA", + "KAMA", + "MAMA", + "T3" + )[maType + 1], fill = "tonexty" ), list( @@ -330,10 +352,10 @@ bollinger_bands.plotly <- function( bollinger_bands.ggplot <- function( x, cols, - ma = SMA(n = 5), - sd = 2, - sd_down, - sd_up, + timePeriod = 5, + deviationsUp = 2, + deviationsDown = 2, + maType = 0, na.bridge = FALSE, ## splice:optional-ggplot:start ## splice:optional-ggplot:end @@ -364,10 +386,10 @@ bollinger_bands.ggplot <- function( cols = rebuild_formula( names(constructed_series) ), - ma = ma, - sd = sd, - sd_down = sd_down, - sd_up = sd_up, + timePeriod = timePeriod, + deviationsUp = deviationsUp, + deviationsDown = deviationsDown, + maType = maType, na.bridge = TRUE ) @@ -389,7 +411,7 @@ bollinger_bands.ggplot <- function( y_lower = "LowerBand" ) ) - name <- label("Bollinger Bands", ma$n, sd) + name <- label("Bollinger Bands", timePeriod, deviationsUp) ## splice:ggplot-assembly:end state <- .chart_state() diff --git a/R/ta_BETA.R b/R/ta_BETA.R index 78eec1b70..ad2bf57b9 100644 --- a/R/ta_BETA.R +++ b/R/ta_BETA.R @@ -1,8 +1,8 @@ #' @export -#' @family Rolling Statistic +#' @family Rolling Statistics #' -#' @title Rolling Beta -#' @templateVar .title Rolling Beta +#' @title Beta +#' @templateVar .title Beta #' @templateVar .author Serkan Korkmaz #' @templateVar .fun rolling_beta #' @@ -10,12 +10,14 @@ ## splice:documentation:end #' #' @template rolling_description +#' #' @template rolling_returns rolling_beta <- function( x, y, - n = 5, - na.bridge = FALSE + timePeriod = 5, + na.bridge = FALSE, + ... ) { UseMethod("rolling_beta") } @@ -27,6 +29,13 @@ rolling_beta <- function( #' @aliases rolling_beta BETA <- rolling_beta +#' @export +#' @usage NULL +#' @rdname rolling_beta +#' +#' @aliases rolling_beta +rollingBeta <- rolling_beta + #' @usage NULL #' @aliases rolling_beta #' @@ -34,8 +43,9 @@ BETA <- rolling_beta rolling_beta.default <- function( x, y, - n = 5, - na.bridge = FALSE + timePeriod = 5, + na.bridge = FALSE, + ... ) { ## calculate indicator and ## return as data.frame @@ -44,13 +54,18 @@ rolling_beta.default <- function( ## splice:call:start as.double(x), as.double(y), - as.integer(n), + as.integer(timePeriod), ## splice:call:end as.logical(na.bridge) ) + ## strip dimensions + ## while preserving + ## attributes + dim(x) <- NULL + ## return indicator - as.double(x) + x } #' @usage NULL @@ -60,18 +75,37 @@ rolling_beta.default <- function( rolling_beta.numeric <- function( x, y, - n = 5, - na.bridge = FALSE + timePeriod = 5, + na.bridge = FALSE, + ... ) { ## calculate indicator and ## return as data.frame x <- rolling_beta.default( x = x, y = y, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge ) + ## strip dimensions + ## while preserving + ## attributes + dim(x) <- NULL + ## return indicator - as.double(x) + x +} + +#' @usage NULL +BETA_lookback <- rollingBeta_lookback <- rolling_beta_lookback <- function( + x, + timePeriod = 5, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_BETA_lookback, + as.integer(timePeriod) + ) } diff --git a/R/ta_BOP.R b/R/ta_BOP.R index 2e313da83..01a6ff1fc 100644 --- a/R/ta_BOP.R +++ b/R/ta_BOP.R @@ -1,17 +1,18 @@ #' @export -#' @family Momentum Indicator +#' @family Momentum Indicators #' -#' @title Balance of Power -#' @templateVar .title Balance of Power +#' @title Balance Of Power +#' @templateVar .title Balance Of Power #' @templateVar .author Serkan Korkmaz #' @templateVar .fun balance_of_power -#' @templateVar .family Momentum Indicator -#' @templateVar .formula ~ open + high + low + close +#' @templateVar .family Momentum Indicators +#' @templateVar .formula ~open + high + low + close #' ## splice:documentation:start ## splice:documentation:end #' #' @template description +#' #' @template returns balance_of_power <- function( x, @@ -29,6 +30,13 @@ balance_of_power <- function( #' @aliases balance_of_power BOP <- balance_of_power +#' @export +#' @usage NULL +#' @rdname balance_of_power +#' +#' @aliases balance_of_power +balanceOfPower <- balance_of_power + #' @usage NULL #' @aliases balance_of_power #' @@ -62,12 +70,10 @@ balance_of_power.default <- function( ## return as data.frame x <- .Call( C_impl_ta_BOP, - ## splice:call:start constructed_series[[1]], constructed_series[[2]], constructed_series[[3]], constructed_series[[4]], - ## splice:call:end as.logical(na.bridge) ) @@ -116,6 +122,17 @@ balance_of_power.matrix <- function( ) } +#' @usage NULL +BOP_lookback <- balanceOfPower_lookback <- balance_of_power_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_BOP_lookback + ) +} #' @usage NULL #' @aliases balance_of_power @@ -204,13 +221,14 @@ balance_of_power.plotly <- function( ), data = constructed_indicator, title = if (missing(title)) { - "Balance of Power" + "Balance Of Power" } else { title } ), data = constructed_indicator[, values_to_extract, drop = FALSE], - values_to_extract = values_to_extract + values_to_extract = values_to_extract, + name = get0(x = "name", ifnotfound = NULL) ) state <- .chart_state() @@ -227,9 +245,9 @@ balance_of_power.ggplot <- function( x, cols, na.bridge = FALSE, + title, ## splice:optional-ggplot:start ## splice:optional-ggplot:end - title, ... ) { ## check ggplot2 availability @@ -296,7 +314,7 @@ balance_of_power.ggplot <- function( ), data = constructed_indicator, title = if (missing(title)) { - "Balance of Power" + "Balance Of Power" } else { title } diff --git a/R/ta_CCI.R b/R/ta_CCI.R index e4b93a9f3..1119c1a35 100644 --- a/R/ta_CCI.R +++ b/R/ta_CCI.R @@ -1,22 +1,23 @@ #' @export -#' @family Momentum Indicator +#' @family Momentum Indicators #' #' @title Commodity Channel Index #' @templateVar .title Commodity Channel Index #' @templateVar .author Serkan Korkmaz #' @templateVar .fun commodity_channel_index -#' @templateVar .family Momentum Indicator -#' @templateVar .formula ~ high + low + close +#' @templateVar .family Momentum Indicators +#' @templateVar .formula ~high + low + close #' ## splice:documentation:start ## splice:documentation:end #' #' @template description +#' #' @template returns commodity_channel_index <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -30,6 +31,13 @@ commodity_channel_index <- function( #' @aliases commodity_channel_index CCI <- commodity_channel_index +#' @export +#' @usage NULL +#' @rdname commodity_channel_index +#' +#' @aliases commodity_channel_index +commodityChannelIndex <- commodity_channel_index + #' @usage NULL #' @aliases commodity_channel_index #' @@ -37,7 +45,7 @@ CCI <- commodity_channel_index commodity_channel_index.default <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -64,12 +72,10 @@ commodity_channel_index.default <- function( ## return as data.frame x <- .Call( C_impl_ta_CCI, - ## splice:call:start constructed_series[[1]], constructed_series[[2]], constructed_series[[3]], - as.integer(n), - ## splice:call:end + as.integer(timePeriod), as.logical(na.bridge) ) @@ -87,7 +93,7 @@ commodity_channel_index.default <- function( commodity_channel_index.data.frame <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -95,7 +101,7 @@ commodity_channel_index.data.frame <- function( commodity_channel_index.default( x = x, cols = cols, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge, ... ) @@ -109,19 +115,32 @@ commodity_channel_index.data.frame <- function( commodity_channel_index.matrix <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { commodity_channel_index.default( x = x, cols = cols, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge, ... ) } +#' @usage NULL +CCI_lookback <- commodityChannelIndex_lookback <- commodity_channel_index_lookback <- function( + x, + cols, + timePeriod = 14, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CCI_lookback, + as.integer(timePeriod) + ) +} #' @usage NULL #' @aliases commodity_channel_index @@ -130,12 +149,13 @@ commodity_channel_index.matrix <- function( commodity_channel_index.plotly <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ## splice:optional-plotly:start lower_bound = -100, upper_bound = 100, ## splice:optional-plotly:end + title, ... ) { ## check that input value @@ -164,10 +184,16 @@ commodity_channel_index.plotly <- function( cols = rebuild_formula( names(constructed_series) ), - n = n, + timePeriod = timePeriod, na.bridge = TRUE ) + ## the constructed indicator + ## always returns excpected + ## columns which can be passed + ## down to add_last_values() + values_to_extract <- colnames(constructed_indicator) + ## add conditional idx constructed_indicator[["idx"]] <- add_idx( constructed_series @@ -177,7 +203,7 @@ commodity_channel_index.plotly <- function( ## splice:plotly-assembly:start name <- sprintf( "CCI(%d)", - n + timePeriod ) traces <- list( plotly_line(lower_bound, nrow(constructed_indicator)), @@ -186,18 +212,32 @@ commodity_channel_index.plotly <- function( ) ## splice:plotly-assembly:end - state <- .chart_state() - plotly_object <- build_plotly( - init = state[["main"]], - traces = traces, - decorators = list(), - name = get0( - x = "name", - ifnotfound = NULL + plotly_object <- add_last_value_ly( + build_plotly( + init = plotly_init(), + traces = traces, + decorators = get0( + x = "decorators", + ifnotfound = list() + ), + name = get0( + x = "name", + ifnotfound = NULL + ), + data = constructed_indicator, + title = if (missing(title)) { + "Commodity Channel Index" + } else { + title + } ), - data = constructed_indicator + data = constructed_indicator[, values_to_extract, drop = FALSE], + values_to_extract = values_to_extract, + name = get0(x = "name", ifnotfound = NULL) ) - state[["main"]] <- plotly_object + + state <- .chart_state() + state$sub <- c(state$sub, list(plotly_object)) plotly_object } @@ -209,8 +249,9 @@ commodity_channel_index.plotly <- function( commodity_channel_index.ggplot <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, + title, ## splice:optional-ggplot:start ## splice:optional-ggplot:end ... @@ -240,10 +281,16 @@ commodity_channel_index.ggplot <- function( cols = rebuild_formula( names(constructed_series) ), - n = n, + timePeriod = timePeriod, na.bridge = TRUE ) + ## the constructed indicator + ## always returns expected + ## columns which can be passed + ## down to add_last_value_gg() + values_to_extract <- colnames(constructed_indicator) + ## add conditional idx constructed_indicator[["idx"]] <- add_idx( constructed_series @@ -256,21 +303,35 @@ commodity_channel_index.ggplot <- function( ggplot_line(100), list(y = "CCI") ) - name <- sprintf("CCI(%d)", n) + name <- sprintf("CCI(%d)", timePeriod) ## splice:ggplot-assembly:end - state <- .chart_state() - ggplot_object <- build_ggplot( - init = state[["main"]], - layers = layers, - decorators = list(), - name = get0( - x = "name", - ifnotfound = NULL + ggplot_object <- add_last_value_gg( + build_ggplot( + init = ggplot_init(), + layers = layers, + decorators = get0( + x = "decorators", + ifnotfound = list() + ), + name = get0( + x = "name", + ifnotfound = NULL + ), + data = constructed_indicator, + title = if (missing(title)) { + "Commodity Channel Index" + } else { + title + } ), - data = constructed_indicator + data = constructed_indicator[, values_to_extract, drop = FALSE], + values_to_extract = values_to_extract, + name = get0(x = "name", ifnotfound = NULL) ) - state[["main"]] <- ggplot_object + + state <- .chart_state() + state$sub <- c(state$sub, list(ggplot_object)) ggplot_object } diff --git a/R/ta_CDL2CROWS.R b/R/ta_CDL2CROWS.R index 1697f99c1..3615e4201 100644 --- a/R/ta_CDL2CROWS.R +++ b/R/ta_CDL2CROWS.R @@ -39,6 +39,13 @@ two_crows <- function( #' @aliases two_crows CDL2CROWS <- two_crows +#' @export +#' @usage NULL +#' @rdname two_crows +#' +#' @aliases two_crows +twoCrows <- two_crows + #' @usage NULL #' @aliases two_crows #' @@ -115,7 +122,12 @@ two_crows.data.frame <- function( ... ) { map_dfr( - NextMethod() + two_crows.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) ) } @@ -129,7 +141,24 @@ two_crows.matrix <- function( na.bridge = FALSE, ... ) { - NextMethod() + two_crows.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDL2CROWS_lookback <- twoCrows_lookback <- two_crows_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CDL2CROWS_lookback + ) } #' @usage NULL @@ -167,7 +196,8 @@ two_crows.plotly <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx @@ -190,7 +220,6 @@ two_crows.plotly <- function( plotly_object } - #' @usage NULL #' @aliases two_crows #' @@ -225,7 +254,8 @@ two_crows.ggplot <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDL3BLACKCROWS.R b/R/ta_CDL3BLACKCROWS.R index a3f46cea1..d0c73ace4 100644 --- a/R/ta_CDL3BLACKCROWS.R +++ b/R/ta_CDL3BLACKCROWS.R @@ -39,6 +39,13 @@ three_black_crows <- function( #' @aliases three_black_crows CDL3BLACKCROWS <- three_black_crows +#' @export +#' @usage NULL +#' @rdname three_black_crows +#' +#' @aliases three_black_crows +threeBlackCrows <- three_black_crows + #' @usage NULL #' @aliases three_black_crows #' @@ -115,7 +122,12 @@ three_black_crows.data.frame <- function( ... ) { map_dfr( - NextMethod() + three_black_crows.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) ) } @@ -129,7 +141,24 @@ three_black_crows.matrix <- function( na.bridge = FALSE, ... ) { - NextMethod() + three_black_crows.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDL3BLACKCROWS_lookback <- threeBlackCrows_lookback <- three_black_crows_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CDL3BLACKCROWS_lookback + ) } #' @usage NULL @@ -167,7 +196,8 @@ three_black_crows.plotly <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx @@ -190,7 +220,6 @@ three_black_crows.plotly <- function( plotly_object } - #' @usage NULL #' @aliases three_black_crows #' @@ -225,7 +254,8 @@ three_black_crows.ggplot <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDL3INSIDE.R b/R/ta_CDL3INSIDE.R index cd46e3309..da82524b7 100644 --- a/R/ta_CDL3INSIDE.R +++ b/R/ta_CDL3INSIDE.R @@ -1,8 +1,8 @@ #' @export #' @family Pattern Recognition #' -#' @title Three Inside -#' @templateVar .title Three Inside +#' @title Three Inside Up/Down +#' @templateVar .title Three Inside Up/Down #' @templateVar .author Serkan Korkmaz #' @templateVar .fun three_inside #' @templateVar .family Pattern Recognition @@ -39,6 +39,13 @@ three_inside <- function( #' @aliases three_inside CDL3INSIDE <- three_inside +#' @export +#' @usage NULL +#' @rdname three_inside +#' +#' @aliases three_inside +threeInside <- three_inside + #' @usage NULL #' @aliases three_inside #' @@ -115,7 +122,12 @@ three_inside.data.frame <- function( ... ) { map_dfr( - NextMethod() + three_inside.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) ) } @@ -129,7 +141,24 @@ three_inside.matrix <- function( na.bridge = FALSE, ... ) { - NextMethod() + three_inside.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDL3INSIDE_lookback <- threeInside_lookback <- three_inside_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CDL3INSIDE_lookback + ) } #' @usage NULL @@ -167,7 +196,8 @@ three_inside.plotly <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx @@ -190,7 +220,6 @@ three_inside.plotly <- function( plotly_object } - #' @usage NULL #' @aliases three_inside #' @@ -225,7 +254,8 @@ three_inside.ggplot <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDL3LINESTRIKE.R b/R/ta_CDL3LINESTRIKE.R index ac54cdbbf..e590b4dfd 100644 --- a/R/ta_CDL3LINESTRIKE.R +++ b/R/ta_CDL3LINESTRIKE.R @@ -39,6 +39,13 @@ three_line_strike <- function( #' @aliases three_line_strike CDL3LINESTRIKE <- three_line_strike +#' @export +#' @usage NULL +#' @rdname three_line_strike +#' +#' @aliases three_line_strike +threeLineStrike <- three_line_strike + #' @usage NULL #' @aliases three_line_strike #' @@ -115,7 +122,12 @@ three_line_strike.data.frame <- function( ... ) { map_dfr( - NextMethod() + three_line_strike.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) ) } @@ -129,7 +141,24 @@ three_line_strike.matrix <- function( na.bridge = FALSE, ... ) { - NextMethod() + three_line_strike.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDL3LINESTRIKE_lookback <- threeLineStrike_lookback <- three_line_strike_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CDL3LINESTRIKE_lookback + ) } #' @usage NULL @@ -167,7 +196,8 @@ three_line_strike.plotly <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx @@ -190,7 +220,6 @@ three_line_strike.plotly <- function( plotly_object } - #' @usage NULL #' @aliases three_line_strike #' @@ -225,7 +254,8 @@ three_line_strike.ggplot <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDL3OUTSIDE.R b/R/ta_CDL3OUTSIDE.R index 872ce706b..fc629a2a9 100644 --- a/R/ta_CDL3OUTSIDE.R +++ b/R/ta_CDL3OUTSIDE.R @@ -1,8 +1,8 @@ #' @export #' @family Pattern Recognition #' -#' @title Three Outside -#' @templateVar .title Three Outside +#' @title Three Outside Up/Down +#' @templateVar .title Three Outside Up/Down #' @templateVar .author Serkan Korkmaz #' @templateVar .fun three_outside #' @templateVar .family Pattern Recognition @@ -39,6 +39,13 @@ three_outside <- function( #' @aliases three_outside CDL3OUTSIDE <- three_outside +#' @export +#' @usage NULL +#' @rdname three_outside +#' +#' @aliases three_outside +threeOutside <- three_outside + #' @usage NULL #' @aliases three_outside #' @@ -115,7 +122,12 @@ three_outside.data.frame <- function( ... ) { map_dfr( - NextMethod() + three_outside.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) ) } @@ -129,7 +141,24 @@ three_outside.matrix <- function( na.bridge = FALSE, ... ) { - NextMethod() + three_outside.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDL3OUTSIDE_lookback <- threeOutside_lookback <- three_outside_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CDL3OUTSIDE_lookback + ) } #' @usage NULL @@ -167,7 +196,8 @@ three_outside.plotly <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx @@ -190,7 +220,6 @@ three_outside.plotly <- function( plotly_object } - #' @usage NULL #' @aliases three_outside #' @@ -225,7 +254,8 @@ three_outside.ggplot <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDL3STARSINSOUTH.R b/R/ta_CDL3STARSINSOUTH.R index bf6fbc1ec..723b918e5 100644 --- a/R/ta_CDL3STARSINSOUTH.R +++ b/R/ta_CDL3STARSINSOUTH.R @@ -1,8 +1,8 @@ #' @export #' @family Pattern Recognition #' -#' @title Three Stars in the South -#' @templateVar .title Three Stars in the South +#' @title Three Stars In The South +#' @templateVar .title Three Stars In The South #' @templateVar .author Serkan Korkmaz #' @templateVar .fun three_stars_in_the_south #' @templateVar .family Pattern Recognition @@ -39,6 +39,13 @@ three_stars_in_the_south <- function( #' @aliases three_stars_in_the_south CDL3STARSINSOUTH <- three_stars_in_the_south +#' @export +#' @usage NULL +#' @rdname three_stars_in_the_south +#' +#' @aliases three_stars_in_the_south +threeStarsInTheSouth <- three_stars_in_the_south + #' @usage NULL #' @aliases three_stars_in_the_south #' @@ -115,7 +122,12 @@ three_stars_in_the_south.data.frame <- function( ... ) { map_dfr( - NextMethod() + three_stars_in_the_south.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) ) } @@ -129,7 +141,24 @@ three_stars_in_the_south.matrix <- function( na.bridge = FALSE, ... ) { - NextMethod() + three_stars_in_the_south.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDL3STARSINSOUTH_lookback <- threeStarsInTheSouth_lookback <- three_stars_in_the_south_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CDL3STARSINSOUTH_lookback + ) } #' @usage NULL @@ -167,7 +196,8 @@ three_stars_in_the_south.plotly <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx @@ -190,7 +220,6 @@ three_stars_in_the_south.plotly <- function( plotly_object } - #' @usage NULL #' @aliases three_stars_in_the_south #' @@ -225,7 +254,8 @@ three_stars_in_the_south.ggplot <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDL3WHITESOLDIERS.R b/R/ta_CDL3WHITESOLDIERS.R index 3d800b3f7..9e30ca422 100644 --- a/R/ta_CDL3WHITESOLDIERS.R +++ b/R/ta_CDL3WHITESOLDIERS.R @@ -1,8 +1,8 @@ #' @export #' @family Pattern Recognition #' -#' @title Three White Soldiers -#' @templateVar .title Three White Soldiers +#' @title Three Advancing White Soldiers +#' @templateVar .title Three Advancing White Soldiers #' @templateVar .author Serkan Korkmaz #' @templateVar .fun three_white_soldiers #' @templateVar .family Pattern Recognition @@ -39,6 +39,13 @@ three_white_soldiers <- function( #' @aliases three_white_soldiers CDL3WHITESOLDIERS <- three_white_soldiers +#' @export +#' @usage NULL +#' @rdname three_white_soldiers +#' +#' @aliases three_white_soldiers +threeWhiteSoldiers <- three_white_soldiers + #' @usage NULL #' @aliases three_white_soldiers #' @@ -115,7 +122,12 @@ three_white_soldiers.data.frame <- function( ... ) { map_dfr( - NextMethod() + three_white_soldiers.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) ) } @@ -129,7 +141,24 @@ three_white_soldiers.matrix <- function( na.bridge = FALSE, ... ) { - NextMethod() + three_white_soldiers.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDL3WHITESOLDIERS_lookback <- threeWhiteSoldiers_lookback <- three_white_soldiers_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CDL3WHITESOLDIERS_lookback + ) } #' @usage NULL @@ -167,7 +196,8 @@ three_white_soldiers.plotly <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx @@ -190,7 +220,6 @@ three_white_soldiers.plotly <- function( plotly_object } - #' @usage NULL #' @aliases three_white_soldiers #' @@ -225,7 +254,8 @@ three_white_soldiers.ggplot <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDLABANDONEDBABY.R b/R/ta_CDLABANDONEDBABY.R index 5decd6880..387eae1c4 100644 --- a/R/ta_CDLABANDONEDBABY.R +++ b/R/ta_CDLABANDONEDBABY.R @@ -26,7 +26,7 @@ abandoned_baby <- function( x, cols, - eps = 0, + penetration = 0.3, na.bridge = FALSE, ... ) { @@ -40,6 +40,13 @@ abandoned_baby <- function( #' @aliases abandoned_baby CDLABANDONEDBABY <- abandoned_baby +#' @export +#' @usage NULL +#' @rdname abandoned_baby +#' +#' @aliases abandoned_baby +abandonedBaby <- abandoned_baby + #' @usage NULL #' @aliases abandoned_baby #' @@ -47,7 +54,7 @@ CDLABANDONEDBABY <- abandoned_baby abandoned_baby.default <- function( x, cols, - eps = 0, + penetration = 0.3, na.bridge = FALSE, ... ) { @@ -91,7 +98,7 @@ abandoned_baby.default <- function( constructed_series[[2]], constructed_series[[3]], constructed_series[[4]], - eps, + as.double(penetration), normalize, as.logical(na.bridge) ) @@ -114,12 +121,18 @@ abandoned_baby.default <- function( abandoned_baby.data.frame <- function( x, cols, - eps = 0, + penetration = 0.3, na.bridge = FALSE, ... ) { map_dfr( - NextMethod() + abandoned_baby.default( + x = x, + cols = cols, + penetration = penetration, + na.bridge = na.bridge, + ... + ) ) } @@ -130,11 +143,31 @@ abandoned_baby.data.frame <- function( abandoned_baby.matrix <- function( x, cols, - eps = 0, + penetration = 0.3, + na.bridge = FALSE, + ... +) { + abandoned_baby.default( + x = x, + cols = cols, + penetration = penetration, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDLABANDONEDBABY_lookback <- abandonedBaby_lookback <- abandoned_baby_lookback <- function( + x, + cols, + penetration = 0.3, na.bridge = FALSE, ... ) { - NextMethod() + .Call( + C_impl_ta_CDLABANDONEDBABY_lookback, + as.double(penetration) + ) } #' @usage NULL @@ -144,7 +177,7 @@ abandoned_baby.matrix <- function( abandoned_baby.plotly <- function( x, cols, - eps = 0, + penetration = 0.3, na.bridge = FALSE, ... ) { @@ -174,7 +207,8 @@ abandoned_baby.plotly <- function( cols = rebuild_formula( names(constructed_series) ), - eps = eps + penetration = penetration, + na.bridge = na.bridge ) ## add conditional idx @@ -197,7 +231,6 @@ abandoned_baby.plotly <- function( plotly_object } - #' @usage NULL #' @aliases abandoned_baby #' @@ -205,7 +238,7 @@ abandoned_baby.plotly <- function( abandoned_baby.ggplot <- function( x, cols, - eps = 0, + penetration = 0.3, na.bridge = FALSE, ... ) { @@ -234,7 +267,8 @@ abandoned_baby.ggplot <- function( cols = rebuild_formula( names(constructed_series) ), - eps = eps + penetration = penetration, + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDLADVANCEBLOCK.R b/R/ta_CDLADVANCEBLOCK.R index 7ffa59eb0..7930fd926 100644 --- a/R/ta_CDLADVANCEBLOCK.R +++ b/R/ta_CDLADVANCEBLOCK.R @@ -39,6 +39,13 @@ advance_block <- function( #' @aliases advance_block CDLADVANCEBLOCK <- advance_block +#' @export +#' @usage NULL +#' @rdname advance_block +#' +#' @aliases advance_block +advanceBlock <- advance_block + #' @usage NULL #' @aliases advance_block #' @@ -115,7 +122,12 @@ advance_block.data.frame <- function( ... ) { map_dfr( - NextMethod() + advance_block.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) ) } @@ -129,7 +141,24 @@ advance_block.matrix <- function( na.bridge = FALSE, ... ) { - NextMethod() + advance_block.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDLADVANCEBLOCK_lookback <- advanceBlock_lookback <- advance_block_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CDLADVANCEBLOCK_lookback + ) } #' @usage NULL @@ -167,7 +196,8 @@ advance_block.plotly <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx @@ -190,7 +220,6 @@ advance_block.plotly <- function( plotly_object } - #' @usage NULL #' @aliases advance_block #' @@ -225,7 +254,8 @@ advance_block.ggplot <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDLBELTHOLD.R b/R/ta_CDLBELTHOLD.R index d241985d7..774588470 100644 --- a/R/ta_CDLBELTHOLD.R +++ b/R/ta_CDLBELTHOLD.R @@ -1,8 +1,8 @@ #' @export #' @family Pattern Recognition #' -#' @title Belt Hold -#' @templateVar .title Belt Hold +#' @title Belt-hold +#' @templateVar .title Belt-hold #' @templateVar .author Serkan Korkmaz #' @templateVar .fun belt_hold #' @templateVar .family Pattern Recognition @@ -39,6 +39,13 @@ belt_hold <- function( #' @aliases belt_hold CDLBELTHOLD <- belt_hold +#' @export +#' @usage NULL +#' @rdname belt_hold +#' +#' @aliases belt_hold +beltHold <- belt_hold + #' @usage NULL #' @aliases belt_hold #' @@ -115,7 +122,12 @@ belt_hold.data.frame <- function( ... ) { map_dfr( - NextMethod() + belt_hold.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) ) } @@ -129,7 +141,24 @@ belt_hold.matrix <- function( na.bridge = FALSE, ... ) { - NextMethod() + belt_hold.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDLBELTHOLD_lookback <- beltHold_lookback <- belt_hold_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CDLBELTHOLD_lookback + ) } #' @usage NULL @@ -167,7 +196,8 @@ belt_hold.plotly <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx @@ -190,7 +220,6 @@ belt_hold.plotly <- function( plotly_object } - #' @usage NULL #' @aliases belt_hold #' @@ -225,7 +254,8 @@ belt_hold.ggplot <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDLBREAKAWAY.R b/R/ta_CDLBREAKAWAY.R index 05fd11f8b..3c2bc9b19 100644 --- a/R/ta_CDLBREAKAWAY.R +++ b/R/ta_CDLBREAKAWAY.R @@ -1,8 +1,8 @@ #' @export #' @family Pattern Recognition #' -#' @title Break Away -#' @templateVar .title Break Away +#' @title Breakaway +#' @templateVar .title Breakaway #' @templateVar .author Serkan Korkmaz #' @templateVar .fun break_away #' @templateVar .family Pattern Recognition @@ -39,6 +39,13 @@ break_away <- function( #' @aliases break_away CDLBREAKAWAY <- break_away +#' @export +#' @usage NULL +#' @rdname break_away +#' +#' @aliases break_away +breakAway <- break_away + #' @usage NULL #' @aliases break_away #' @@ -115,7 +122,12 @@ break_away.data.frame <- function( ... ) { map_dfr( - NextMethod() + break_away.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) ) } @@ -129,7 +141,24 @@ break_away.matrix <- function( na.bridge = FALSE, ... ) { - NextMethod() + break_away.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDLBREAKAWAY_lookback <- breakAway_lookback <- break_away_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CDLBREAKAWAY_lookback + ) } #' @usage NULL @@ -167,7 +196,8 @@ break_away.plotly <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx @@ -190,7 +220,6 @@ break_away.plotly <- function( plotly_object } - #' @usage NULL #' @aliases break_away #' @@ -225,7 +254,8 @@ break_away.ggplot <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDLCLOSINGMARUBOZU.R b/R/ta_CDLCLOSINGMARUBOZU.R index 8c12755f5..af68e5998 100644 --- a/R/ta_CDLCLOSINGMARUBOZU.R +++ b/R/ta_CDLCLOSINGMARUBOZU.R @@ -39,6 +39,13 @@ closing_marubozu <- function( #' @aliases closing_marubozu CDLCLOSINGMARUBOZU <- closing_marubozu +#' @export +#' @usage NULL +#' @rdname closing_marubozu +#' +#' @aliases closing_marubozu +closingMarubozu <- closing_marubozu + #' @usage NULL #' @aliases closing_marubozu #' @@ -115,7 +122,12 @@ closing_marubozu.data.frame <- function( ... ) { map_dfr( - NextMethod() + closing_marubozu.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) ) } @@ -129,7 +141,24 @@ closing_marubozu.matrix <- function( na.bridge = FALSE, ... ) { - NextMethod() + closing_marubozu.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDLCLOSINGMARUBOZU_lookback <- closingMarubozu_lookback <- closing_marubozu_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CDLCLOSINGMARUBOZU_lookback + ) } #' @usage NULL @@ -167,7 +196,8 @@ closing_marubozu.plotly <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx @@ -190,7 +220,6 @@ closing_marubozu.plotly <- function( plotly_object } - #' @usage NULL #' @aliases closing_marubozu #' @@ -225,7 +254,8 @@ closing_marubozu.ggplot <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDLCONCEALBABYSWALL.R b/R/ta_CDLCONCEALBABYSWALL.R index 1abe77544..52100f9bf 100644 --- a/R/ta_CDLCONCEALBABYSWALL.R +++ b/R/ta_CDLCONCEALBABYSWALL.R @@ -39,6 +39,13 @@ concealing_baby_swallow <- function( #' @aliases concealing_baby_swallow CDLCONCEALBABYSWALL <- concealing_baby_swallow +#' @export +#' @usage NULL +#' @rdname concealing_baby_swallow +#' +#' @aliases concealing_baby_swallow +concealingBabySwallow <- concealing_baby_swallow + #' @usage NULL #' @aliases concealing_baby_swallow #' @@ -115,7 +122,12 @@ concealing_baby_swallow.data.frame <- function( ... ) { map_dfr( - NextMethod() + concealing_baby_swallow.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) ) } @@ -129,7 +141,24 @@ concealing_baby_swallow.matrix <- function( na.bridge = FALSE, ... ) { - NextMethod() + concealing_baby_swallow.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDLCONCEALBABYSWALL_lookback <- concealingBabySwallow_lookback <- concealing_baby_swallow_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CDLCONCEALBABYSWALL_lookback + ) } #' @usage NULL @@ -167,7 +196,8 @@ concealing_baby_swallow.plotly <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx @@ -190,7 +220,6 @@ concealing_baby_swallow.plotly <- function( plotly_object } - #' @usage NULL #' @aliases concealing_baby_swallow #' @@ -225,7 +254,8 @@ concealing_baby_swallow.ggplot <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDLCOUNTERATTACK.R b/R/ta_CDLCOUNTERATTACK.R index 3fb8660c4..3f14a1af8 100644 --- a/R/ta_CDLCOUNTERATTACK.R +++ b/R/ta_CDLCOUNTERATTACK.R @@ -1,8 +1,8 @@ #' @export #' @family Pattern Recognition #' -#' @title Counter Attack -#' @templateVar .title Counter Attack +#' @title Counterattack +#' @templateVar .title Counterattack #' @templateVar .author Serkan Korkmaz #' @templateVar .fun counter_attack #' @templateVar .family Pattern Recognition @@ -39,6 +39,13 @@ counter_attack <- function( #' @aliases counter_attack CDLCOUNTERATTACK <- counter_attack +#' @export +#' @usage NULL +#' @rdname counter_attack +#' +#' @aliases counter_attack +counterAttack <- counter_attack + #' @usage NULL #' @aliases counter_attack #' @@ -115,7 +122,12 @@ counter_attack.data.frame <- function( ... ) { map_dfr( - NextMethod() + counter_attack.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) ) } @@ -129,7 +141,24 @@ counter_attack.matrix <- function( na.bridge = FALSE, ... ) { - NextMethod() + counter_attack.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDLCOUNTERATTACK_lookback <- counterAttack_lookback <- counter_attack_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CDLCOUNTERATTACK_lookback + ) } #' @usage NULL @@ -167,7 +196,8 @@ counter_attack.plotly <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx @@ -190,7 +220,6 @@ counter_attack.plotly <- function( plotly_object } - #' @usage NULL #' @aliases counter_attack #' @@ -225,7 +254,8 @@ counter_attack.ggplot <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDLDARKCLOUDCOVER.R b/R/ta_CDLDARKCLOUDCOVER.R index b56bd5113..da42c6f96 100644 --- a/R/ta_CDLDARKCLOUDCOVER.R +++ b/R/ta_CDLDARKCLOUDCOVER.R @@ -26,7 +26,7 @@ dark_cloud_cover <- function( x, cols, - eps = 0, + penetration = 0.5, na.bridge = FALSE, ... ) { @@ -40,6 +40,13 @@ dark_cloud_cover <- function( #' @aliases dark_cloud_cover CDLDARKCLOUDCOVER <- dark_cloud_cover +#' @export +#' @usage NULL +#' @rdname dark_cloud_cover +#' +#' @aliases dark_cloud_cover +darkCloudCover <- dark_cloud_cover + #' @usage NULL #' @aliases dark_cloud_cover #' @@ -47,7 +54,7 @@ CDLDARKCLOUDCOVER <- dark_cloud_cover dark_cloud_cover.default <- function( x, cols, - eps = 0, + penetration = 0.5, na.bridge = FALSE, ... ) { @@ -91,7 +98,7 @@ dark_cloud_cover.default <- function( constructed_series[[2]], constructed_series[[3]], constructed_series[[4]], - eps, + as.double(penetration), normalize, as.logical(na.bridge) ) @@ -114,12 +121,18 @@ dark_cloud_cover.default <- function( dark_cloud_cover.data.frame <- function( x, cols, - eps = 0, + penetration = 0.5, na.bridge = FALSE, ... ) { map_dfr( - NextMethod() + dark_cloud_cover.default( + x = x, + cols = cols, + penetration = penetration, + na.bridge = na.bridge, + ... + ) ) } @@ -130,11 +143,31 @@ dark_cloud_cover.data.frame <- function( dark_cloud_cover.matrix <- function( x, cols, - eps = 0, + penetration = 0.5, + na.bridge = FALSE, + ... +) { + dark_cloud_cover.default( + x = x, + cols = cols, + penetration = penetration, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDLDARKCLOUDCOVER_lookback <- darkCloudCover_lookback <- dark_cloud_cover_lookback <- function( + x, + cols, + penetration = 0.5, na.bridge = FALSE, ... ) { - NextMethod() + .Call( + C_impl_ta_CDLDARKCLOUDCOVER_lookback, + as.double(penetration) + ) } #' @usage NULL @@ -144,7 +177,7 @@ dark_cloud_cover.matrix <- function( dark_cloud_cover.plotly <- function( x, cols, - eps = 0, + penetration = 0.5, na.bridge = FALSE, ... ) { @@ -174,7 +207,8 @@ dark_cloud_cover.plotly <- function( cols = rebuild_formula( names(constructed_series) ), - eps = eps + penetration = penetration, + na.bridge = na.bridge ) ## add conditional idx @@ -197,7 +231,6 @@ dark_cloud_cover.plotly <- function( plotly_object } - #' @usage NULL #' @aliases dark_cloud_cover #' @@ -205,7 +238,7 @@ dark_cloud_cover.plotly <- function( dark_cloud_cover.ggplot <- function( x, cols, - eps = 0, + penetration = 0.5, na.bridge = FALSE, ... ) { @@ -234,7 +267,8 @@ dark_cloud_cover.ggplot <- function( cols = rebuild_formula( names(constructed_series) ), - eps = eps + penetration = penetration, + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDLDOJI.R b/R/ta_CDLDOJI.R index 2ca3a5002..bec111837 100644 --- a/R/ta_CDLDOJI.R +++ b/R/ta_CDLDOJI.R @@ -115,7 +115,12 @@ doji.data.frame <- function( ... ) { map_dfr( - NextMethod() + doji.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) ) } @@ -129,7 +134,24 @@ doji.matrix <- function( na.bridge = FALSE, ... ) { - NextMethod() + doji.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDLDOJI_lookback <- doji_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CDLDOJI_lookback + ) } #' @usage NULL @@ -167,7 +189,8 @@ doji.plotly <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx @@ -190,7 +213,6 @@ doji.plotly <- function( plotly_object } - #' @usage NULL #' @aliases doji #' @@ -225,7 +247,8 @@ doji.ggplot <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDLDOJISTAR.R b/R/ta_CDLDOJISTAR.R index 9691c0ef6..d9216409b 100644 --- a/R/ta_CDLDOJISTAR.R +++ b/R/ta_CDLDOJISTAR.R @@ -39,6 +39,13 @@ doji_star <- function( #' @aliases doji_star CDLDOJISTAR <- doji_star +#' @export +#' @usage NULL +#' @rdname doji_star +#' +#' @aliases doji_star +dojiStar <- doji_star + #' @usage NULL #' @aliases doji_star #' @@ -115,7 +122,12 @@ doji_star.data.frame <- function( ... ) { map_dfr( - NextMethod() + doji_star.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) ) } @@ -129,7 +141,24 @@ doji_star.matrix <- function( na.bridge = FALSE, ... ) { - NextMethod() + doji_star.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDLDOJISTAR_lookback <- dojiStar_lookback <- doji_star_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CDLDOJISTAR_lookback + ) } #' @usage NULL @@ -167,7 +196,8 @@ doji_star.plotly <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx @@ -190,7 +220,6 @@ doji_star.plotly <- function( plotly_object } - #' @usage NULL #' @aliases doji_star #' @@ -225,7 +254,8 @@ doji_star.ggplot <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDLDRAGONFLYDOJI.R b/R/ta_CDLDRAGONFLYDOJI.R index 602530860..9e7bbb2f2 100644 --- a/R/ta_CDLDRAGONFLYDOJI.R +++ b/R/ta_CDLDRAGONFLYDOJI.R @@ -39,6 +39,13 @@ dragonfly_doji <- function( #' @aliases dragonfly_doji CDLDRAGONFLYDOJI <- dragonfly_doji +#' @export +#' @usage NULL +#' @rdname dragonfly_doji +#' +#' @aliases dragonfly_doji +dragonflyDoji <- dragonfly_doji + #' @usage NULL #' @aliases dragonfly_doji #' @@ -115,7 +122,12 @@ dragonfly_doji.data.frame <- function( ... ) { map_dfr( - NextMethod() + dragonfly_doji.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) ) } @@ -129,7 +141,24 @@ dragonfly_doji.matrix <- function( na.bridge = FALSE, ... ) { - NextMethod() + dragonfly_doji.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDLDRAGONFLYDOJI_lookback <- dragonflyDoji_lookback <- dragonfly_doji_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CDLDRAGONFLYDOJI_lookback + ) } #' @usage NULL @@ -167,7 +196,8 @@ dragonfly_doji.plotly <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx @@ -190,7 +220,6 @@ dragonfly_doji.plotly <- function( plotly_object } - #' @usage NULL #' @aliases dragonfly_doji #' @@ -225,7 +254,8 @@ dragonfly_doji.ggplot <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDLENGULFING.R b/R/ta_CDLENGULFING.R index 24038dd37..ec0a2d952 100644 --- a/R/ta_CDLENGULFING.R +++ b/R/ta_CDLENGULFING.R @@ -1,8 +1,8 @@ #' @export #' @family Pattern Recognition #' -#' @title Engulfing -#' @templateVar .title Engulfing +#' @title Engulfing Pattern +#' @templateVar .title Engulfing Pattern #' @templateVar .author Serkan Korkmaz #' @templateVar .fun engulfing #' @templateVar .family Pattern Recognition @@ -115,7 +115,12 @@ engulfing.data.frame <- function( ... ) { map_dfr( - NextMethod() + engulfing.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) ) } @@ -129,7 +134,24 @@ engulfing.matrix <- function( na.bridge = FALSE, ... ) { - NextMethod() + engulfing.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDLENGULFING_lookback <- engulfing_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CDLENGULFING_lookback + ) } #' @usage NULL @@ -167,7 +189,8 @@ engulfing.plotly <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx @@ -190,7 +213,6 @@ engulfing.plotly <- function( plotly_object } - #' @usage NULL #' @aliases engulfing #' @@ -225,7 +247,8 @@ engulfing.ggplot <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDLEVENINGDOJISTAR.R b/R/ta_CDLEVENINGDOJISTAR.R index 907656aa7..ac78692f3 100644 --- a/R/ta_CDLEVENINGDOJISTAR.R +++ b/R/ta_CDLEVENINGDOJISTAR.R @@ -26,7 +26,7 @@ evening_doji_star <- function( x, cols, - eps = 0, + penetration = 0.3, na.bridge = FALSE, ... ) { @@ -40,6 +40,13 @@ evening_doji_star <- function( #' @aliases evening_doji_star CDLEVENINGDOJISTAR <- evening_doji_star +#' @export +#' @usage NULL +#' @rdname evening_doji_star +#' +#' @aliases evening_doji_star +eveningDojiStar <- evening_doji_star + #' @usage NULL #' @aliases evening_doji_star #' @@ -47,7 +54,7 @@ CDLEVENINGDOJISTAR <- evening_doji_star evening_doji_star.default <- function( x, cols, - eps = 0, + penetration = 0.3, na.bridge = FALSE, ... ) { @@ -91,7 +98,7 @@ evening_doji_star.default <- function( constructed_series[[2]], constructed_series[[3]], constructed_series[[4]], - eps, + as.double(penetration), normalize, as.logical(na.bridge) ) @@ -114,12 +121,18 @@ evening_doji_star.default <- function( evening_doji_star.data.frame <- function( x, cols, - eps = 0, + penetration = 0.3, na.bridge = FALSE, ... ) { map_dfr( - NextMethod() + evening_doji_star.default( + x = x, + cols = cols, + penetration = penetration, + na.bridge = na.bridge, + ... + ) ) } @@ -130,11 +143,31 @@ evening_doji_star.data.frame <- function( evening_doji_star.matrix <- function( x, cols, - eps = 0, + penetration = 0.3, + na.bridge = FALSE, + ... +) { + evening_doji_star.default( + x = x, + cols = cols, + penetration = penetration, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDLEVENINGDOJISTAR_lookback <- eveningDojiStar_lookback <- evening_doji_star_lookback <- function( + x, + cols, + penetration = 0.3, na.bridge = FALSE, ... ) { - NextMethod() + .Call( + C_impl_ta_CDLEVENINGDOJISTAR_lookback, + as.double(penetration) + ) } #' @usage NULL @@ -144,7 +177,7 @@ evening_doji_star.matrix <- function( evening_doji_star.plotly <- function( x, cols, - eps = 0, + penetration = 0.3, na.bridge = FALSE, ... ) { @@ -174,7 +207,8 @@ evening_doji_star.plotly <- function( cols = rebuild_formula( names(constructed_series) ), - eps = eps + penetration = penetration, + na.bridge = na.bridge ) ## add conditional idx @@ -197,7 +231,6 @@ evening_doji_star.plotly <- function( plotly_object } - #' @usage NULL #' @aliases evening_doji_star #' @@ -205,7 +238,7 @@ evening_doji_star.plotly <- function( evening_doji_star.ggplot <- function( x, cols, - eps = 0, + penetration = 0.3, na.bridge = FALSE, ... ) { @@ -234,7 +267,8 @@ evening_doji_star.ggplot <- function( cols = rebuild_formula( names(constructed_series) ), - eps = eps + penetration = penetration, + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDLEVENINGSTAR.R b/R/ta_CDLEVENINGSTAR.R index 944020248..125d85543 100644 --- a/R/ta_CDLEVENINGSTAR.R +++ b/R/ta_CDLEVENINGSTAR.R @@ -26,7 +26,7 @@ evening_star <- function( x, cols, - eps = 0, + penetration = 0.3, na.bridge = FALSE, ... ) { @@ -40,6 +40,13 @@ evening_star <- function( #' @aliases evening_star CDLEVENINGSTAR <- evening_star +#' @export +#' @usage NULL +#' @rdname evening_star +#' +#' @aliases evening_star +eveningStar <- evening_star + #' @usage NULL #' @aliases evening_star #' @@ -47,7 +54,7 @@ CDLEVENINGSTAR <- evening_star evening_star.default <- function( x, cols, - eps = 0, + penetration = 0.3, na.bridge = FALSE, ... ) { @@ -91,7 +98,7 @@ evening_star.default <- function( constructed_series[[2]], constructed_series[[3]], constructed_series[[4]], - eps, + as.double(penetration), normalize, as.logical(na.bridge) ) @@ -114,12 +121,18 @@ evening_star.default <- function( evening_star.data.frame <- function( x, cols, - eps = 0, + penetration = 0.3, na.bridge = FALSE, ... ) { map_dfr( - NextMethod() + evening_star.default( + x = x, + cols = cols, + penetration = penetration, + na.bridge = na.bridge, + ... + ) ) } @@ -130,11 +143,31 @@ evening_star.data.frame <- function( evening_star.matrix <- function( x, cols, - eps = 0, + penetration = 0.3, + na.bridge = FALSE, + ... +) { + evening_star.default( + x = x, + cols = cols, + penetration = penetration, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDLEVENINGSTAR_lookback <- eveningStar_lookback <- evening_star_lookback <- function( + x, + cols, + penetration = 0.3, na.bridge = FALSE, ... ) { - NextMethod() + .Call( + C_impl_ta_CDLEVENINGSTAR_lookback, + as.double(penetration) + ) } #' @usage NULL @@ -144,7 +177,7 @@ evening_star.matrix <- function( evening_star.plotly <- function( x, cols, - eps = 0, + penetration = 0.3, na.bridge = FALSE, ... ) { @@ -174,7 +207,8 @@ evening_star.plotly <- function( cols = rebuild_formula( names(constructed_series) ), - eps = eps + penetration = penetration, + na.bridge = na.bridge ) ## add conditional idx @@ -197,7 +231,6 @@ evening_star.plotly <- function( plotly_object } - #' @usage NULL #' @aliases evening_star #' @@ -205,7 +238,7 @@ evening_star.plotly <- function( evening_star.ggplot <- function( x, cols, - eps = 0, + penetration = 0.3, na.bridge = FALSE, ... ) { @@ -234,7 +267,8 @@ evening_star.ggplot <- function( cols = rebuild_formula( names(constructed_series) ), - eps = eps + penetration = penetration, + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDLGAPSIDESIDEWHITE.R b/R/ta_CDLGAPSIDESIDEWHITE.R index 50410f78b..de5e8f8c2 100644 --- a/R/ta_CDLGAPSIDESIDEWHITE.R +++ b/R/ta_CDLGAPSIDESIDEWHITE.R @@ -39,6 +39,13 @@ gaps_side_white <- function( #' @aliases gaps_side_white CDLGAPSIDESIDEWHITE <- gaps_side_white +#' @export +#' @usage NULL +#' @rdname gaps_side_white +#' +#' @aliases gaps_side_white +gapsSideWhite <- gaps_side_white + #' @usage NULL #' @aliases gaps_side_white #' @@ -115,7 +122,12 @@ gaps_side_white.data.frame <- function( ... ) { map_dfr( - NextMethod() + gaps_side_white.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) ) } @@ -129,7 +141,24 @@ gaps_side_white.matrix <- function( na.bridge = FALSE, ... ) { - NextMethod() + gaps_side_white.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDLGAPSIDESIDEWHITE_lookback <- gapsSideWhite_lookback <- gaps_side_white_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CDLGAPSIDESIDEWHITE_lookback + ) } #' @usage NULL @@ -167,7 +196,8 @@ gaps_side_white.plotly <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx @@ -190,7 +220,6 @@ gaps_side_white.plotly <- function( plotly_object } - #' @usage NULL #' @aliases gaps_side_white #' @@ -225,7 +254,8 @@ gaps_side_white.ggplot <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDLGRAVESTONEDOJI.R b/R/ta_CDLGRAVESTONEDOJI.R index 931163072..a1a8e6b70 100644 --- a/R/ta_CDLGRAVESTONEDOJI.R +++ b/R/ta_CDLGRAVESTONEDOJI.R @@ -39,6 +39,13 @@ gravestone_doji <- function( #' @aliases gravestone_doji CDLGRAVESTONEDOJI <- gravestone_doji +#' @export +#' @usage NULL +#' @rdname gravestone_doji +#' +#' @aliases gravestone_doji +gravestoneDoji <- gravestone_doji + #' @usage NULL #' @aliases gravestone_doji #' @@ -115,7 +122,12 @@ gravestone_doji.data.frame <- function( ... ) { map_dfr( - NextMethod() + gravestone_doji.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) ) } @@ -129,7 +141,24 @@ gravestone_doji.matrix <- function( na.bridge = FALSE, ... ) { - NextMethod() + gravestone_doji.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDLGRAVESTONEDOJI_lookback <- gravestoneDoji_lookback <- gravestone_doji_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CDLGRAVESTONEDOJI_lookback + ) } #' @usage NULL @@ -167,7 +196,8 @@ gravestone_doji.plotly <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx @@ -190,7 +220,6 @@ gravestone_doji.plotly <- function( plotly_object } - #' @usage NULL #' @aliases gravestone_doji #' @@ -225,7 +254,8 @@ gravestone_doji.ggplot <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDLHAMMER.R b/R/ta_CDLHAMMER.R index bf74d0411..b27203f87 100644 --- a/R/ta_CDLHAMMER.R +++ b/R/ta_CDLHAMMER.R @@ -115,7 +115,12 @@ hammer.data.frame <- function( ... ) { map_dfr( - NextMethod() + hammer.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) ) } @@ -129,7 +134,24 @@ hammer.matrix <- function( na.bridge = FALSE, ... ) { - NextMethod() + hammer.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDLHAMMER_lookback <- hammer_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CDLHAMMER_lookback + ) } #' @usage NULL @@ -167,7 +189,8 @@ hammer.plotly <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx @@ -190,7 +213,6 @@ hammer.plotly <- function( plotly_object } - #' @usage NULL #' @aliases hammer #' @@ -225,7 +247,8 @@ hammer.ggplot <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDLHANGINGMAN.R b/R/ta_CDLHANGINGMAN.R index 427325177..fcfeb18a9 100644 --- a/R/ta_CDLHANGINGMAN.R +++ b/R/ta_CDLHANGINGMAN.R @@ -39,6 +39,13 @@ hanging_man <- function( #' @aliases hanging_man CDLHANGINGMAN <- hanging_man +#' @export +#' @usage NULL +#' @rdname hanging_man +#' +#' @aliases hanging_man +hangingMan <- hanging_man + #' @usage NULL #' @aliases hanging_man #' @@ -115,7 +122,12 @@ hanging_man.data.frame <- function( ... ) { map_dfr( - NextMethod() + hanging_man.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) ) } @@ -129,7 +141,24 @@ hanging_man.matrix <- function( na.bridge = FALSE, ... ) { - NextMethod() + hanging_man.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDLHANGINGMAN_lookback <- hangingMan_lookback <- hanging_man_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CDLHANGINGMAN_lookback + ) } #' @usage NULL @@ -167,7 +196,8 @@ hanging_man.plotly <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx @@ -190,7 +220,6 @@ hanging_man.plotly <- function( plotly_object } - #' @usage NULL #' @aliases hanging_man #' @@ -225,7 +254,8 @@ hanging_man.ggplot <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDLHARAMI.R b/R/ta_CDLHARAMI.R index 0e1a5403f..47ea7b55c 100644 --- a/R/ta_CDLHARAMI.R +++ b/R/ta_CDLHARAMI.R @@ -1,8 +1,8 @@ #' @export #' @family Pattern Recognition #' -#' @title Harami -#' @templateVar .title Harami +#' @title Harami Pattern +#' @templateVar .title Harami Pattern #' @templateVar .author Serkan Korkmaz #' @templateVar .fun harami #' @templateVar .family Pattern Recognition @@ -115,7 +115,12 @@ harami.data.frame <- function( ... ) { map_dfr( - NextMethod() + harami.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) ) } @@ -129,7 +134,24 @@ harami.matrix <- function( na.bridge = FALSE, ... ) { - NextMethod() + harami.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDLHARAMI_lookback <- harami_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CDLHARAMI_lookback + ) } #' @usage NULL @@ -167,7 +189,8 @@ harami.plotly <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx @@ -190,7 +213,6 @@ harami.plotly <- function( plotly_object } - #' @usage NULL #' @aliases harami #' @@ -225,7 +247,8 @@ harami.ggplot <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDLHARAMICROSS.R b/R/ta_CDLHARAMICROSS.R index 749141b97..2881eee1c 100644 --- a/R/ta_CDLHARAMICROSS.R +++ b/R/ta_CDLHARAMICROSS.R @@ -1,8 +1,8 @@ #' @export #' @family Pattern Recognition #' -#' @title Harami Cross -#' @templateVar .title Harami Cross +#' @title Harami Cross Pattern +#' @templateVar .title Harami Cross Pattern #' @templateVar .author Serkan Korkmaz #' @templateVar .fun harami_cross #' @templateVar .family Pattern Recognition @@ -39,6 +39,13 @@ harami_cross <- function( #' @aliases harami_cross CDLHARAMICROSS <- harami_cross +#' @export +#' @usage NULL +#' @rdname harami_cross +#' +#' @aliases harami_cross +haramiCross <- harami_cross + #' @usage NULL #' @aliases harami_cross #' @@ -115,7 +122,12 @@ harami_cross.data.frame <- function( ... ) { map_dfr( - NextMethod() + harami_cross.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) ) } @@ -129,7 +141,24 @@ harami_cross.matrix <- function( na.bridge = FALSE, ... ) { - NextMethod() + harami_cross.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDLHARAMICROSS_lookback <- haramiCross_lookback <- harami_cross_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CDLHARAMICROSS_lookback + ) } #' @usage NULL @@ -167,7 +196,8 @@ harami_cross.plotly <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx @@ -190,7 +220,6 @@ harami_cross.plotly <- function( plotly_object } - #' @usage NULL #' @aliases harami_cross #' @@ -225,7 +254,8 @@ harami_cross.ggplot <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDLHIGHWAVE.R b/R/ta_CDLHIGHWAVE.R index 17100b4e3..ad60c5929 100644 --- a/R/ta_CDLHIGHWAVE.R +++ b/R/ta_CDLHIGHWAVE.R @@ -1,8 +1,8 @@ #' @export #' @family Pattern Recognition #' -#' @title High Wave -#' @templateVar .title High Wave +#' @title High-Wave Candle +#' @templateVar .title High-Wave Candle #' @templateVar .author Serkan Korkmaz #' @templateVar .fun high_wave #' @templateVar .family Pattern Recognition @@ -39,6 +39,13 @@ high_wave <- function( #' @aliases high_wave CDLHIGHWAVE <- high_wave +#' @export +#' @usage NULL +#' @rdname high_wave +#' +#' @aliases high_wave +highWave <- high_wave + #' @usage NULL #' @aliases high_wave #' @@ -115,7 +122,12 @@ high_wave.data.frame <- function( ... ) { map_dfr( - NextMethod() + high_wave.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) ) } @@ -129,7 +141,24 @@ high_wave.matrix <- function( na.bridge = FALSE, ... ) { - NextMethod() + high_wave.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDLHIGHWAVE_lookback <- highWave_lookback <- high_wave_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CDLHIGHWAVE_lookback + ) } #' @usage NULL @@ -167,7 +196,8 @@ high_wave.plotly <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx @@ -190,7 +220,6 @@ high_wave.plotly <- function( plotly_object } - #' @usage NULL #' @aliases high_wave #' @@ -225,7 +254,8 @@ high_wave.ggplot <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDLHIKKAKE.R b/R/ta_CDLHIKKAKE.R index f5e218e47..8084cb4a3 100644 --- a/R/ta_CDLHIKKAKE.R +++ b/R/ta_CDLHIKKAKE.R @@ -1,8 +1,8 @@ #' @export #' @family Pattern Recognition #' -#' @title Hikkake -#' @templateVar .title Hikkake +#' @title Hikkake Pattern +#' @templateVar .title Hikkake Pattern #' @templateVar .author Serkan Korkmaz #' @templateVar .fun hikakke #' @templateVar .family Pattern Recognition @@ -115,7 +115,12 @@ hikakke.data.frame <- function( ... ) { map_dfr( - NextMethod() + hikakke.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) ) } @@ -129,7 +134,24 @@ hikakke.matrix <- function( na.bridge = FALSE, ... ) { - NextMethod() + hikakke.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDLHIKKAKE_lookback <- hikakke_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CDLHIKKAKE_lookback + ) } #' @usage NULL @@ -167,7 +189,8 @@ hikakke.plotly <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx @@ -190,7 +213,6 @@ hikakke.plotly <- function( plotly_object } - #' @usage NULL #' @aliases hikakke #' @@ -225,7 +247,8 @@ hikakke.ggplot <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDLHIKKAKEMOD.R b/R/ta_CDLHIKKAKEMOD.R index 43fdab5ee..11b6bab91 100644 --- a/R/ta_CDLHIKKAKEMOD.R +++ b/R/ta_CDLHIKKAKEMOD.R @@ -1,8 +1,8 @@ #' @export #' @family Pattern Recognition #' -#' @title Hikkake Modified -#' @templateVar .title Hikkake Modified +#' @title Modified Hikkake Pattern +#' @templateVar .title Modified Hikkake Pattern #' @templateVar .author Serkan Korkmaz #' @templateVar .fun hikakke_mod #' @templateVar .family Pattern Recognition @@ -39,6 +39,13 @@ hikakke_mod <- function( #' @aliases hikakke_mod CDLHIKKAKEMOD <- hikakke_mod +#' @export +#' @usage NULL +#' @rdname hikakke_mod +#' +#' @aliases hikakke_mod +hikakkeMod <- hikakke_mod + #' @usage NULL #' @aliases hikakke_mod #' @@ -115,7 +122,12 @@ hikakke_mod.data.frame <- function( ... ) { map_dfr( - NextMethod() + hikakke_mod.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) ) } @@ -129,7 +141,24 @@ hikakke_mod.matrix <- function( na.bridge = FALSE, ... ) { - NextMethod() + hikakke_mod.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDLHIKKAKEMOD_lookback <- hikakkeMod_lookback <- hikakke_mod_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CDLHIKKAKEMOD_lookback + ) } #' @usage NULL @@ -167,7 +196,8 @@ hikakke_mod.plotly <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx @@ -190,7 +220,6 @@ hikakke_mod.plotly <- function( plotly_object } - #' @usage NULL #' @aliases hikakke_mod #' @@ -225,7 +254,8 @@ hikakke_mod.ggplot <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDLHOMINGPIGEON.R b/R/ta_CDLHOMINGPIGEON.R index 82566f6b6..fba92b1ea 100644 --- a/R/ta_CDLHOMINGPIGEON.R +++ b/R/ta_CDLHOMINGPIGEON.R @@ -39,6 +39,13 @@ homing_pigeon <- function( #' @aliases homing_pigeon CDLHOMINGPIGEON <- homing_pigeon +#' @export +#' @usage NULL +#' @rdname homing_pigeon +#' +#' @aliases homing_pigeon +homingPigeon <- homing_pigeon + #' @usage NULL #' @aliases homing_pigeon #' @@ -115,7 +122,12 @@ homing_pigeon.data.frame <- function( ... ) { map_dfr( - NextMethod() + homing_pigeon.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) ) } @@ -129,7 +141,24 @@ homing_pigeon.matrix <- function( na.bridge = FALSE, ... ) { - NextMethod() + homing_pigeon.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDLHOMINGPIGEON_lookback <- homingPigeon_lookback <- homing_pigeon_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CDLHOMINGPIGEON_lookback + ) } #' @usage NULL @@ -167,7 +196,8 @@ homing_pigeon.plotly <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx @@ -190,7 +220,6 @@ homing_pigeon.plotly <- function( plotly_object } - #' @usage NULL #' @aliases homing_pigeon #' @@ -225,7 +254,8 @@ homing_pigeon.ggplot <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDLIDENTICAL3CROWS.R b/R/ta_CDLIDENTICAL3CROWS.R index 6d53e8b46..256dc1eb9 100644 --- a/R/ta_CDLIDENTICAL3CROWS.R +++ b/R/ta_CDLIDENTICAL3CROWS.R @@ -39,6 +39,13 @@ three_identical_crows <- function( #' @aliases three_identical_crows CDLIDENTICAL3CROWS <- three_identical_crows +#' @export +#' @usage NULL +#' @rdname three_identical_crows +#' +#' @aliases three_identical_crows +threeIdenticalCrows <- three_identical_crows + #' @usage NULL #' @aliases three_identical_crows #' @@ -115,7 +122,12 @@ three_identical_crows.data.frame <- function( ... ) { map_dfr( - NextMethod() + three_identical_crows.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) ) } @@ -129,7 +141,24 @@ three_identical_crows.matrix <- function( na.bridge = FALSE, ... ) { - NextMethod() + three_identical_crows.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDLIDENTICAL3CROWS_lookback <- threeIdenticalCrows_lookback <- three_identical_crows_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CDLIDENTICAL3CROWS_lookback + ) } #' @usage NULL @@ -167,7 +196,8 @@ three_identical_crows.plotly <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx @@ -190,7 +220,6 @@ three_identical_crows.plotly <- function( plotly_object } - #' @usage NULL #' @aliases three_identical_crows #' @@ -225,7 +254,8 @@ three_identical_crows.ggplot <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDLINNECK.R b/R/ta_CDLINNECK.R index 0ad45078d..aa9398bd4 100644 --- a/R/ta_CDLINNECK.R +++ b/R/ta_CDLINNECK.R @@ -1,8 +1,8 @@ #' @export #' @family Pattern Recognition #' -#' @title In Neck -#' @templateVar .title In Neck +#' @title In-Neck Pattern +#' @templateVar .title In-Neck Pattern #' @templateVar .author Serkan Korkmaz #' @templateVar .fun in_neck #' @templateVar .family Pattern Recognition @@ -39,6 +39,13 @@ in_neck <- function( #' @aliases in_neck CDLINNECK <- in_neck +#' @export +#' @usage NULL +#' @rdname in_neck +#' +#' @aliases in_neck +inNeck <- in_neck + #' @usage NULL #' @aliases in_neck #' @@ -115,7 +122,12 @@ in_neck.data.frame <- function( ... ) { map_dfr( - NextMethod() + in_neck.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) ) } @@ -129,7 +141,24 @@ in_neck.matrix <- function( na.bridge = FALSE, ... ) { - NextMethod() + in_neck.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDLINNECK_lookback <- inNeck_lookback <- in_neck_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CDLINNECK_lookback + ) } #' @usage NULL @@ -167,7 +196,8 @@ in_neck.plotly <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx @@ -190,7 +220,6 @@ in_neck.plotly <- function( plotly_object } - #' @usage NULL #' @aliases in_neck #' @@ -225,7 +254,8 @@ in_neck.ggplot <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDLINVERTEDHAMMER.R b/R/ta_CDLINVERTEDHAMMER.R index 46b28e3a1..a55211985 100644 --- a/R/ta_CDLINVERTEDHAMMER.R +++ b/R/ta_CDLINVERTEDHAMMER.R @@ -39,6 +39,13 @@ inverted_hammer <- function( #' @aliases inverted_hammer CDLINVERTEDHAMMER <- inverted_hammer +#' @export +#' @usage NULL +#' @rdname inverted_hammer +#' +#' @aliases inverted_hammer +invertedHammer <- inverted_hammer + #' @usage NULL #' @aliases inverted_hammer #' @@ -115,7 +122,12 @@ inverted_hammer.data.frame <- function( ... ) { map_dfr( - NextMethod() + inverted_hammer.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) ) } @@ -129,7 +141,24 @@ inverted_hammer.matrix <- function( na.bridge = FALSE, ... ) { - NextMethod() + inverted_hammer.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDLINVERTEDHAMMER_lookback <- invertedHammer_lookback <- inverted_hammer_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CDLINVERTEDHAMMER_lookback + ) } #' @usage NULL @@ -167,7 +196,8 @@ inverted_hammer.plotly <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx @@ -190,7 +220,6 @@ inverted_hammer.plotly <- function( plotly_object } - #' @usage NULL #' @aliases inverted_hammer #' @@ -225,7 +254,8 @@ inverted_hammer.ggplot <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDLKICKING.R b/R/ta_CDLKICKING.R index 079feb387..320620fe1 100644 --- a/R/ta_CDLKICKING.R +++ b/R/ta_CDLKICKING.R @@ -115,7 +115,12 @@ kicking.data.frame <- function( ... ) { map_dfr( - NextMethod() + kicking.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) ) } @@ -129,7 +134,24 @@ kicking.matrix <- function( na.bridge = FALSE, ... ) { - NextMethod() + kicking.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDLKICKING_lookback <- kicking_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CDLKICKING_lookback + ) } #' @usage NULL @@ -167,7 +189,8 @@ kicking.plotly <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx @@ -190,7 +213,6 @@ kicking.plotly <- function( plotly_object } - #' @usage NULL #' @aliases kicking #' @@ -225,7 +247,8 @@ kicking.ggplot <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDLKICKINGBYLENGTH.R b/R/ta_CDLKICKINGBYLENGTH.R index 9e60f5a56..4fa625ff7 100644 --- a/R/ta_CDLKICKINGBYLENGTH.R +++ b/R/ta_CDLKICKINGBYLENGTH.R @@ -1,8 +1,8 @@ #' @export #' @family Pattern Recognition #' -#' @title Kicking Baby Length -#' @templateVar .title Kicking Baby Length +#' @title Kicking - bull/bear determined by the longer marubozu +#' @templateVar .title Kicking - bull/bear determined by the longer marubozu #' @templateVar .author Serkan Korkmaz #' @templateVar .fun kicking_baby_length #' @templateVar .family Pattern Recognition @@ -39,6 +39,13 @@ kicking_baby_length <- function( #' @aliases kicking_baby_length CDLKICKINGBYLENGTH <- kicking_baby_length +#' @export +#' @usage NULL +#' @rdname kicking_baby_length +#' +#' @aliases kicking_baby_length +kickingBabyLength <- kicking_baby_length + #' @usage NULL #' @aliases kicking_baby_length #' @@ -115,7 +122,12 @@ kicking_baby_length.data.frame <- function( ... ) { map_dfr( - NextMethod() + kicking_baby_length.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) ) } @@ -129,7 +141,24 @@ kicking_baby_length.matrix <- function( na.bridge = FALSE, ... ) { - NextMethod() + kicking_baby_length.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDLKICKINGBYLENGTH_lookback <- kickingBabyLength_lookback <- kicking_baby_length_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CDLKICKINGBYLENGTH_lookback + ) } #' @usage NULL @@ -167,7 +196,8 @@ kicking_baby_length.plotly <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx @@ -190,7 +220,6 @@ kicking_baby_length.plotly <- function( plotly_object } - #' @usage NULL #' @aliases kicking_baby_length #' @@ -225,7 +254,8 @@ kicking_baby_length.ggplot <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDLLADDERBOTTOM.R b/R/ta_CDLLADDERBOTTOM.R index a43a9cf41..51fc9e3e9 100644 --- a/R/ta_CDLLADDERBOTTOM.R +++ b/R/ta_CDLLADDERBOTTOM.R @@ -39,6 +39,13 @@ ladder_bottom <- function( #' @aliases ladder_bottom CDLLADDERBOTTOM <- ladder_bottom +#' @export +#' @usage NULL +#' @rdname ladder_bottom +#' +#' @aliases ladder_bottom +ladderBottom <- ladder_bottom + #' @usage NULL #' @aliases ladder_bottom #' @@ -115,7 +122,12 @@ ladder_bottom.data.frame <- function( ... ) { map_dfr( - NextMethod() + ladder_bottom.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) ) } @@ -129,7 +141,24 @@ ladder_bottom.matrix <- function( na.bridge = FALSE, ... ) { - NextMethod() + ladder_bottom.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDLLADDERBOTTOM_lookback <- ladderBottom_lookback <- ladder_bottom_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CDLLADDERBOTTOM_lookback + ) } #' @usage NULL @@ -167,7 +196,8 @@ ladder_bottom.plotly <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx @@ -190,7 +220,6 @@ ladder_bottom.plotly <- function( plotly_object } - #' @usage NULL #' @aliases ladder_bottom #' @@ -225,7 +254,8 @@ ladder_bottom.ggplot <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDLLONGLEGGEDDOJI.R b/R/ta_CDLLONGLEGGEDDOJI.R index 342e5c135..4084282b2 100644 --- a/R/ta_CDLLONGLEGGEDDOJI.R +++ b/R/ta_CDLLONGLEGGEDDOJI.R @@ -39,6 +39,13 @@ long_legged_doji <- function( #' @aliases long_legged_doji CDLLONGLEGGEDDOJI <- long_legged_doji +#' @export +#' @usage NULL +#' @rdname long_legged_doji +#' +#' @aliases long_legged_doji +longLeggedDoji <- long_legged_doji + #' @usage NULL #' @aliases long_legged_doji #' @@ -115,7 +122,12 @@ long_legged_doji.data.frame <- function( ... ) { map_dfr( - NextMethod() + long_legged_doji.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) ) } @@ -129,7 +141,24 @@ long_legged_doji.matrix <- function( na.bridge = FALSE, ... ) { - NextMethod() + long_legged_doji.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDLLONGLEGGEDDOJI_lookback <- longLeggedDoji_lookback <- long_legged_doji_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CDLLONGLEGGEDDOJI_lookback + ) } #' @usage NULL @@ -167,7 +196,8 @@ long_legged_doji.plotly <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx @@ -190,7 +220,6 @@ long_legged_doji.plotly <- function( plotly_object } - #' @usage NULL #' @aliases long_legged_doji #' @@ -225,7 +254,8 @@ long_legged_doji.ggplot <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDLLONGLINE.R b/R/ta_CDLLONGLINE.R index 7c907f73c..59d24e9b2 100644 --- a/R/ta_CDLLONGLINE.R +++ b/R/ta_CDLLONGLINE.R @@ -1,8 +1,8 @@ #' @export #' @family Pattern Recognition #' -#' @title Long Line -#' @templateVar .title Long Line +#' @title Long Line Candle +#' @templateVar .title Long Line Candle #' @templateVar .author Serkan Korkmaz #' @templateVar .fun long_line #' @templateVar .family Pattern Recognition @@ -39,6 +39,13 @@ long_line <- function( #' @aliases long_line CDLLONGLINE <- long_line +#' @export +#' @usage NULL +#' @rdname long_line +#' +#' @aliases long_line +longLine <- long_line + #' @usage NULL #' @aliases long_line #' @@ -115,7 +122,12 @@ long_line.data.frame <- function( ... ) { map_dfr( - NextMethod() + long_line.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) ) } @@ -129,7 +141,24 @@ long_line.matrix <- function( na.bridge = FALSE, ... ) { - NextMethod() + long_line.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDLLONGLINE_lookback <- longLine_lookback <- long_line_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CDLLONGLINE_lookback + ) } #' @usage NULL @@ -167,7 +196,8 @@ long_line.plotly <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx @@ -190,7 +220,6 @@ long_line.plotly <- function( plotly_object } - #' @usage NULL #' @aliases long_line #' @@ -225,7 +254,8 @@ long_line.ggplot <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDLMARUBOZU.R b/R/ta_CDLMARUBOZU.R index fe592ac37..ed540a839 100644 --- a/R/ta_CDLMARUBOZU.R +++ b/R/ta_CDLMARUBOZU.R @@ -115,7 +115,12 @@ marubozu.data.frame <- function( ... ) { map_dfr( - NextMethod() + marubozu.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) ) } @@ -129,7 +134,24 @@ marubozu.matrix <- function( na.bridge = FALSE, ... ) { - NextMethod() + marubozu.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDLMARUBOZU_lookback <- marubozu_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CDLMARUBOZU_lookback + ) } #' @usage NULL @@ -167,7 +189,8 @@ marubozu.plotly <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx @@ -190,7 +213,6 @@ marubozu.plotly <- function( plotly_object } - #' @usage NULL #' @aliases marubozu #' @@ -225,7 +247,8 @@ marubozu.ggplot <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDLMATCHINGLOW.R b/R/ta_CDLMATCHINGLOW.R index c1aab57d1..b55e7cb94 100644 --- a/R/ta_CDLMATCHINGLOW.R +++ b/R/ta_CDLMATCHINGLOW.R @@ -39,6 +39,13 @@ matching_low <- function( #' @aliases matching_low CDLMATCHINGLOW <- matching_low +#' @export +#' @usage NULL +#' @rdname matching_low +#' +#' @aliases matching_low +matchingLow <- matching_low + #' @usage NULL #' @aliases matching_low #' @@ -115,7 +122,12 @@ matching_low.data.frame <- function( ... ) { map_dfr( - NextMethod() + matching_low.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) ) } @@ -129,7 +141,24 @@ matching_low.matrix <- function( na.bridge = FALSE, ... ) { - NextMethod() + matching_low.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDLMATCHINGLOW_lookback <- matchingLow_lookback <- matching_low_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CDLMATCHINGLOW_lookback + ) } #' @usage NULL @@ -167,7 +196,8 @@ matching_low.plotly <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx @@ -190,7 +220,6 @@ matching_low.plotly <- function( plotly_object } - #' @usage NULL #' @aliases matching_low #' @@ -225,7 +254,8 @@ matching_low.ggplot <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDLMATHOLD.R b/R/ta_CDLMATHOLD.R index afe98eabf..180fd8a4c 100644 --- a/R/ta_CDLMATHOLD.R +++ b/R/ta_CDLMATHOLD.R @@ -26,7 +26,7 @@ mat_hold <- function( x, cols, - eps = 0, + penetration = 0.5, na.bridge = FALSE, ... ) { @@ -40,6 +40,13 @@ mat_hold <- function( #' @aliases mat_hold CDLMATHOLD <- mat_hold +#' @export +#' @usage NULL +#' @rdname mat_hold +#' +#' @aliases mat_hold +matHold <- mat_hold + #' @usage NULL #' @aliases mat_hold #' @@ -47,7 +54,7 @@ CDLMATHOLD <- mat_hold mat_hold.default <- function( x, cols, - eps = 0, + penetration = 0.5, na.bridge = FALSE, ... ) { @@ -91,7 +98,7 @@ mat_hold.default <- function( constructed_series[[2]], constructed_series[[3]], constructed_series[[4]], - eps, + as.double(penetration), normalize, as.logical(na.bridge) ) @@ -114,12 +121,18 @@ mat_hold.default <- function( mat_hold.data.frame <- function( x, cols, - eps = 0, + penetration = 0.5, na.bridge = FALSE, ... ) { map_dfr( - NextMethod() + mat_hold.default( + x = x, + cols = cols, + penetration = penetration, + na.bridge = na.bridge, + ... + ) ) } @@ -130,11 +143,31 @@ mat_hold.data.frame <- function( mat_hold.matrix <- function( x, cols, - eps = 0, + penetration = 0.5, + na.bridge = FALSE, + ... +) { + mat_hold.default( + x = x, + cols = cols, + penetration = penetration, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDLMATHOLD_lookback <- matHold_lookback <- mat_hold_lookback <- function( + x, + cols, + penetration = 0.5, na.bridge = FALSE, ... ) { - NextMethod() + .Call( + C_impl_ta_CDLMATHOLD_lookback, + as.double(penetration) + ) } #' @usage NULL @@ -144,7 +177,7 @@ mat_hold.matrix <- function( mat_hold.plotly <- function( x, cols, - eps = 0, + penetration = 0.5, na.bridge = FALSE, ... ) { @@ -174,7 +207,8 @@ mat_hold.plotly <- function( cols = rebuild_formula( names(constructed_series) ), - eps = eps + penetration = penetration, + na.bridge = na.bridge ) ## add conditional idx @@ -197,7 +231,6 @@ mat_hold.plotly <- function( plotly_object } - #' @usage NULL #' @aliases mat_hold #' @@ -205,7 +238,7 @@ mat_hold.plotly <- function( mat_hold.ggplot <- function( x, cols, - eps = 0, + penetration = 0.5, na.bridge = FALSE, ... ) { @@ -234,7 +267,8 @@ mat_hold.ggplot <- function( cols = rebuild_formula( names(constructed_series) ), - eps = eps + penetration = penetration, + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDLMORNINGDOJISTAR.R b/R/ta_CDLMORNINGDOJISTAR.R index 5aa05cb81..ef9075fb7 100644 --- a/R/ta_CDLMORNINGDOJISTAR.R +++ b/R/ta_CDLMORNINGDOJISTAR.R @@ -26,7 +26,7 @@ morning_doji_star <- function( x, cols, - eps = 0, + penetration = 0.3, na.bridge = FALSE, ... ) { @@ -40,6 +40,13 @@ morning_doji_star <- function( #' @aliases morning_doji_star CDLMORNINGDOJISTAR <- morning_doji_star +#' @export +#' @usage NULL +#' @rdname morning_doji_star +#' +#' @aliases morning_doji_star +morningDojiStar <- morning_doji_star + #' @usage NULL #' @aliases morning_doji_star #' @@ -47,7 +54,7 @@ CDLMORNINGDOJISTAR <- morning_doji_star morning_doji_star.default <- function( x, cols, - eps = 0, + penetration = 0.3, na.bridge = FALSE, ... ) { @@ -91,7 +98,7 @@ morning_doji_star.default <- function( constructed_series[[2]], constructed_series[[3]], constructed_series[[4]], - eps, + as.double(penetration), normalize, as.logical(na.bridge) ) @@ -114,12 +121,18 @@ morning_doji_star.default <- function( morning_doji_star.data.frame <- function( x, cols, - eps = 0, + penetration = 0.3, na.bridge = FALSE, ... ) { map_dfr( - NextMethod() + morning_doji_star.default( + x = x, + cols = cols, + penetration = penetration, + na.bridge = na.bridge, + ... + ) ) } @@ -130,11 +143,31 @@ morning_doji_star.data.frame <- function( morning_doji_star.matrix <- function( x, cols, - eps = 0, + penetration = 0.3, + na.bridge = FALSE, + ... +) { + morning_doji_star.default( + x = x, + cols = cols, + penetration = penetration, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDLMORNINGDOJISTAR_lookback <- morningDojiStar_lookback <- morning_doji_star_lookback <- function( + x, + cols, + penetration = 0.3, na.bridge = FALSE, ... ) { - NextMethod() + .Call( + C_impl_ta_CDLMORNINGDOJISTAR_lookback, + as.double(penetration) + ) } #' @usage NULL @@ -144,7 +177,7 @@ morning_doji_star.matrix <- function( morning_doji_star.plotly <- function( x, cols, - eps = 0, + penetration = 0.3, na.bridge = FALSE, ... ) { @@ -174,7 +207,8 @@ morning_doji_star.plotly <- function( cols = rebuild_formula( names(constructed_series) ), - eps = eps + penetration = penetration, + na.bridge = na.bridge ) ## add conditional idx @@ -197,7 +231,6 @@ morning_doji_star.plotly <- function( plotly_object } - #' @usage NULL #' @aliases morning_doji_star #' @@ -205,7 +238,7 @@ morning_doji_star.plotly <- function( morning_doji_star.ggplot <- function( x, cols, - eps = 0, + penetration = 0.3, na.bridge = FALSE, ... ) { @@ -234,7 +267,8 @@ morning_doji_star.ggplot <- function( cols = rebuild_formula( names(constructed_series) ), - eps = eps + penetration = penetration, + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDLMORNINGSTAR.R b/R/ta_CDLMORNINGSTAR.R index d2fd17206..94dbf01f7 100644 --- a/R/ta_CDLMORNINGSTAR.R +++ b/R/ta_CDLMORNINGSTAR.R @@ -26,7 +26,7 @@ morning_star <- function( x, cols, - eps = 0, + penetration = 0.3, na.bridge = FALSE, ... ) { @@ -40,6 +40,13 @@ morning_star <- function( #' @aliases morning_star CDLMORNINGSTAR <- morning_star +#' @export +#' @usage NULL +#' @rdname morning_star +#' +#' @aliases morning_star +morningStar <- morning_star + #' @usage NULL #' @aliases morning_star #' @@ -47,7 +54,7 @@ CDLMORNINGSTAR <- morning_star morning_star.default <- function( x, cols, - eps = 0, + penetration = 0.3, na.bridge = FALSE, ... ) { @@ -91,7 +98,7 @@ morning_star.default <- function( constructed_series[[2]], constructed_series[[3]], constructed_series[[4]], - eps, + as.double(penetration), normalize, as.logical(na.bridge) ) @@ -114,12 +121,18 @@ morning_star.default <- function( morning_star.data.frame <- function( x, cols, - eps = 0, + penetration = 0.3, na.bridge = FALSE, ... ) { map_dfr( - NextMethod() + morning_star.default( + x = x, + cols = cols, + penetration = penetration, + na.bridge = na.bridge, + ... + ) ) } @@ -130,11 +143,31 @@ morning_star.data.frame <- function( morning_star.matrix <- function( x, cols, - eps = 0, + penetration = 0.3, + na.bridge = FALSE, + ... +) { + morning_star.default( + x = x, + cols = cols, + penetration = penetration, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDLMORNINGSTAR_lookback <- morningStar_lookback <- morning_star_lookback <- function( + x, + cols, + penetration = 0.3, na.bridge = FALSE, ... ) { - NextMethod() + .Call( + C_impl_ta_CDLMORNINGSTAR_lookback, + as.double(penetration) + ) } #' @usage NULL @@ -144,7 +177,7 @@ morning_star.matrix <- function( morning_star.plotly <- function( x, cols, - eps = 0, + penetration = 0.3, na.bridge = FALSE, ... ) { @@ -174,7 +207,8 @@ morning_star.plotly <- function( cols = rebuild_formula( names(constructed_series) ), - eps = eps + penetration = penetration, + na.bridge = na.bridge ) ## add conditional idx @@ -197,7 +231,6 @@ morning_star.plotly <- function( plotly_object } - #' @usage NULL #' @aliases morning_star #' @@ -205,7 +238,7 @@ morning_star.plotly <- function( morning_star.ggplot <- function( x, cols, - eps = 0, + penetration = 0.3, na.bridge = FALSE, ... ) { @@ -234,7 +267,8 @@ morning_star.ggplot <- function( cols = rebuild_formula( names(constructed_series) ), - eps = eps + penetration = penetration, + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDLONNECK.R b/R/ta_CDLONNECK.R index 4d9ed7fe6..1158f827d 100644 --- a/R/ta_CDLONNECK.R +++ b/R/ta_CDLONNECK.R @@ -1,8 +1,8 @@ #' @export #' @family Pattern Recognition #' -#' @title On-Neck -#' @templateVar .title On-Neck +#' @title On-Neck Pattern +#' @templateVar .title On-Neck Pattern #' @templateVar .author Serkan Korkmaz #' @templateVar .fun on_neck #' @templateVar .family Pattern Recognition @@ -39,6 +39,13 @@ on_neck <- function( #' @aliases on_neck CDLONNECK <- on_neck +#' @export +#' @usage NULL +#' @rdname on_neck +#' +#' @aliases on_neck +onNeck <- on_neck + #' @usage NULL #' @aliases on_neck #' @@ -115,7 +122,12 @@ on_neck.data.frame <- function( ... ) { map_dfr( - NextMethod() + on_neck.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) ) } @@ -129,7 +141,24 @@ on_neck.matrix <- function( na.bridge = FALSE, ... ) { - NextMethod() + on_neck.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDLONNECK_lookback <- onNeck_lookback <- on_neck_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CDLONNECK_lookback + ) } #' @usage NULL @@ -167,7 +196,8 @@ on_neck.plotly <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx @@ -190,7 +220,6 @@ on_neck.plotly <- function( plotly_object } - #' @usage NULL #' @aliases on_neck #' @@ -225,7 +254,8 @@ on_neck.ggplot <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDLPIERCING.R b/R/ta_CDLPIERCING.R index 5df9f1330..efa7e433f 100644 --- a/R/ta_CDLPIERCING.R +++ b/R/ta_CDLPIERCING.R @@ -1,8 +1,8 @@ #' @export #' @family Pattern Recognition #' -#' @title Piercing -#' @templateVar .title Piercing +#' @title Piercing Pattern +#' @templateVar .title Piercing Pattern #' @templateVar .author Serkan Korkmaz #' @templateVar .fun piercing #' @templateVar .family Pattern Recognition @@ -115,7 +115,12 @@ piercing.data.frame <- function( ... ) { map_dfr( - NextMethod() + piercing.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) ) } @@ -129,7 +134,24 @@ piercing.matrix <- function( na.bridge = FALSE, ... ) { - NextMethod() + piercing.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDLPIERCING_lookback <- piercing_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CDLPIERCING_lookback + ) } #' @usage NULL @@ -167,7 +189,8 @@ piercing.plotly <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx @@ -190,7 +213,6 @@ piercing.plotly <- function( plotly_object } - #' @usage NULL #' @aliases piercing #' @@ -225,7 +247,8 @@ piercing.ggplot <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDLRICKSHAWMAN.R b/R/ta_CDLRICKSHAWMAN.R index f96e13579..4d697ae40 100644 --- a/R/ta_CDLRICKSHAWMAN.R +++ b/R/ta_CDLRICKSHAWMAN.R @@ -39,6 +39,13 @@ rickshaw_man <- function( #' @aliases rickshaw_man CDLRICKSHAWMAN <- rickshaw_man +#' @export +#' @usage NULL +#' @rdname rickshaw_man +#' +#' @aliases rickshaw_man +rickshawMan <- rickshaw_man + #' @usage NULL #' @aliases rickshaw_man #' @@ -115,7 +122,12 @@ rickshaw_man.data.frame <- function( ... ) { map_dfr( - NextMethod() + rickshaw_man.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) ) } @@ -129,7 +141,24 @@ rickshaw_man.matrix <- function( na.bridge = FALSE, ... ) { - NextMethod() + rickshaw_man.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDLRICKSHAWMAN_lookback <- rickshawMan_lookback <- rickshaw_man_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CDLRICKSHAWMAN_lookback + ) } #' @usage NULL @@ -167,7 +196,8 @@ rickshaw_man.plotly <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx @@ -190,7 +220,6 @@ rickshaw_man.plotly <- function( plotly_object } - #' @usage NULL #' @aliases rickshaw_man #' @@ -225,7 +254,8 @@ rickshaw_man.ggplot <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDLRISEFALL3METHODS.R b/R/ta_CDLRISEFALL3METHODS.R index 116fa14ee..17ce29d27 100644 --- a/R/ta_CDLRISEFALL3METHODS.R +++ b/R/ta_CDLRISEFALL3METHODS.R @@ -39,6 +39,13 @@ rise_fall_3_methods <- function( #' @aliases rise_fall_3_methods CDLRISEFALL3METHODS <- rise_fall_3_methods +#' @export +#' @usage NULL +#' @rdname rise_fall_3_methods +#' +#' @aliases rise_fall_3_methods +riseFall3Methods <- rise_fall_3_methods + #' @usage NULL #' @aliases rise_fall_3_methods #' @@ -115,7 +122,12 @@ rise_fall_3_methods.data.frame <- function( ... ) { map_dfr( - NextMethod() + rise_fall_3_methods.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) ) } @@ -129,7 +141,24 @@ rise_fall_3_methods.matrix <- function( na.bridge = FALSE, ... ) { - NextMethod() + rise_fall_3_methods.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDLRISEFALL3METHODS_lookback <- riseFall3Methods_lookback <- rise_fall_3_methods_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CDLRISEFALL3METHODS_lookback + ) } #' @usage NULL @@ -167,7 +196,8 @@ rise_fall_3_methods.plotly <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx @@ -190,7 +220,6 @@ rise_fall_3_methods.plotly <- function( plotly_object } - #' @usage NULL #' @aliases rise_fall_3_methods #' @@ -225,7 +254,8 @@ rise_fall_3_methods.ggplot <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDLSEPARATINGLINES.R b/R/ta_CDLSEPARATINGLINES.R index e0ff5f769..da857c8f0 100644 --- a/R/ta_CDLSEPARATINGLINES.R +++ b/R/ta_CDLSEPARATINGLINES.R @@ -39,6 +39,13 @@ separating_lines <- function( #' @aliases separating_lines CDLSEPARATINGLINES <- separating_lines +#' @export +#' @usage NULL +#' @rdname separating_lines +#' +#' @aliases separating_lines +separatingLines <- separating_lines + #' @usage NULL #' @aliases separating_lines #' @@ -115,7 +122,12 @@ separating_lines.data.frame <- function( ... ) { map_dfr( - NextMethod() + separating_lines.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) ) } @@ -129,7 +141,24 @@ separating_lines.matrix <- function( na.bridge = FALSE, ... ) { - NextMethod() + separating_lines.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDLSEPARATINGLINES_lookback <- separatingLines_lookback <- separating_lines_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CDLSEPARATINGLINES_lookback + ) } #' @usage NULL @@ -167,7 +196,8 @@ separating_lines.plotly <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx @@ -190,7 +220,6 @@ separating_lines.plotly <- function( plotly_object } - #' @usage NULL #' @aliases separating_lines #' @@ -225,7 +254,8 @@ separating_lines.ggplot <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDLSHOOTINGSTAR.R b/R/ta_CDLSHOOTINGSTAR.R index a99cea3f1..77b1f68c3 100644 --- a/R/ta_CDLSHOOTINGSTAR.R +++ b/R/ta_CDLSHOOTINGSTAR.R @@ -39,6 +39,13 @@ shooting_star <- function( #' @aliases shooting_star CDLSHOOTINGSTAR <- shooting_star +#' @export +#' @usage NULL +#' @rdname shooting_star +#' +#' @aliases shooting_star +shootingStar <- shooting_star + #' @usage NULL #' @aliases shooting_star #' @@ -115,7 +122,12 @@ shooting_star.data.frame <- function( ... ) { map_dfr( - NextMethod() + shooting_star.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) ) } @@ -129,7 +141,24 @@ shooting_star.matrix <- function( na.bridge = FALSE, ... ) { - NextMethod() + shooting_star.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDLSHOOTINGSTAR_lookback <- shootingStar_lookback <- shooting_star_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CDLSHOOTINGSTAR_lookback + ) } #' @usage NULL @@ -167,7 +196,8 @@ shooting_star.plotly <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx @@ -190,7 +220,6 @@ shooting_star.plotly <- function( plotly_object } - #' @usage NULL #' @aliases shooting_star #' @@ -225,7 +254,8 @@ shooting_star.ggplot <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDLSHORTLINE.R b/R/ta_CDLSHORTLINE.R index c5dd4c8bf..4044bb321 100644 --- a/R/ta_CDLSHORTLINE.R +++ b/R/ta_CDLSHORTLINE.R @@ -39,6 +39,13 @@ short_line <- function( #' @aliases short_line CDLSHORTLINE <- short_line +#' @export +#' @usage NULL +#' @rdname short_line +#' +#' @aliases short_line +shortLine <- short_line + #' @usage NULL #' @aliases short_line #' @@ -115,7 +122,12 @@ short_line.data.frame <- function( ... ) { map_dfr( - NextMethod() + short_line.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) ) } @@ -129,7 +141,24 @@ short_line.matrix <- function( na.bridge = FALSE, ... ) { - NextMethod() + short_line.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDLSHORTLINE_lookback <- shortLine_lookback <- short_line_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CDLSHORTLINE_lookback + ) } #' @usage NULL @@ -167,7 +196,8 @@ short_line.plotly <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx @@ -190,7 +220,6 @@ short_line.plotly <- function( plotly_object } - #' @usage NULL #' @aliases short_line #' @@ -225,7 +254,8 @@ short_line.ggplot <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDLSPINNINGTOP.R b/R/ta_CDLSPINNINGTOP.R index cfb3609dd..e03f61f18 100644 --- a/R/ta_CDLSPINNINGTOP.R +++ b/R/ta_CDLSPINNINGTOP.R @@ -39,6 +39,13 @@ spinning_top <- function( #' @aliases spinning_top CDLSPINNINGTOP <- spinning_top +#' @export +#' @usage NULL +#' @rdname spinning_top +#' +#' @aliases spinning_top +spinningTop <- spinning_top + #' @usage NULL #' @aliases spinning_top #' @@ -115,7 +122,12 @@ spinning_top.data.frame <- function( ... ) { map_dfr( - NextMethod() + spinning_top.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) ) } @@ -129,7 +141,24 @@ spinning_top.matrix <- function( na.bridge = FALSE, ... ) { - NextMethod() + spinning_top.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDLSPINNINGTOP_lookback <- spinningTop_lookback <- spinning_top_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CDLSPINNINGTOP_lookback + ) } #' @usage NULL @@ -167,7 +196,8 @@ spinning_top.plotly <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx @@ -190,7 +220,6 @@ spinning_top.plotly <- function( plotly_object } - #' @usage NULL #' @aliases spinning_top #' @@ -225,7 +254,8 @@ spinning_top.ggplot <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDLSTALLEDPATTERN.R b/R/ta_CDLSTALLEDPATTERN.R index 472c88d01..7812764a2 100644 --- a/R/ta_CDLSTALLEDPATTERN.R +++ b/R/ta_CDLSTALLEDPATTERN.R @@ -39,6 +39,13 @@ stalled_pattern <- function( #' @aliases stalled_pattern CDLSTALLEDPATTERN <- stalled_pattern +#' @export +#' @usage NULL +#' @rdname stalled_pattern +#' +#' @aliases stalled_pattern +stalledPattern <- stalled_pattern + #' @usage NULL #' @aliases stalled_pattern #' @@ -115,7 +122,12 @@ stalled_pattern.data.frame <- function( ... ) { map_dfr( - NextMethod() + stalled_pattern.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) ) } @@ -129,7 +141,24 @@ stalled_pattern.matrix <- function( na.bridge = FALSE, ... ) { - NextMethod() + stalled_pattern.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDLSTALLEDPATTERN_lookback <- stalledPattern_lookback <- stalled_pattern_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CDLSTALLEDPATTERN_lookback + ) } #' @usage NULL @@ -167,7 +196,8 @@ stalled_pattern.plotly <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx @@ -190,7 +220,6 @@ stalled_pattern.plotly <- function( plotly_object } - #' @usage NULL #' @aliases stalled_pattern #' @@ -225,7 +254,8 @@ stalled_pattern.ggplot <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDLSTICKSANDWICH.R b/R/ta_CDLSTICKSANDWICH.R index 75b91ed4c..5c554bea9 100644 --- a/R/ta_CDLSTICKSANDWICH.R +++ b/R/ta_CDLSTICKSANDWICH.R @@ -39,6 +39,13 @@ stick_sandwich <- function( #' @aliases stick_sandwich CDLSTICKSANDWICH <- stick_sandwich +#' @export +#' @usage NULL +#' @rdname stick_sandwich +#' +#' @aliases stick_sandwich +stickSandwich <- stick_sandwich + #' @usage NULL #' @aliases stick_sandwich #' @@ -115,7 +122,12 @@ stick_sandwich.data.frame <- function( ... ) { map_dfr( - NextMethod() + stick_sandwich.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) ) } @@ -129,7 +141,24 @@ stick_sandwich.matrix <- function( na.bridge = FALSE, ... ) { - NextMethod() + stick_sandwich.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDLSTICKSANDWICH_lookback <- stickSandwich_lookback <- stick_sandwich_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CDLSTICKSANDWICH_lookback + ) } #' @usage NULL @@ -167,7 +196,8 @@ stick_sandwich.plotly <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx @@ -190,7 +220,6 @@ stick_sandwich.plotly <- function( plotly_object } - #' @usage NULL #' @aliases stick_sandwich #' @@ -225,7 +254,8 @@ stick_sandwich.ggplot <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDLTAKURI.R b/R/ta_CDLTAKURI.R index da480fd62..6273baa29 100644 --- a/R/ta_CDLTAKURI.R +++ b/R/ta_CDLTAKURI.R @@ -1,8 +1,8 @@ #' @export #' @family Pattern Recognition #' -#' @title Takuri -#' @templateVar .title Takuri +#' @title Takuri (Dragonfly Doji with very long lower shadow) +#' @templateVar .title Takuri (Dragonfly Doji with very long lower shadow) #' @templateVar .author Serkan Korkmaz #' @templateVar .fun takuri #' @templateVar .family Pattern Recognition @@ -115,7 +115,12 @@ takuri.data.frame <- function( ... ) { map_dfr( - NextMethod() + takuri.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) ) } @@ -129,7 +134,24 @@ takuri.matrix <- function( na.bridge = FALSE, ... ) { - NextMethod() + takuri.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDLTAKURI_lookback <- takuri_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CDLTAKURI_lookback + ) } #' @usage NULL @@ -167,7 +189,8 @@ takuri.plotly <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx @@ -190,7 +213,6 @@ takuri.plotly <- function( plotly_object } - #' @usage NULL #' @aliases takuri #' @@ -225,7 +247,8 @@ takuri.ggplot <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDLTASUKIGAP.R b/R/ta_CDLTASUKIGAP.R index 5ecd06cad..eb77bc8a3 100644 --- a/R/ta_CDLTASUKIGAP.R +++ b/R/ta_CDLTASUKIGAP.R @@ -39,6 +39,13 @@ tasuki_gap <- function( #' @aliases tasuki_gap CDLTASUKIGAP <- tasuki_gap +#' @export +#' @usage NULL +#' @rdname tasuki_gap +#' +#' @aliases tasuki_gap +tasukiGap <- tasuki_gap + #' @usage NULL #' @aliases tasuki_gap #' @@ -115,7 +122,12 @@ tasuki_gap.data.frame <- function( ... ) { map_dfr( - NextMethod() + tasuki_gap.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) ) } @@ -129,7 +141,24 @@ tasuki_gap.matrix <- function( na.bridge = FALSE, ... ) { - NextMethod() + tasuki_gap.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDLTASUKIGAP_lookback <- tasukiGap_lookback <- tasuki_gap_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CDLTASUKIGAP_lookback + ) } #' @usage NULL @@ -167,7 +196,8 @@ tasuki_gap.plotly <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx @@ -190,7 +220,6 @@ tasuki_gap.plotly <- function( plotly_object } - #' @usage NULL #' @aliases tasuki_gap #' @@ -225,7 +254,8 @@ tasuki_gap.ggplot <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDLTHRUSTING.R b/R/ta_CDLTHRUSTING.R index 08b496e3e..e724fe13a 100644 --- a/R/ta_CDLTHRUSTING.R +++ b/R/ta_CDLTHRUSTING.R @@ -1,8 +1,8 @@ #' @export #' @family Pattern Recognition #' -#' @title Thrusting -#' @templateVar .title Thrusting +#' @title Thrusting Pattern +#' @templateVar .title Thrusting Pattern #' @templateVar .author Serkan Korkmaz #' @templateVar .fun thrusting #' @templateVar .family Pattern Recognition @@ -115,7 +115,12 @@ thrusting.data.frame <- function( ... ) { map_dfr( - NextMethod() + thrusting.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) ) } @@ -129,7 +134,24 @@ thrusting.matrix <- function( na.bridge = FALSE, ... ) { - NextMethod() + thrusting.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDLTHRUSTING_lookback <- thrusting_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CDLTHRUSTING_lookback + ) } #' @usage NULL @@ -167,7 +189,8 @@ thrusting.plotly <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx @@ -190,7 +213,6 @@ thrusting.plotly <- function( plotly_object } - #' @usage NULL #' @aliases thrusting #' @@ -225,7 +247,8 @@ thrusting.ggplot <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDLTRISTAR.R b/R/ta_CDLTRISTAR.R index fb99feeef..46d99997a 100644 --- a/R/ta_CDLTRISTAR.R +++ b/R/ta_CDLTRISTAR.R @@ -1,8 +1,8 @@ #' @export #' @family Pattern Recognition #' -#' @title Tristar -#' @templateVar .title Tristar +#' @title Tristar Pattern +#' @templateVar .title Tristar Pattern #' @templateVar .author Serkan Korkmaz #' @templateVar .fun tristar #' @templateVar .family Pattern Recognition @@ -115,7 +115,12 @@ tristar.data.frame <- function( ... ) { map_dfr( - NextMethod() + tristar.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) ) } @@ -129,7 +134,24 @@ tristar.matrix <- function( na.bridge = FALSE, ... ) { - NextMethod() + tristar.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDLTRISTAR_lookback <- tristar_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CDLTRISTAR_lookback + ) } #' @usage NULL @@ -167,7 +189,8 @@ tristar.plotly <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx @@ -190,7 +213,6 @@ tristar.plotly <- function( plotly_object } - #' @usage NULL #' @aliases tristar #' @@ -225,7 +247,8 @@ tristar.ggplot <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDLUNIQUE3RIVER.R b/R/ta_CDLUNIQUE3RIVER.R index ee608e3ce..19c84bbe8 100644 --- a/R/ta_CDLUNIQUE3RIVER.R +++ b/R/ta_CDLUNIQUE3RIVER.R @@ -1,8 +1,8 @@ #' @export #' @family Pattern Recognition #' -#' @title Unique Three River -#' @templateVar .title Unique Three River +#' @title Unique 3 River +#' @templateVar .title Unique 3 River #' @templateVar .author Serkan Korkmaz #' @templateVar .fun unique_3_river #' @templateVar .family Pattern Recognition @@ -39,6 +39,13 @@ unique_3_river <- function( #' @aliases unique_3_river CDLUNIQUE3RIVER <- unique_3_river +#' @export +#' @usage NULL +#' @rdname unique_3_river +#' +#' @aliases unique_3_river +unique3River <- unique_3_river + #' @usage NULL #' @aliases unique_3_river #' @@ -115,7 +122,12 @@ unique_3_river.data.frame <- function( ... ) { map_dfr( - NextMethod() + unique_3_river.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) ) } @@ -129,7 +141,24 @@ unique_3_river.matrix <- function( na.bridge = FALSE, ... ) { - NextMethod() + unique_3_river.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDLUNIQUE3RIVER_lookback <- unique3River_lookback <- unique_3_river_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CDLUNIQUE3RIVER_lookback + ) } #' @usage NULL @@ -167,7 +196,8 @@ unique_3_river.plotly <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx @@ -190,7 +220,6 @@ unique_3_river.plotly <- function( plotly_object } - #' @usage NULL #' @aliases unique_3_river #' @@ -225,7 +254,8 @@ unique_3_river.ggplot <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDLUPSIDEGAP2CROWS.R b/R/ta_CDLUPSIDEGAP2CROWS.R index 977c2b4e0..0f4530ec1 100644 --- a/R/ta_CDLUPSIDEGAP2CROWS.R +++ b/R/ta_CDLUPSIDEGAP2CROWS.R @@ -39,6 +39,13 @@ upside_gap_2_crows <- function( #' @aliases upside_gap_2_crows CDLUPSIDEGAP2CROWS <- upside_gap_2_crows +#' @export +#' @usage NULL +#' @rdname upside_gap_2_crows +#' +#' @aliases upside_gap_2_crows +upsideGap2Crows <- upside_gap_2_crows + #' @usage NULL #' @aliases upside_gap_2_crows #' @@ -115,7 +122,12 @@ upside_gap_2_crows.data.frame <- function( ... ) { map_dfr( - NextMethod() + upside_gap_2_crows.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) ) } @@ -129,7 +141,24 @@ upside_gap_2_crows.matrix <- function( na.bridge = FALSE, ... ) { - NextMethod() + upside_gap_2_crows.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDLUPSIDEGAP2CROWS_lookback <- upsideGap2Crows_lookback <- upside_gap_2_crows_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CDLUPSIDEGAP2CROWS_lookback + ) } #' @usage NULL @@ -167,7 +196,8 @@ upside_gap_2_crows.plotly <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx @@ -190,7 +220,6 @@ upside_gap_2_crows.plotly <- function( plotly_object } - #' @usage NULL #' @aliases upside_gap_2_crows #' @@ -225,7 +254,8 @@ upside_gap_2_crows.ggplot <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CDLXSIDEGAP3METHODS.R b/R/ta_CDLXSIDEGAP3METHODS.R index ee6fa3088..50b926a4a 100644 --- a/R/ta_CDLXSIDEGAP3METHODS.R +++ b/R/ta_CDLXSIDEGAP3METHODS.R @@ -39,6 +39,13 @@ xside_gap_3_methods <- function( #' @aliases xside_gap_3_methods CDLXSIDEGAP3METHODS <- xside_gap_3_methods +#' @export +#' @usage NULL +#' @rdname xside_gap_3_methods +#' +#' @aliases xside_gap_3_methods +xsideGap3Methods <- xside_gap_3_methods + #' @usage NULL #' @aliases xside_gap_3_methods #' @@ -115,7 +122,12 @@ xside_gap_3_methods.data.frame <- function( ... ) { map_dfr( - NextMethod() + xside_gap_3_methods.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) ) } @@ -129,7 +141,24 @@ xside_gap_3_methods.matrix <- function( na.bridge = FALSE, ... ) { - NextMethod() + xside_gap_3_methods.default( + x = x, + cols = cols, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +CDLXSIDEGAP3METHODS_lookback <- xsideGap3Methods_lookback <- xside_gap_3_methods_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CDLXSIDEGAP3METHODS_lookback + ) } #' @usage NULL @@ -167,7 +196,8 @@ xside_gap_3_methods.plotly <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx @@ -190,7 +220,6 @@ xside_gap_3_methods.plotly <- function( plotly_object } - #' @usage NULL #' @aliases xside_gap_3_methods #' @@ -225,7 +254,8 @@ xside_gap_3_methods.ggplot <- function( x = constructed_series, cols = rebuild_formula( names(constructed_series) - ) + ), + na.bridge = na.bridge ) ## add conditional idx diff --git a/R/ta_CMO.R b/R/ta_CMO.R index 746249e3e..87a726285 100644 --- a/R/ta_CMO.R +++ b/R/ta_CMO.R @@ -1,22 +1,23 @@ #' @export -#' @family Momentum Indicator +#' @family Momentum Indicators #' #' @title Chande Momentum Oscillator #' @templateVar .title Chande Momentum Oscillator #' @templateVar .author Serkan Korkmaz #' @templateVar .fun chande_momentum_oscillator -#' @templateVar .family Momentum Indicator -#' @templateVar .formula ~ close +#' @templateVar .family Momentum Indicators +#' @templateVar .formula ~close #' ## splice:documentation:start ## splice:documentation:end #' #' @template description +#' #' @template returns chande_momentum_oscillator <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -30,6 +31,13 @@ chande_momentum_oscillator <- function( #' @aliases chande_momentum_oscillator CMO <- chande_momentum_oscillator +#' @export +#' @usage NULL +#' @rdname chande_momentum_oscillator +#' +#' @aliases chande_momentum_oscillator +chandeMomentumOscillator <- chande_momentum_oscillator + #' @usage NULL #' @aliases chande_momentum_oscillator #' @@ -37,7 +45,7 @@ CMO <- chande_momentum_oscillator chande_momentum_oscillator.default <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -64,10 +72,8 @@ chande_momentum_oscillator.default <- function( ## return as data.frame x <- .Call( C_impl_ta_CMO, - ## splice:call:start constructed_series[[1]], - as.integer(n), - ## splice:call:end + as.integer(timePeriod), as.logical(na.bridge) ) @@ -85,7 +91,7 @@ chande_momentum_oscillator.default <- function( chande_momentum_oscillator.data.frame <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -93,7 +99,7 @@ chande_momentum_oscillator.data.frame <- function( chande_momentum_oscillator.default( x = x, cols = cols, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge, ... ) @@ -107,19 +113,32 @@ chande_momentum_oscillator.data.frame <- function( chande_momentum_oscillator.matrix <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { chande_momentum_oscillator.default( x = x, cols = cols, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge, ... ) } +#' @usage NULL +CMO_lookback <- chandeMomentumOscillator_lookback <- chande_momentum_oscillator_lookback <- function( + x, + cols, + timePeriod = 14, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CMO_lookback, + as.integer(timePeriod) + ) +} #' @usage NULL #' @aliases chande_momentum_oscillator @@ -128,7 +147,7 @@ chande_momentum_oscillator.matrix <- function( chande_momentum_oscillator.numeric <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -144,29 +163,18 @@ chande_momentum_oscillator.numeric <- function( ## to 'C' x <- .Call( C_impl_ta_CMO, - ## splice:numeric:start as.double(x), - as.integer(n), - ## splice:numeric:end + as.integer(timePeriod), 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 #' @aliases chande_momentum_oscillator #' @@ -174,7 +182,7 @@ chande_momentum_oscillator.numeric <- function( chande_momentum_oscillator.plotly <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ## splice:optional-plotly:start lower_bound = -50, @@ -209,7 +217,7 @@ chande_momentum_oscillator.plotly <- function( cols = rebuild_formula( names(constructed_series) ), - n = n, + timePeriod = timePeriod, na.bridge = TRUE ) @@ -227,7 +235,7 @@ chande_momentum_oscillator.plotly <- function( ## construct {plotly}-object ## splice:plotly-assembly:start - name <- sprintf("CMO(%d)", n) + name <- sprintf("CMO(%d)", timePeriod) decorators <- list( function(p) add_limit_ly(p, y_range = c(-100, 100)) @@ -267,7 +275,8 @@ chande_momentum_oscillator.plotly <- function( } ), data = constructed_indicator[, values_to_extract, drop = FALSE], - values_to_extract = values_to_extract + values_to_extract = values_to_extract, + name = get0(x = "name", ifnotfound = NULL) ) state <- .chart_state() @@ -283,11 +292,11 @@ chande_momentum_oscillator.plotly <- function( chande_momentum_oscillator.ggplot <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, + title, ## splice:optional-ggplot:start ## splice:optional-ggplot:end - title, ... ) { ## check ggplot2 availability @@ -315,7 +324,7 @@ chande_momentum_oscillator.ggplot <- function( cols = rebuild_formula( names(constructed_series) ), - n = n, + timePeriod = timePeriod, na.bridge = TRUE ) @@ -340,7 +349,7 @@ chande_momentum_oscillator.ggplot <- function( ggplot_line(50), list(y = "CMO") ) - name <- sprintf("CMO(%d)", n) + name <- sprintf("CMO(%d)", timePeriod) ## splice:ggplot-assembly:end ggplot_object <- add_last_value_gg( diff --git a/R/ta_CORREL.R b/R/ta_CORREL.R index ebfabfb6a..2f2aa1a1e 100644 --- a/R/ta_CORREL.R +++ b/R/ta_CORREL.R @@ -1,8 +1,8 @@ #' @export -#' @family Rolling Statistic +#' @family Rolling Statistics #' -#' @title Rolling Correlation -#' @templateVar .title Rolling Correlation +#' @title Pearson's Correlation Coefficient (r) +#' @templateVar .title Pearson's Correlation Coefficient (r) #' @templateVar .author Serkan Korkmaz #' @templateVar .fun rolling_correlation #' @@ -10,12 +10,14 @@ ## splice:documentation:end #' #' @template rolling_description +#' #' @template rolling_returns rolling_correlation <- function( x, y, - n = 30, - na.bridge = FALSE + timePeriod = 30, + na.bridge = FALSE, + ... ) { UseMethod("rolling_correlation") } @@ -27,6 +29,13 @@ rolling_correlation <- function( #' @aliases rolling_correlation CORREL <- rolling_correlation +#' @export +#' @usage NULL +#' @rdname rolling_correlation +#' +#' @aliases rolling_correlation +rollingCorrelation <- rolling_correlation + #' @usage NULL #' @aliases rolling_correlation #' @@ -34,8 +43,9 @@ CORREL <- rolling_correlation rolling_correlation.default <- function( x, y, - n = 30, - na.bridge = FALSE + timePeriod = 30, + na.bridge = FALSE, + ... ) { ## calculate indicator and ## return as data.frame @@ -44,13 +54,18 @@ rolling_correlation.default <- function( ## splice:call:start as.double(x), as.double(y), - as.integer(n), + as.integer(timePeriod), ## splice:call:end as.logical(na.bridge) ) + ## strip dimensions + ## while preserving + ## attributes + dim(x) <- NULL + ## return indicator - as.double(x) + x } #' @usage NULL @@ -60,18 +75,37 @@ rolling_correlation.default <- function( rolling_correlation.numeric <- function( x, y, - n = 30, - na.bridge = FALSE + timePeriod = 30, + na.bridge = FALSE, + ... ) { ## calculate indicator and ## return as data.frame x <- rolling_correlation.default( x = x, y = y, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge ) + ## strip dimensions + ## while preserving + ## attributes + dim(x) <- NULL + ## return indicator - as.double(x) + x +} + +#' @usage NULL +CORREL_lookback <- rollingCorrelation_lookback <- rolling_correlation_lookback <- function( + x, + timePeriod = 30, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_CORREL_lookback, + as.integer(timePeriod) + ) } diff --git a/R/ta_DEMA.R b/R/ta_DEMA.R index 8dc00b6cf..80ae501f6 100644 --- a/R/ta_DEMA.R +++ b/R/ta_DEMA.R @@ -1,11 +1,11 @@ #' @export -#' @family Overlap Study +#' @family Overlap Studies #' #' @title Double Exponential Moving Average #' @templateVar .title Double Exponential Moving Average #' @templateVar .author Serkan Korkmaz #' @templateVar .fun double_exponential_moving_average -#' @templateVar .family Overlap Study +#' @templateVar .family Overlap Studies #' @templateVar .formula ~close #' ## splice:documentation:start @@ -18,11 +18,12 @@ #' indicators that supports various Moving Average specifications. #' #' @template description +#' #' @template returns double_exponential_moving_average <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, ... ) { @@ -33,13 +34,19 @@ double_exponential_moving_average <- function( ## from call x <- structure( list( - n = if (missing(n)) 30L else as.integer(n), + timePeriod = if (missing(timePeriod)) { + 30L + } else { + as.integer(timePeriod) + }, maType = 3L - ) + ), + class = "maType" ) return(x) } + UseMethod("double_exponential_moving_average") } @@ -50,6 +57,13 @@ double_exponential_moving_average <- function( #' @aliases double_exponential_moving_average DEMA <- double_exponential_moving_average +#' @export +#' @usage NULL +#' @rdname double_exponential_moving_average +#' +#' @aliases double_exponential_moving_average +doubleExponentialMovingAverage <- double_exponential_moving_average + #' @usage NULL #' @aliases double_exponential_moving_average #' @@ -57,7 +71,7 @@ DEMA <- double_exponential_moving_average double_exponential_moving_average.default <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, ... ) { @@ -84,8 +98,8 @@ double_exponential_moving_average.default <- function( ## return as data.frame x <- .Call( C_impl_ta_DEMA, - as.double(constructed_series[[1]]), - as.integer(n), + constructed_series[[1]], + as.integer(timePeriod), as.logical(na.bridge) ) @@ -103,12 +117,18 @@ double_exponential_moving_average.default <- function( double_exponential_moving_average.data.frame <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, ... ) { map_dfr( - NextMethod() + double_exponential_moving_average.default( + x = x, + cols = cols, + timePeriod = timePeriod, + na.bridge = na.bridge, + ... + ) ) } @@ -119,17 +139,14 @@ double_exponential_moving_average.data.frame <- function( double_exponential_moving_average.matrix <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, ... ) { - ## pass directly to - ## double_exponential_moving_average.default to avoid - ## shenanigans with NextMethod() double_exponential_moving_average.default( x = x, cols = cols, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge, ... ) @@ -142,7 +159,7 @@ double_exponential_moving_average.matrix <- function( double_exponential_moving_average.numeric <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, ... ) { @@ -159,25 +176,32 @@ double_exponential_moving_average.numeric <- function( x <- .Call( C_impl_ta_DEMA, as.double(x), - as.integer(n), + as.integer(timePeriod), 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 <- doubleExponentialMovingAverage_lookback <- double_exponential_moving_average_lookback <- function( + x, + cols, + timePeriod = 30, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_DEMA_lookback, + as.integer(timePeriod) + ) +} + + #' @usage NULL #' @aliases double_exponential_moving_average #' @@ -185,7 +209,7 @@ double_exponential_moving_average.numeric <- function( double_exponential_moving_average.plotly <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, ... ) { @@ -215,7 +239,8 @@ double_exponential_moving_average.plotly <- function( cols = rebuild_formula( names(constructed_series) ), - n = n + timePeriod = timePeriod, + na.bridge = TRUE ) ## add conditional idx @@ -238,15 +263,15 @@ double_exponential_moving_average.plotly <- function( ) ) ), - name = label("DEMA", n), - decorators = list() + name = label("DEMA", timePeriod), + decorators = list(), + data = constructed_indicator ) state[["main"]] <- plotly_object plotly_object } - #' @usage NULL #' @aliases double_exponential_moving_average #' @@ -254,7 +279,7 @@ double_exponential_moving_average.plotly <- function( double_exponential_moving_average.ggplot <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, ... ) { @@ -283,7 +308,8 @@ double_exponential_moving_average.ggplot <- function( cols = rebuild_formula( names(constructed_series) ), - n = n + timePeriod = timePeriod, + na.bridge = TRUE ) ## add conditional idx @@ -300,7 +326,7 @@ double_exponential_moving_average.ggplot <- function( y = "DEMA" ) ), - name = label("DEMA", n), + name = label("DEMA", timePeriod), decorators = list(), data = constructed_indicator ) diff --git a/R/ta_DX.R b/R/ta_DX.R index 1db4d604a..4670c97f5 100644 --- a/R/ta_DX.R +++ b/R/ta_DX.R @@ -1,22 +1,23 @@ #' @export -#' @family Momentum Indicator +#' @family Momentum Indicators #' #' @title Directional Movement Index #' @templateVar .title Directional Movement Index #' @templateVar .author Serkan Korkmaz #' @templateVar .fun directional_movement_index -#' @templateVar .family Momentum Indicator +#' @templateVar .family Momentum Indicators #' @templateVar .formula ~high + low + close #' ## splice:documentation:start ## splice:documentation:end #' #' @template description +#' #' @template returns directional_movement_index <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -30,6 +31,13 @@ directional_movement_index <- function( #' @aliases directional_movement_index DX <- directional_movement_index +#' @export +#' @usage NULL +#' @rdname directional_movement_index +#' +#' @aliases directional_movement_index +directionalMovementIndex <- directional_movement_index + #' @usage NULL #' @aliases directional_movement_index #' @@ -37,7 +45,7 @@ DX <- directional_movement_index directional_movement_index.default <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -64,12 +72,10 @@ directional_movement_index.default <- function( ## return as data.frame x <- .Call( C_impl_ta_DX, - ## splice:call:start constructed_series[[1]], constructed_series[[2]], constructed_series[[3]], - as.integer(n), - ## splice:call:end + as.integer(timePeriod), as.logical(na.bridge) ) @@ -87,7 +93,7 @@ directional_movement_index.default <- function( directional_movement_index.data.frame <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -95,7 +101,7 @@ directional_movement_index.data.frame <- function( directional_movement_index.default( x = x, cols = cols, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge, ... ) @@ -109,19 +115,32 @@ directional_movement_index.data.frame <- function( directional_movement_index.matrix <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { directional_movement_index.default( x = x, cols = cols, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge, ... ) } +#' @usage NULL +DX_lookback <- directionalMovementIndex_lookback <- directional_movement_index_lookback <- function( + x, + cols, + timePeriod = 14, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_DX_lookback, + as.integer(timePeriod) + ) +} #' @usage NULL #' @aliases directional_movement_index @@ -130,7 +149,7 @@ directional_movement_index.matrix <- function( directional_movement_index.plotly <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ## splice:optional-plotly:start ## splice:optional-plotly:end @@ -163,7 +182,7 @@ directional_movement_index.plotly <- function( cols = rebuild_formula( names(constructed_series) ), - n = n, + timePeriod = timePeriod, na.bridge = TRUE ) @@ -182,7 +201,7 @@ directional_movement_index.plotly <- function( ## splice:plotly-assembly:start name <- sprintf( "DX(%d)", - n + timePeriod ) decorators <- list( @@ -216,7 +235,8 @@ directional_movement_index.plotly <- function( } ), data = constructed_indicator[, values_to_extract, drop = FALSE], - values_to_extract = values_to_extract + values_to_extract = values_to_extract, + name = get0(x = "name", ifnotfound = NULL) ) state <- .chart_state() @@ -232,11 +252,11 @@ directional_movement_index.plotly <- function( directional_movement_index.ggplot <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, + title, ## splice:optional-ggplot:start ## splice:optional-ggplot:end - title, ... ) { ## check ggplot2 availability @@ -264,7 +284,7 @@ directional_movement_index.ggplot <- function( cols = rebuild_formula( names(constructed_series) ), - n = n, + timePeriod = timePeriod, na.bridge = TRUE ) @@ -287,7 +307,7 @@ directional_movement_index.ggplot <- function( layers <- list( list(y = "DX") ) - name <- sprintf("DX(%d)", n) + name <- sprintf("DX(%d)", timePeriod) ## splice:ggplot-assembly:end ggplot_object <- add_last_value_gg( diff --git a/R/ta_EMA.R b/R/ta_EMA.R index e85e4d49c..6ace188d0 100644 --- a/R/ta_EMA.R +++ b/R/ta_EMA.R @@ -1,11 +1,11 @@ #' @export -#' @family Overlap Study +#' @family Overlap Studies #' #' @title Exponential Moving Average #' @templateVar .title Exponential Moving Average #' @templateVar .author Serkan Korkmaz #' @templateVar .fun exponential_moving_average -#' @templateVar .family Overlap Study +#' @templateVar .family Overlap Studies #' @templateVar .formula ~close #' ## splice:documentation:start @@ -18,11 +18,12 @@ #' indicators that supports various Moving Average specifications. #' #' @template description +#' #' @template returns exponential_moving_average <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, ... ) { @@ -33,13 +34,19 @@ exponential_moving_average <- function( ## from call x <- structure( list( - n = if (missing(n)) 30L else as.integer(n), + timePeriod = if (missing(timePeriod)) { + 30L + } else { + as.integer(timePeriod) + }, maType = 1L - ) + ), + class = "maType" ) return(x) } + UseMethod("exponential_moving_average") } @@ -50,6 +57,13 @@ exponential_moving_average <- function( #' @aliases exponential_moving_average EMA <- exponential_moving_average +#' @export +#' @usage NULL +#' @rdname exponential_moving_average +#' +#' @aliases exponential_moving_average +exponentialMovingAverage <- exponential_moving_average + #' @usage NULL #' @aliases exponential_moving_average #' @@ -57,7 +71,7 @@ EMA <- exponential_moving_average exponential_moving_average.default <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, ... ) { @@ -84,8 +98,8 @@ exponential_moving_average.default <- function( ## return as data.frame x <- .Call( C_impl_ta_EMA, - as.double(constructed_series[[1]]), - as.integer(n), + constructed_series[[1]], + as.integer(timePeriod), as.logical(na.bridge) ) @@ -103,12 +117,18 @@ exponential_moving_average.default <- function( exponential_moving_average.data.frame <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, ... ) { map_dfr( - NextMethod() + exponential_moving_average.default( + x = x, + cols = cols, + timePeriod = timePeriod, + na.bridge = na.bridge, + ... + ) ) } @@ -119,17 +139,14 @@ exponential_moving_average.data.frame <- function( exponential_moving_average.matrix <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, ... ) { - ## pass directly to - ## exponential_moving_average.default to avoid - ## shenanigans with NextMethod() exponential_moving_average.default( x = x, cols = cols, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge, ... ) @@ -142,7 +159,7 @@ exponential_moving_average.matrix <- function( exponential_moving_average.numeric <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, ... ) { @@ -159,25 +176,32 @@ exponential_moving_average.numeric <- function( x <- .Call( C_impl_ta_EMA, as.double(x), - as.integer(n), + as.integer(timePeriod), 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 <- exponentialMovingAverage_lookback <- exponential_moving_average_lookback <- function( + x, + cols, + timePeriod = 30, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_EMA_lookback, + as.integer(timePeriod) + ) +} + + #' @usage NULL #' @aliases exponential_moving_average #' @@ -185,7 +209,7 @@ exponential_moving_average.numeric <- function( exponential_moving_average.plotly <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, ... ) { @@ -215,7 +239,8 @@ exponential_moving_average.plotly <- function( cols = rebuild_formula( names(constructed_series) ), - n = n + timePeriod = timePeriod, + na.bridge = TRUE ) ## add conditional idx @@ -238,15 +263,15 @@ exponential_moving_average.plotly <- function( ) ) ), - name = label("EMA", n), - decorators = list() + name = label("EMA", timePeriod), + decorators = list(), + data = constructed_indicator ) state[["main"]] <- plotly_object plotly_object } - #' @usage NULL #' @aliases exponential_moving_average #' @@ -254,7 +279,7 @@ exponential_moving_average.plotly <- function( exponential_moving_average.ggplot <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, ... ) { @@ -283,7 +308,8 @@ exponential_moving_average.ggplot <- function( cols = rebuild_formula( names(constructed_series) ), - n = n + timePeriod = timePeriod, + na.bridge = TRUE ) ## add conditional idx @@ -300,7 +326,7 @@ exponential_moving_average.ggplot <- function( y = "EMA" ) ), - name = label("EMA", n), + name = label("EMA", timePeriod), decorators = list(), data = constructed_indicator ) diff --git a/R/ta_HT_DCPERIOD.R b/R/ta_HT_DCPERIOD.R index e806d99c3..6d408ee10 100644 --- a/R/ta_HT_DCPERIOD.R +++ b/R/ta_HT_DCPERIOD.R @@ -1,17 +1,18 @@ #' @export -#' @family Cycle Indicator +#' @family Cycle Indicators #' #' @title Hilbert Transform - Dominant Cycle Period #' @templateVar .title Hilbert Transform - Dominant Cycle Period #' @templateVar .author Serkan Korkmaz #' @templateVar .fun dominant_cycle_period -#' @templateVar .family Cycle Indicator +#' @templateVar .family Cycle Indicators #' @templateVar .formula ~close #' ## splice:documentation:start ## splice:documentation:end #' #' @template description +#' #' @template returns dominant_cycle_period <- function( x, @@ -29,6 +30,13 @@ dominant_cycle_period <- function( #' @aliases dominant_cycle_period HT_DCPERIOD <- dominant_cycle_period +#' @export +#' @usage NULL +#' @rdname dominant_cycle_period +#' +#' @aliases dominant_cycle_period +dominantCyclePeriod <- dominant_cycle_period + #' @usage NULL #' @aliases dominant_cycle_period #' @@ -62,9 +70,7 @@ dominant_cycle_period.default <- function( ## return as data.frame x <- .Call( C_impl_ta_HT_DCPERIOD, - ## splice:call:start constructed_series[[1]], - ## splice:call:end as.logical(na.bridge) ) @@ -113,6 +119,17 @@ dominant_cycle_period.matrix <- function( ) } +#' @usage NULL +HT_DCPERIOD_lookback <- dominantCyclePeriod_lookback <- dominant_cycle_period_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_HT_DCPERIOD_lookback + ) +} #' @usage NULL #' @aliases dominant_cycle_period @@ -136,28 +153,17 @@ dominant_cycle_period.numeric <- function( ## to 'C' x <- .Call( C_impl_ta_HT_DCPERIOD, - ## splice:numeric:start as.double(x), - ## splice:numeric:end 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 #' @aliases dominant_cycle_period #' @@ -249,7 +255,8 @@ dominant_cycle_period.plotly <- function( } ), data = constructed_indicator[, values_to_extract, drop = FALSE], - values_to_extract = values_to_extract + values_to_extract = values_to_extract, + name = get0(x = "name", ifnotfound = NULL) ) state <- .chart_state() @@ -266,9 +273,9 @@ dominant_cycle_period.ggplot <- function( x, cols, na.bridge = FALSE, + title, ## splice:optional-ggplot:start ## splice:optional-ggplot:end - title, ... ) { ## check ggplot2 availability diff --git a/R/ta_HT_DCPHASE.R b/R/ta_HT_DCPHASE.R index 315e5007b..b4bb51e34 100644 --- a/R/ta_HT_DCPHASE.R +++ b/R/ta_HT_DCPHASE.R @@ -1,17 +1,18 @@ #' @export -#' @family Cycle Indicator +#' @family Cycle Indicators #' #' @title Hilbert Transform - Dominant Cycle Phase #' @templateVar .title Hilbert Transform - Dominant Cycle Phase #' @templateVar .author Serkan Korkmaz #' @templateVar .fun dominant_cycle_phase -#' @templateVar .family Cycle Indicator +#' @templateVar .family Cycle Indicators #' @templateVar .formula ~close #' ## splice:documentation:start ## splice:documentation:end #' #' @template description +#' #' @template returns dominant_cycle_phase <- function( x, @@ -29,6 +30,13 @@ dominant_cycle_phase <- function( #' @aliases dominant_cycle_phase HT_DCPHASE <- dominant_cycle_phase +#' @export +#' @usage NULL +#' @rdname dominant_cycle_phase +#' +#' @aliases dominant_cycle_phase +dominantCyclePhase <- dominant_cycle_phase + #' @usage NULL #' @aliases dominant_cycle_phase #' @@ -62,9 +70,7 @@ dominant_cycle_phase.default <- function( ## return as data.frame x <- .Call( C_impl_ta_HT_DCPHASE, - ## splice:call:start constructed_series[[1]], - ## splice:call:end as.logical(na.bridge) ) @@ -113,6 +119,17 @@ dominant_cycle_phase.matrix <- function( ) } +#' @usage NULL +HT_DCPHASE_lookback <- dominantCyclePhase_lookback <- dominant_cycle_phase_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_HT_DCPHASE_lookback + ) +} #' @usage NULL #' @aliases dominant_cycle_phase @@ -136,28 +153,17 @@ dominant_cycle_phase.numeric <- function( ## to 'C' x <- .Call( C_impl_ta_HT_DCPHASE, - ## splice:numeric:start as.double(x), - ## splice:numeric:end 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 #' @aliases dominant_cycle_phase #' @@ -213,7 +219,7 @@ dominant_cycle_phase.plotly <- function( ## construct {plotly}-object ## splice:plotly-assembly:start - name <- sprintf("DCPeriod") + name <- "DCPhase" decorators <- list() @@ -249,7 +255,8 @@ dominant_cycle_phase.plotly <- function( } ), data = constructed_indicator[, values_to_extract, drop = FALSE], - values_to_extract = values_to_extract + values_to_extract = values_to_extract, + name = get0(x = "name", ifnotfound = NULL) ) state <- .chart_state() @@ -266,9 +273,9 @@ dominant_cycle_phase.ggplot <- function( x, cols, na.bridge = FALSE, + title, ## splice:optional-ggplot:start ## splice:optional-ggplot:end - title, ... ) { ## check ggplot2 availability diff --git a/R/ta_HT_PHASOR.R b/R/ta_HT_PHASOR.R index 27f29560a..3351345ca 100644 --- a/R/ta_HT_PHASOR.R +++ b/R/ta_HT_PHASOR.R @@ -1,17 +1,18 @@ #' @export -#' @family Cycle Indicator +#' @family Cycle Indicators #' #' @title Hilbert Transform - Phasor Components #' @templateVar .title Hilbert Transform - Phasor Components #' @templateVar .author Serkan Korkmaz #' @templateVar .fun phasor_components -#' @templateVar .family Cycle Indicator +#' @templateVar .family Cycle Indicators #' @templateVar .formula ~close #' ## splice:documentation:start ## splice:documentation:end #' #' @template description +#' #' @template returns phasor_components <- function( x, @@ -29,6 +30,13 @@ phasor_components <- function( #' @aliases phasor_components HT_PHASOR <- phasor_components +#' @export +#' @usage NULL +#' @rdname phasor_components +#' +#' @aliases phasor_components +phasorComponents <- phasor_components + #' @usage NULL #' @aliases phasor_components #' @@ -62,9 +70,7 @@ phasor_components.default <- function( ## return as data.frame x <- .Call( C_impl_ta_HT_PHASOR, - ## splice:call:start constructed_series[[1]], - ## splice:call:end as.logical(na.bridge) ) @@ -113,6 +119,17 @@ phasor_components.matrix <- function( ) } +#' @usage NULL +HT_PHASOR_lookback <- phasorComponents_lookback <- phasor_components_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_HT_PHASOR_lookback + ) +} #' @usage NULL #' @aliases phasor_components @@ -136,28 +153,17 @@ phasor_components.numeric <- function( ## to 'C' x <- .Call( C_impl_ta_HT_PHASOR, - ## splice:numeric:start as.double(x), - ## splice:numeric:end 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 #' @aliases phasor_components #' @@ -257,7 +263,8 @@ phasor_components.plotly <- function( } ), data = constructed_indicator[, values_to_extract, drop = FALSE], - values_to_extract = values_to_extract + values_to_extract = values_to_extract, + name = get0(x = "name", ifnotfound = NULL) ) state <- .chart_state() @@ -274,9 +281,9 @@ phasor_components.ggplot <- function( x, cols, na.bridge = FALSE, + title, ## splice:optional-ggplot:start ## splice:optional-ggplot:end - title, ... ) { ## check ggplot2 availability diff --git a/R/ta_HT_SINE.R b/R/ta_HT_SINE.R index dad2622eb..75c12931a 100644 --- a/R/ta_HT_SINE.R +++ b/R/ta_HT_SINE.R @@ -1,17 +1,18 @@ #' @export -#' @family Cycle Indicator +#' @family Cycle Indicators #' #' @title Hilbert Transform - SineWave #' @templateVar .title Hilbert Transform - SineWave #' @templateVar .author Serkan Korkmaz #' @templateVar .fun sine_wave -#' @templateVar .family Cycle Indicator +#' @templateVar .family Cycle Indicators #' @templateVar .formula ~close #' ## splice:documentation:start ## splice:documentation:end #' #' @template description +#' #' @template returns sine_wave <- function( x, @@ -29,6 +30,13 @@ sine_wave <- function( #' @aliases sine_wave HT_SINE <- sine_wave +#' @export +#' @usage NULL +#' @rdname sine_wave +#' +#' @aliases sine_wave +sineWave <- sine_wave + #' @usage NULL #' @aliases sine_wave #' @@ -62,9 +70,7 @@ sine_wave.default <- function( ## return as data.frame x <- .Call( C_impl_ta_HT_SINE, - ## splice:call:start constructed_series[[1]], - ## splice:call:end as.logical(na.bridge) ) @@ -113,6 +119,17 @@ sine_wave.matrix <- function( ) } +#' @usage NULL +HT_SINE_lookback <- sineWave_lookback <- sine_wave_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_HT_SINE_lookback + ) +} #' @usage NULL #' @aliases sine_wave @@ -136,28 +153,17 @@ sine_wave.numeric <- function( ## to 'C' x <- .Call( C_impl_ta_HT_SINE, - ## splice:numeric:start as.double(x), - ## splice:numeric:end 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 #' @aliases sine_wave #' @@ -255,7 +261,8 @@ sine_wave.plotly <- function( } ), data = constructed_indicator[, values_to_extract, drop = FALSE], - values_to_extract = values_to_extract + values_to_extract = values_to_extract, + name = get0(x = "name", ifnotfound = NULL) ) state <- .chart_state() @@ -272,9 +279,9 @@ sine_wave.ggplot <- function( x, cols, na.bridge = FALSE, + title, ## splice:optional-ggplot:start ## splice:optional-ggplot:end - title, ... ) { ## check ggplot2 availability diff --git a/R/ta_HT_TRENDLINE.R b/R/ta_HT_TRENDLINE.R index f0051a5a9..4d3c6e1fa 100644 --- a/R/ta_HT_TRENDLINE.R +++ b/R/ta_HT_TRENDLINE.R @@ -1,17 +1,18 @@ #' @export -#' @family Overlap Study +#' @family Overlap Studies #' #' @title Hilbert Transform - Instantaneous Trendline #' @templateVar .title Hilbert Transform - Instantaneous Trendline #' @templateVar .author Serkan Korkmaz #' @templateVar .fun trendline -#' @templateVar .family Overlap Study +#' @templateVar .family Overlap Studies #' @templateVar .formula ~close #' ## splice:documentation:start ## splice:documentation:end #' #' @template description +#' #' @template returns trendline <- function( x, @@ -62,9 +63,7 @@ trendline.default <- function( ## return as data.frame x <- .Call( C_impl_ta_HT_TRENDLINE, - ## splice:call:start constructed_series[[1]], - ## splice:call:end as.logical(na.bridge) ) @@ -113,6 +112,17 @@ trendline.matrix <- function( ) } +#' @usage NULL +HT_TRENDLINE_lookback <- trendline_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_HT_TRENDLINE_lookback + ) +} #' @usage NULL #' @aliases trendline @@ -136,28 +146,17 @@ trendline.numeric <- function( ## to 'C' x <- .Call( C_impl_ta_HT_TRENDLINE, - ## splice:numeric:start as.double(x), - ## splice:numeric:end 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 #' @aliases trendline #' diff --git a/R/ta_HT_TRENDMODE.R b/R/ta_HT_TRENDMODE.R index dcbbacf1a..e9545a78c 100644 --- a/R/ta_HT_TRENDMODE.R +++ b/R/ta_HT_TRENDMODE.R @@ -1,17 +1,18 @@ #' @export -#' @family Cycle Indicator +#' @family Cycle Indicators #' #' @title Hilbert Transform - Trend vs Cycle Mode #' @templateVar .title Hilbert Transform - Trend vs Cycle Mode #' @templateVar .author Serkan Korkmaz #' @templateVar .fun trend_cycle_mode -#' @templateVar .family Cycle Indicator +#' @templateVar .family Cycle Indicators #' @templateVar .formula ~close #' ## splice:documentation:start ## splice:documentation:end #' #' @template description +#' #' @template returns trend_cycle_mode <- function( x, @@ -29,6 +30,13 @@ trend_cycle_mode <- function( #' @aliases trend_cycle_mode HT_TRENDMODE <- trend_cycle_mode +#' @export +#' @usage NULL +#' @rdname trend_cycle_mode +#' +#' @aliases trend_cycle_mode +trendCycleMode <- trend_cycle_mode + #' @usage NULL #' @aliases trend_cycle_mode #' @@ -62,9 +70,7 @@ trend_cycle_mode.default <- function( ## return as data.frame x <- .Call( C_impl_ta_HT_TRENDMODE, - ## splice:call:start constructed_series[[1]], - ## splice:call:end as.logical(na.bridge) ) @@ -113,6 +119,17 @@ trend_cycle_mode.matrix <- function( ) } +#' @usage NULL +HT_TRENDMODE_lookback <- trendCycleMode_lookback <- trend_cycle_mode_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_HT_TRENDMODE_lookback + ) +} #' @usage NULL #' @aliases trend_cycle_mode @@ -136,28 +153,17 @@ trend_cycle_mode.numeric <- function( ## to 'C' x <- .Call( C_impl_ta_HT_TRENDMODE, - ## splice:numeric:start as.double(x), - ## splice:numeric:end 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 #' @aliases trend_cycle_mode #' @@ -248,7 +254,8 @@ trend_cycle_mode.plotly <- function( } ), data = constructed_indicator[, values_to_extract, drop = FALSE], - values_to_extract = values_to_extract + values_to_extract = values_to_extract, + name = get0(x = "name", ifnotfound = NULL) ) state <- .chart_state() @@ -265,9 +272,9 @@ trend_cycle_mode.ggplot <- function( x, cols, na.bridge = FALSE, + title, ## splice:optional-ggplot:start ## splice:optional-ggplot:end - title, ... ) { ## check ggplot2 availability diff --git a/R/ta_IMI.R b/R/ta_IMI.R index 753987df7..255b3158a 100644 --- a/R/ta_IMI.R +++ b/R/ta_IMI.R @@ -1,22 +1,23 @@ #' @export -#' @family Momentum Indicator +#' @family Momentum Indicators #' -#' @title Intraday Movement Index -#' @templateVar .title Intraday Movement Index +#' @title Intraday Momentum Index +#' @templateVar .title Intraday Momentum Index #' @templateVar .author Serkan Korkmaz #' @templateVar .fun intraday_movement_index -#' @templateVar .family Momentum Indicator +#' @templateVar .family Momentum Indicators #' @templateVar .formula ~open + close #' ## splice:documentation:start ## splice:documentation:end #' #' @template description +#' #' @template returns intraday_movement_index <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -30,6 +31,13 @@ intraday_movement_index <- function( #' @aliases intraday_movement_index IMI <- intraday_movement_index +#' @export +#' @usage NULL +#' @rdname intraday_movement_index +#' +#' @aliases intraday_movement_index +intradayMovementIndex <- intraday_movement_index + #' @usage NULL #' @aliases intraday_movement_index #' @@ -37,7 +45,7 @@ IMI <- intraday_movement_index intraday_movement_index.default <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -64,11 +72,9 @@ intraday_movement_index.default <- function( ## return as data.frame x <- .Call( C_impl_ta_IMI, - ## splice:call:start constructed_series[[1]], constructed_series[[2]], - as.integer(n), - ## splice:call:end + as.integer(timePeriod), as.logical(na.bridge) ) @@ -86,7 +92,7 @@ intraday_movement_index.default <- function( intraday_movement_index.data.frame <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -94,7 +100,7 @@ intraday_movement_index.data.frame <- function( intraday_movement_index.default( x = x, cols = cols, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge, ... ) @@ -108,19 +114,32 @@ intraday_movement_index.data.frame <- function( intraday_movement_index.matrix <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { intraday_movement_index.default( x = x, cols = cols, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge, ... ) } +#' @usage NULL +IMI_lookback <- intradayMovementIndex_lookback <- intraday_movement_index_lookback <- function( + x, + cols, + timePeriod = 14, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_IMI_lookback, + as.integer(timePeriod) + ) +} #' @usage NULL #' @aliases intraday_movement_index @@ -129,7 +148,7 @@ intraday_movement_index.matrix <- function( intraday_movement_index.plotly <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ## splice:optional-plotly:start ## splice:optional-plotly:end @@ -162,7 +181,7 @@ intraday_movement_index.plotly <- function( cols = rebuild_formula( names(constructed_series) ), - n = n, + timePeriod = timePeriod, na.bridge = TRUE ) @@ -181,7 +200,7 @@ intraday_movement_index.plotly <- function( ## splice:plotly-assembly:start name <- sprintf( "IMI(%d)", - n + timePeriod ) decorators <- list() @@ -205,13 +224,14 @@ intraday_movement_index.plotly <- function( ), data = constructed_indicator, title = if (missing(title)) { - "Intraday Movement Index" + "Intraday Momentum Index" } else { title } ), data = constructed_indicator[, values_to_extract, drop = FALSE], - values_to_extract = values_to_extract + values_to_extract = values_to_extract, + name = get0(x = "name", ifnotfound = NULL) ) state <- .chart_state() @@ -227,11 +247,11 @@ intraday_movement_index.plotly <- function( intraday_movement_index.ggplot <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, + title, ## splice:optional-ggplot:start ## splice:optional-ggplot:end - title, ... ) { ## check ggplot2 availability @@ -259,7 +279,7 @@ intraday_movement_index.ggplot <- function( cols = rebuild_formula( names(constructed_series) ), - n = n, + timePeriod = timePeriod, na.bridge = TRUE ) @@ -282,7 +302,7 @@ intraday_movement_index.ggplot <- function( layers <- list( list(y = "IMI") ) - name <- sprintf("IMI(%d)", n) + name <- sprintf("IMI(%d)", timePeriod) ## splice:ggplot-assembly:end ggplot_object <- add_last_value_gg( @@ -299,7 +319,7 @@ intraday_movement_index.ggplot <- function( ), data = constructed_indicator, title = if (missing(title)) { - "Intraday Movement Index" + "Intraday Momentum Index" } else { title } diff --git a/R/ta_KAMA.R b/R/ta_KAMA.R index 5f0f0d315..8b11760b4 100644 --- a/R/ta_KAMA.R +++ b/R/ta_KAMA.R @@ -1,11 +1,11 @@ #' @export -#' @family Overlap Study +#' @family Overlap Studies #' #' @title Kaufman Adaptive Moving Average #' @templateVar .title Kaufman Adaptive Moving Average #' @templateVar .author Serkan Korkmaz #' @templateVar .fun kaufman_adaptive_moving_average -#' @templateVar .family Overlap Study +#' @templateVar .family Overlap Studies #' @templateVar .formula ~close #' ## splice:documentation:start @@ -18,11 +18,12 @@ #' indicators that supports various Moving Average specifications. #' #' @template description +#' #' @template returns kaufman_adaptive_moving_average <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, ... ) { @@ -33,13 +34,19 @@ kaufman_adaptive_moving_average <- function( ## from call x <- structure( list( - n = if (missing(n)) 30L else as.integer(n), + timePeriod = if (missing(timePeriod)) { + 30L + } else { + as.integer(timePeriod) + }, maType = 6L - ) + ), + class = "maType" ) return(x) } + UseMethod("kaufman_adaptive_moving_average") } @@ -50,6 +57,13 @@ kaufman_adaptive_moving_average <- function( #' @aliases kaufman_adaptive_moving_average KAMA <- kaufman_adaptive_moving_average +#' @export +#' @usage NULL +#' @rdname kaufman_adaptive_moving_average +#' +#' @aliases kaufman_adaptive_moving_average +kaufmanAdaptiveMovingAverage <- kaufman_adaptive_moving_average + #' @usage NULL #' @aliases kaufman_adaptive_moving_average #' @@ -57,7 +71,7 @@ KAMA <- kaufman_adaptive_moving_average kaufman_adaptive_moving_average.default <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, ... ) { @@ -84,8 +98,8 @@ kaufman_adaptive_moving_average.default <- function( ## return as data.frame x <- .Call( C_impl_ta_KAMA, - as.double(constructed_series[[1]]), - as.integer(n), + constructed_series[[1]], + as.integer(timePeriod), as.logical(na.bridge) ) @@ -103,12 +117,18 @@ kaufman_adaptive_moving_average.default <- function( kaufman_adaptive_moving_average.data.frame <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, ... ) { map_dfr( - NextMethod() + kaufman_adaptive_moving_average.default( + x = x, + cols = cols, + timePeriod = timePeriod, + na.bridge = na.bridge, + ... + ) ) } @@ -119,17 +139,14 @@ kaufman_adaptive_moving_average.data.frame <- function( kaufman_adaptive_moving_average.matrix <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, ... ) { - ## pass directly to - ## kaufman_adaptive_moving_average.default to avoid - ## shenanigans with NextMethod() kaufman_adaptive_moving_average.default( x = x, cols = cols, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge, ... ) @@ -142,7 +159,7 @@ kaufman_adaptive_moving_average.matrix <- function( kaufman_adaptive_moving_average.numeric <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, ... ) { @@ -159,25 +176,32 @@ kaufman_adaptive_moving_average.numeric <- function( x <- .Call( C_impl_ta_KAMA, as.double(x), - as.integer(n), + as.integer(timePeriod), 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 <- kaufmanAdaptiveMovingAverage_lookback <- kaufman_adaptive_moving_average_lookback <- function( + x, + cols, + timePeriod = 30, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_KAMA_lookback, + as.integer(timePeriod) + ) +} + + #' @usage NULL #' @aliases kaufman_adaptive_moving_average #' @@ -185,7 +209,7 @@ kaufman_adaptive_moving_average.numeric <- function( kaufman_adaptive_moving_average.plotly <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, ... ) { @@ -215,7 +239,8 @@ kaufman_adaptive_moving_average.plotly <- function( cols = rebuild_formula( names(constructed_series) ), - n = n + timePeriod = timePeriod, + na.bridge = TRUE ) ## add conditional idx @@ -238,15 +263,15 @@ kaufman_adaptive_moving_average.plotly <- function( ) ) ), - name = label("KAMA", n), - decorators = list() + name = label("KAMA", timePeriod), + decorators = list(), + data = constructed_indicator ) state[["main"]] <- plotly_object plotly_object } - #' @usage NULL #' @aliases kaufman_adaptive_moving_average #' @@ -254,7 +279,7 @@ kaufman_adaptive_moving_average.plotly <- function( kaufman_adaptive_moving_average.ggplot <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, ... ) { @@ -283,7 +308,8 @@ kaufman_adaptive_moving_average.ggplot <- function( cols = rebuild_formula( names(constructed_series) ), - n = n + timePeriod = timePeriod, + na.bridge = TRUE ) ## add conditional idx @@ -300,7 +326,7 @@ kaufman_adaptive_moving_average.ggplot <- function( y = "KAMA" ) ), - name = label("KAMA", n), + name = label("KAMA", timePeriod), decorators = list(), data = constructed_indicator ) diff --git a/R/ta_MACD.R b/R/ta_MACD.R index 364b16b81..7d1ea4273 100644 --- a/R/ta_MACD.R +++ b/R/ta_MACD.R @@ -1,27 +1,27 @@ #' @export -#' @family Momentum Indicator +#' @family Momentum Indicators #' -#' @title Moving Average Convergence Divergence -#' @templateVar .title Moving Average Convergence Divergence +#' @title Moving Average Convergence/Divergence +#' @templateVar .title Moving Average Convergence/Divergence #' @templateVar .author Serkan Korkmaz #' @templateVar .fun moving_average_convergence_divergence -#' @templateVar .family Momentum Indicator +#' @templateVar .family Momentum Indicators #' @templateVar .formula ~close #' ## splice:documentation:start -#' @param fast ([integer]). Period for the fast Moving Average (MA). -#' @param slow ([integer]). Period for the slow Moving Average (MA). -#' @param signal ([integer]). Period for the signal Moving Average (MA). ## splice:documentation:end #' #' @template description +#' @param fastPeriod ([integer]). Number of period for the fast MA. Defaults to `12`. +#' @param slowPeriod ([integer]). Number of period for the slow MA. Defaults to `26`. +#' @param signalPeriod ([integer]). Smoothing for the signal line (nb of period). Defaults to `9`. #' @template returns moving_average_convergence_divergence <- function( x, cols, - fast = 12, - slow = 26, - signal = 9, + fastPeriod = 12, + slowPeriod = 26, + signalPeriod = 9, na.bridge = FALSE, ... ) { @@ -35,6 +35,13 @@ moving_average_convergence_divergence <- function( #' @aliases moving_average_convergence_divergence MACD <- moving_average_convergence_divergence +#' @export +#' @usage NULL +#' @rdname moving_average_convergence_divergence +#' +#' @aliases moving_average_convergence_divergence +movingAverageConvergenceDivergence <- moving_average_convergence_divergence + #' @usage NULL #' @aliases moving_average_convergence_divergence #' @@ -42,9 +49,9 @@ MACD <- moving_average_convergence_divergence moving_average_convergence_divergence.default <- function( x, cols, - fast = 12, - slow = 26, - signal = 9, + fastPeriod = 12, + slowPeriod = 26, + signalPeriod = 9, na.bridge = FALSE, ... ) { @@ -71,12 +78,10 @@ moving_average_convergence_divergence.default <- function( ## return as data.frame x <- .Call( C_impl_ta_MACD, - ## splice:call:start constructed_series[[1]], - as.integer(fast), - as.integer(slow), - as.integer(signal), - ## splice:call:end + as.integer(fastPeriod), + as.integer(slowPeriod), + as.integer(signalPeriod), as.logical(na.bridge) ) @@ -94,9 +99,9 @@ moving_average_convergence_divergence.default <- function( moving_average_convergence_divergence.data.frame <- function( x, cols, - fast = 12, - slow = 26, - signal = 9, + fastPeriod = 12, + slowPeriod = 26, + signalPeriod = 9, na.bridge = FALSE, ... ) { @@ -104,9 +109,9 @@ moving_average_convergence_divergence.data.frame <- function( moving_average_convergence_divergence.default( x = x, cols = cols, - fast = fast, - slow = slow, - signal = signal, + fastPeriod = fastPeriod, + slowPeriod = slowPeriod, + signalPeriod = signalPeriod, na.bridge = na.bridge, ... ) @@ -120,23 +125,40 @@ moving_average_convergence_divergence.data.frame <- function( moving_average_convergence_divergence.matrix <- function( x, cols, - fast = 12, - slow = 26, - signal = 9, + fastPeriod = 12, + slowPeriod = 26, + signalPeriod = 9, na.bridge = FALSE, ... ) { moving_average_convergence_divergence.default( x = x, cols = cols, - fast = fast, - slow = slow, - signal = signal, + fastPeriod = fastPeriod, + slowPeriod = slowPeriod, + signalPeriod = signalPeriod, na.bridge = na.bridge, ... ) } +#' @usage NULL +MACD_lookback <- movingAverageConvergenceDivergence_lookback <- moving_average_convergence_divergence_lookback <- function( + x, + cols, + fastPeriod = 12, + slowPeriod = 26, + signalPeriod = 9, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_MACD_lookback, + as.integer(fastPeriod), + as.integer(slowPeriod), + as.integer(signalPeriod) + ) +} #' @usage NULL #' @aliases moving_average_convergence_divergence @@ -145,9 +167,9 @@ moving_average_convergence_divergence.matrix <- function( moving_average_convergence_divergence.numeric <- function( x, cols, - fast = 12, - slow = 26, - signal = 9, + fastPeriod = 12, + slowPeriod = 26, + signalPeriod = 9, na.bridge = FALSE, ... ) { @@ -163,31 +185,20 @@ moving_average_convergence_divergence.numeric <- function( ## to 'C' x <- .Call( C_impl_ta_MACD, - ## splice:numeric:start as.double(x), - as.integer(fast), - as.integer(slow), - as.integer(signal), - ## splice:numeric:end + as.integer(fastPeriod), + as.integer(slowPeriod), + as.integer(signalPeriod), 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 #' @aliases moving_average_convergence_divergence #' @@ -195,9 +206,9 @@ moving_average_convergence_divergence.numeric <- function( moving_average_convergence_divergence.plotly <- function( x, cols, - fast = 12, - slow = 26, - signal = 9, + fastPeriod = 12, + slowPeriod = 26, + signalPeriod = 9, na.bridge = FALSE, ## splice:optional-plotly:start ## splice:optional-plotly:end @@ -230,9 +241,9 @@ moving_average_convergence_divergence.plotly <- function( cols = rebuild_formula( names(constructed_series) ), - fast = fast, - slow = slow, - signal = signal, + fastPeriod = fastPeriod, + slowPeriod = slowPeriod, + signalPeriod = signalPeriod, na.bridge = TRUE ) @@ -257,9 +268,9 @@ moving_average_convergence_divergence.plotly <- function( ## construct plotly object name <- sprintf( "MACD(%d, %d, %d)", - fast, - slow, - signal + fastPeriod, + slowPeriod, + signalPeriod ) traces <- list( @@ -279,7 +290,7 @@ moving_average_convergence_divergence.plotly <- function( inherit = FALSE, name = sprintf( fmt = "Signal(%d)", - if (is.list(signal)) signal$n else signal + signalPeriod ) ), list( @@ -287,8 +298,8 @@ moving_average_convergence_divergence.plotly <- function( inherit = FALSE, name = sprintf( fmt = "MACD(%d, %d)", - if (is.list(fast)) fast$n else fast, - if (is.list(slow)) slow$n else slow + fastPeriod, + slowPeriod ) ) ) @@ -308,13 +319,14 @@ moving_average_convergence_divergence.plotly <- function( ), data = constructed_indicator, title = if (missing(title)) { - "Moving Average Convergence Divergence" + "Moving Average Convergence/Divergence" } else { title } ), data = constructed_indicator[, values_to_extract, drop = FALSE], - values_to_extract = values_to_extract + values_to_extract = values_to_extract, + name = get0(x = "name", ifnotfound = NULL) ) state <- .chart_state() @@ -330,13 +342,13 @@ moving_average_convergence_divergence.plotly <- function( moving_average_convergence_divergence.ggplot <- function( x, cols, - fast = 12, - slow = 26, - signal = 9, + fastPeriod = 12, + slowPeriod = 26, + signalPeriod = 9, na.bridge = FALSE, + title, ## splice:optional-ggplot:start ## splice:optional-ggplot:end - title, ... ) { ## check ggplot2 availability @@ -364,9 +376,9 @@ moving_average_convergence_divergence.ggplot <- function( cols = rebuild_formula( names(constructed_series) ), - fast = fast, - slow = slow, - signal = signal, + fastPeriod = fastPeriod, + slowPeriod = slowPeriod, + signalPeriod = signalPeriod, na.bridge = TRUE ) @@ -383,6 +395,8 @@ moving_average_convergence_divergence.ggplot <- function( ## construct {ggplot2}-object ## splice:ggplot-assembly:start + ## calculate directions for bull + ## and bear candles constructed_indicator$direction <- constructed_indicator$MACDSignal >= constructed_indicator$MACD layers <- list( @@ -395,10 +409,10 @@ moving_average_convergence_divergence.ggplot <- function( .chart_variables$bearish_body ) ), - list(y = "MACDSignal", name = sprintf("Signal(%d)", signal)), - list(y = "MACD", name = sprintf("MACD(%d, %d)", fast, slow)) + list(y = "MACDSignal", name = sprintf("Signal(%d)", signalPeriod)), + list(y = "MACD", name = sprintf("MACD(%d, %d)", fastPeriod, slowPeriod)) ) - name <- sprintf("MACD(%d, %d, %d)", fast, slow, signal) + name <- sprintf("MACD(%d, %d, %d)", fastPeriod, slowPeriod, signalPeriod) ## splice:ggplot-assembly:end ggplot_object <- add_last_value_gg( @@ -415,7 +429,7 @@ moving_average_convergence_divergence.ggplot <- function( ), data = constructed_indicator, title = if (missing(title)) { - "Moving Average Convergence Divergence" + "Moving Average Convergence/Divergence" } else { title } diff --git a/R/ta_MACDEXT.R b/R/ta_MACDEXT.R index 23d99dd0e..12e36144b 100644 --- a/R/ta_MACDEXT.R +++ b/R/ta_MACDEXT.R @@ -1,27 +1,33 @@ #' @export -#' @family Momentum Indicator +#' @family Momentum Indicators #' -#' @title Moving Average Convergence Divergence (Extended) -#' @templateVar .title Moving Average Convergence Divergence (Extended) +#' @title MACD with controllable MA type +#' @templateVar .title MACD with controllable MA type #' @templateVar .author Serkan Korkmaz #' @templateVar .fun extended_moving_average_convergence_divergence -#' @templateVar .family Momentum Indicator +#' @templateVar .family Momentum Indicators #' @templateVar .formula ~close #' ## splice:documentation:start -#' @param fast ([list]). Period and Moving Average (MA) type for the fast MA. [EMA] by default. -#' @param slow ([list]). Period and Moving Average (MA) type for the slow MA. [EMA] by default. -#' @param signal ([list]). Period and Moving Average (MA) type for the signal MA. [EMA] by default. ## splice:documentation:end #' #' @template description +#' @param fastPeriod ([integer]). Number of period for the fast MA. Defaults to `12`. +#' @param fastMa ([integer]). Type of Moving Average for fast MA. Defaults to `0` ([SMA]). Can also be passed as talib::SMA. +#' @param slowPeriod ([integer]). Number of period for the slow MA. Defaults to `26`. +#' @param slowMa ([integer]). Type of Moving Average for slow MA. Defaults to `0` ([SMA]). Can also be passed as talib::SMA. +#' @param signalPeriod ([integer]). Smoothing for the signal line (nb of period). Defaults to `9`. +#' @param signalMa ([integer]). Type of Moving Average for signal line. Defaults to `0` ([SMA]). Can also be passed as talib::SMA. #' @template returns extended_moving_average_convergence_divergence <- function( x, cols, - fast = SMA(n = 12), - slow = SMA(n = 26), - signal = SMA(n = 9), + fastPeriod = 12, + fastMa = 0, + slowPeriod = 26, + slowMa = 0, + signalPeriod = 9, + signalMa = 0, na.bridge = FALSE, ... ) { @@ -35,6 +41,13 @@ extended_moving_average_convergence_divergence <- function( #' @aliases extended_moving_average_convergence_divergence MACDEXT <- extended_moving_average_convergence_divergence +#' @export +#' @usage NULL +#' @rdname extended_moving_average_convergence_divergence +#' +#' @aliases extended_moving_average_convergence_divergence +extendedMovingAverageConvergenceDivergence <- extended_moving_average_convergence_divergence + #' @usage NULL #' @aliases extended_moving_average_convergence_divergence #' @@ -42,9 +55,12 @@ MACDEXT <- extended_moving_average_convergence_divergence extended_moving_average_convergence_divergence.default <- function( x, cols, - fast = SMA(n = 12), - slow = SMA(n = 26), - signal = SMA(n = 9), + fastPeriod = 12, + fastMa = 0, + slowPeriod = 26, + slowMa = 0, + signalPeriod = 9, + signalMa = 0, na.bridge = FALSE, ... ) { @@ -71,15 +87,13 @@ extended_moving_average_convergence_divergence.default <- function( ## return as data.frame x <- .Call( C_impl_ta_MACDEXT, - ## splice:call:start constructed_series[[1]], - fast$n, - fast$maType, - slow$n, - slow$maType, - signal$n, - signal$maType, - ## splice:call:end + as.integer(fastPeriod), + as.maType(fastMa), + as.integer(slowPeriod), + as.maType(slowMa), + as.integer(signalPeriod), + as.maType(signalMa), as.logical(na.bridge) ) @@ -97,9 +111,12 @@ extended_moving_average_convergence_divergence.default <- function( extended_moving_average_convergence_divergence.data.frame <- function( x, cols, - fast = SMA(n = 12), - slow = SMA(n = 26), - signal = SMA(n = 9), + fastPeriod = 12, + fastMa = 0, + slowPeriod = 26, + slowMa = 0, + signalPeriod = 9, + signalMa = 0, na.bridge = FALSE, ... ) { @@ -107,9 +124,12 @@ extended_moving_average_convergence_divergence.data.frame <- function( extended_moving_average_convergence_divergence.default( x = x, cols = cols, - fast = fast, - slow = slow, - signal = signal, + fastPeriod = fastPeriod, + fastMa = fastMa, + slowPeriod = slowPeriod, + slowMa = slowMa, + signalPeriod = signalPeriod, + signalMa = signalMa, na.bridge = na.bridge, ... ) @@ -123,23 +143,52 @@ extended_moving_average_convergence_divergence.data.frame <- function( extended_moving_average_convergence_divergence.matrix <- function( x, cols, - fast = SMA(n = 12), - slow = SMA(n = 26), - signal = SMA(n = 9), + fastPeriod = 12, + fastMa = 0, + slowPeriod = 26, + slowMa = 0, + signalPeriod = 9, + signalMa = 0, na.bridge = FALSE, ... ) { extended_moving_average_convergence_divergence.default( x = x, cols = cols, - fast = fast, - slow = slow, - signal = signal, + fastPeriod = fastPeriod, + fastMa = fastMa, + slowPeriod = slowPeriod, + slowMa = slowMa, + signalPeriod = signalPeriod, + signalMa = signalMa, na.bridge = na.bridge, ... ) } +#' @usage NULL +MACDEXT_lookback <- extendedMovingAverageConvergenceDivergence_lookback <- extended_moving_average_convergence_divergence_lookback <- function( + x, + cols, + fastPeriod = 12, + fastMa = 0, + slowPeriod = 26, + slowMa = 0, + signalPeriod = 9, + signalMa = 0, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_MACDEXT_lookback, + as.integer(fastPeriod), + as.maType(fastMa), + as.integer(slowPeriod), + as.maType(slowMa), + as.integer(signalPeriod), + as.maType(signalMa) + ) +} #' @usage NULL #' @aliases extended_moving_average_convergence_divergence @@ -148,9 +197,12 @@ extended_moving_average_convergence_divergence.matrix <- function( extended_moving_average_convergence_divergence.numeric <- function( x, cols, - fast = SMA(n = 12), - slow = SMA(n = 26), - signal = SMA(n = 9), + fastPeriod = 12, + fastMa = 0, + slowPeriod = 26, + slowMa = 0, + signalPeriod = 9, + signalMa = 0, na.bridge = FALSE, ... ) { @@ -166,34 +218,23 @@ extended_moving_average_convergence_divergence.numeric <- function( ## to 'C' x <- .Call( C_impl_ta_MACDEXT, - ## splice:numeric:start as.double(x), - fast$n, - fast$maType, - slow$n, - slow$maType, - signal$n, - signal$maType, - ## splice:numeric:end + as.integer(fastPeriod), + as.maType(fastMa), + as.integer(slowPeriod), + as.maType(slowMa), + as.integer(signalPeriod), + as.maType(signalMa), 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 #' @aliases extended_moving_average_convergence_divergence #' @@ -201,9 +242,12 @@ extended_moving_average_convergence_divergence.numeric <- function( extended_moving_average_convergence_divergence.plotly <- function( x, cols, - fast = SMA(n = 12), - slow = SMA(n = 26), - signal = SMA(n = 9), + fastPeriod = 12, + fastMa = 0, + slowPeriod = 26, + slowMa = 0, + signalPeriod = 9, + signalMa = 0, na.bridge = FALSE, ## splice:optional-plotly:start ## splice:optional-plotly:end @@ -236,9 +280,12 @@ extended_moving_average_convergence_divergence.plotly <- function( cols = rebuild_formula( names(constructed_series) ), - fast = fast, - slow = slow, - signal = signal, + fastPeriod = fastPeriod, + fastMa = fastMa, + slowPeriod = slowPeriod, + slowMa = slowMa, + signalPeriod = signalPeriod, + signalMa = signalMa, na.bridge = TRUE ) @@ -263,9 +310,9 @@ extended_moving_average_convergence_divergence.plotly <- function( ## construct plotly object name <- sprintf( "MACD(%d, %d, %d)", - if (is.list(fast)) fast$n else fast, - if (is.list(slow)) slow$n else slow, - if (is.list(signal)) signal$n else signal + fastPeriod, + slowPeriod, + signalPeriod ) traces <- list( @@ -285,7 +332,7 @@ extended_moving_average_convergence_divergence.plotly <- function( inherit = FALSE, name = sprintf( fmt = "Signal(%d)", - if (is.list(signal)) signal$n else signal + signalPeriod ) ), list( @@ -293,8 +340,8 @@ extended_moving_average_convergence_divergence.plotly <- function( inherit = FALSE, name = sprintf( fmt = "MACD(%d, %d)", - if (is.list(fast)) fast$n else fast, - if (is.list(slow)) slow$n else slow + fastPeriod, + slowPeriod ) ) ) @@ -314,13 +361,14 @@ extended_moving_average_convergence_divergence.plotly <- function( ), data = constructed_indicator, title = if (missing(title)) { - "Moving Average Convergence Divergence (Extended)" + "MACD with controllable MA type" } else { title } ), data = constructed_indicator[, values_to_extract, drop = FALSE], - values_to_extract = values_to_extract + values_to_extract = values_to_extract, + name = get0(x = "name", ifnotfound = NULL) ) state <- .chart_state() @@ -336,13 +384,16 @@ extended_moving_average_convergence_divergence.plotly <- function( extended_moving_average_convergence_divergence.ggplot <- function( x, cols, - fast = SMA(n = 12), - slow = SMA(n = 26), - signal = SMA(n = 9), + fastPeriod = 12, + fastMa = 0, + slowPeriod = 26, + slowMa = 0, + signalPeriod = 9, + signalMa = 0, na.bridge = FALSE, + title, ## splice:optional-ggplot:start ## splice:optional-ggplot:end - title, ... ) { ## check ggplot2 availability @@ -370,9 +421,12 @@ extended_moving_average_convergence_divergence.ggplot <- function( cols = rebuild_formula( names(constructed_series) ), - fast = fast, - slow = slow, - signal = signal, + fastPeriod = fastPeriod, + fastMa = fastMa, + slowPeriod = slowPeriod, + slowMa = slowMa, + signalPeriod = signalPeriod, + signalMa = signalMa, na.bridge = TRUE ) @@ -389,6 +443,8 @@ extended_moving_average_convergence_divergence.ggplot <- function( ## construct {ggplot2}-object ## splice:ggplot-assembly:start + ## calculate directions for bull + ## and bear candles constructed_indicator$direction <- constructed_indicator$MACDSignal >= constructed_indicator$MACD layers <- list( @@ -401,28 +457,10 @@ extended_moving_average_convergence_divergence.ggplot <- function( .chart_variables$bearish_body ) ), - list( - y = "MACDSignal", - name = sprintf( - "Signal(%d)", - if (is.list(signal)) signal$n else signal - ) - ), - list( - y = "MACD", - name = sprintf( - "MACD(%d, %d)", - if (is.list(fast)) fast$n else fast, - if (is.list(slow)) slow$n else slow - ) - ) - ) - name <- sprintf( - "MACD(%d, %d, %d)", - if (is.list(fast)) fast$n else fast, - if (is.list(slow)) slow$n else slow, - if (is.list(signal)) signal$n else signal + list(y = "MACDSignal", name = sprintf("Signal(%d)", signalPeriod)), + list(y = "MACD", name = sprintf("MACD(%d, %d)", fastPeriod, slowPeriod)) ) + name <- sprintf("MACD(%d, %d, %d)", fastPeriod, slowPeriod, signalPeriod) ## splice:ggplot-assembly:end ggplot_object <- add_last_value_gg( @@ -439,7 +477,7 @@ extended_moving_average_convergence_divergence.ggplot <- function( ), data = constructed_indicator, title = if (missing(title)) { - "Moving Average Convergence Divergence (Extended)" + "MACD with controllable MA type" } else { title } diff --git a/R/ta_MACDFIX.R b/R/ta_MACDFIX.R index 636895fc3..1d0b23913 100644 --- a/R/ta_MACDFIX.R +++ b/R/ta_MACDFIX.R @@ -1,23 +1,23 @@ #' @export -#' @family Momentum Indicator +#' @family Momentum Indicators #' -#' @title Moving Average Convergence Divergence (Fixed) -#' @templateVar .title Moving Average Convergence Divergence (Fixed) +#' @title Moving Average Convergence/Divergence Fix 12/26 +#' @templateVar .title Moving Average Convergence/Divergence Fix 12/26 #' @templateVar .author Serkan Korkmaz #' @templateVar .fun fixed_moving_average_convergence_divergence -#' @templateVar .family Momentum Indicator +#' @templateVar .family Momentum Indicators #' @templateVar .formula ~close #' ## splice:documentation:start -#' @param signal ([integer]). Period for the signal Moving Average (MA). ## splice:documentation:end #' #' @template description +#' @param signalPeriod ([integer]). Smoothing for the signal line (nb of period). Defaults to `9`. #' @template returns fixed_moving_average_convergence_divergence <- function( x, cols, - signal = 9, + signalPeriod = 9, na.bridge = FALSE, ... ) { @@ -31,6 +31,13 @@ fixed_moving_average_convergence_divergence <- function( #' @aliases fixed_moving_average_convergence_divergence MACDFIX <- fixed_moving_average_convergence_divergence +#' @export +#' @usage NULL +#' @rdname fixed_moving_average_convergence_divergence +#' +#' @aliases fixed_moving_average_convergence_divergence +fixedMovingAverageConvergenceDivergence <- fixed_moving_average_convergence_divergence + #' @usage NULL #' @aliases fixed_moving_average_convergence_divergence #' @@ -38,7 +45,7 @@ MACDFIX <- fixed_moving_average_convergence_divergence fixed_moving_average_convergence_divergence.default <- function( x, cols, - signal = 9, + signalPeriod = 9, na.bridge = FALSE, ... ) { @@ -65,10 +72,8 @@ fixed_moving_average_convergence_divergence.default <- function( ## return as data.frame x <- .Call( C_impl_ta_MACDFIX, - ## splice:call:start constructed_series[[1]], - as.integer(signal), - ## splice:call:end + as.integer(signalPeriod), as.logical(na.bridge) ) @@ -86,7 +91,7 @@ fixed_moving_average_convergence_divergence.default <- function( fixed_moving_average_convergence_divergence.data.frame <- function( x, cols, - signal = 9, + signalPeriod = 9, na.bridge = FALSE, ... ) { @@ -94,7 +99,7 @@ fixed_moving_average_convergence_divergence.data.frame <- function( fixed_moving_average_convergence_divergence.default( x = x, cols = cols, - signal = signal, + signalPeriod = signalPeriod, na.bridge = na.bridge, ... ) @@ -108,19 +113,32 @@ fixed_moving_average_convergence_divergence.data.frame <- function( fixed_moving_average_convergence_divergence.matrix <- function( x, cols, - signal = 9, + signalPeriod = 9, na.bridge = FALSE, ... ) { fixed_moving_average_convergence_divergence.default( x = x, cols = cols, - signal = signal, + signalPeriod = signalPeriod, na.bridge = na.bridge, ... ) } +#' @usage NULL +MACDFIX_lookback <- fixedMovingAverageConvergenceDivergence_lookback <- fixed_moving_average_convergence_divergence_lookback <- function( + x, + cols, + signalPeriod = 9, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_MACDFIX_lookback, + as.integer(signalPeriod) + ) +} #' @usage NULL #' @aliases fixed_moving_average_convergence_divergence @@ -129,7 +147,7 @@ fixed_moving_average_convergence_divergence.matrix <- function( fixed_moving_average_convergence_divergence.numeric <- function( x, cols, - signal = 9, + signalPeriod = 9, na.bridge = FALSE, ... ) { @@ -145,29 +163,18 @@ fixed_moving_average_convergence_divergence.numeric <- function( ## to 'C' x <- .Call( C_impl_ta_MACDFIX, - ## splice:numeric:start as.double(x), - as.integer(signal), - ## splice:numeric:end + as.integer(signalPeriod), 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 #' @aliases fixed_moving_average_convergence_divergence #' @@ -175,7 +182,7 @@ fixed_moving_average_convergence_divergence.numeric <- function( fixed_moving_average_convergence_divergence.plotly <- function( x, cols, - signal = 9, + signalPeriod = 9, na.bridge = FALSE, ## splice:optional-plotly:start ## splice:optional-plotly:end @@ -208,7 +215,7 @@ fixed_moving_average_convergence_divergence.plotly <- function( cols = rebuild_formula( names(constructed_series) ), - signal = signal, + signalPeriod = signalPeriod, na.bridge = TRUE ) @@ -233,7 +240,7 @@ fixed_moving_average_convergence_divergence.plotly <- function( ## construct plotly object name <- sprintf( "MACD(%d)", - if (is.list(signal)) signal$n else signal + signalPeriod ) traces <- list( @@ -253,7 +260,7 @@ fixed_moving_average_convergence_divergence.plotly <- function( inherit = FALSE, name = sprintf( fmt = "Signal(%d)", - if (is.list(signal)) signal$n else signal + signalPeriod ) ), list( @@ -282,13 +289,14 @@ fixed_moving_average_convergence_divergence.plotly <- function( ), data = constructed_indicator, title = if (missing(title)) { - "Moving Average Convergence Divergence (Fixed)" + "Moving Average Convergence/Divergence Fix 12/26" } else { title } ), data = constructed_indicator[, values_to_extract, drop = FALSE], - values_to_extract = values_to_extract + values_to_extract = values_to_extract, + name = get0(x = "name", ifnotfound = NULL) ) state <- .chart_state() @@ -304,11 +312,11 @@ fixed_moving_average_convergence_divergence.plotly <- function( fixed_moving_average_convergence_divergence.ggplot <- function( x, cols, - signal = 9, + signalPeriod = 9, na.bridge = FALSE, + title, ## splice:optional-ggplot:start ## splice:optional-ggplot:end - title, ... ) { ## check ggplot2 availability @@ -336,7 +344,7 @@ fixed_moving_average_convergence_divergence.ggplot <- function( cols = rebuild_formula( names(constructed_series) ), - signal = signal, + signalPeriod = signalPeriod, na.bridge = TRUE ) @@ -353,6 +361,8 @@ fixed_moving_average_convergence_divergence.ggplot <- function( ## construct {ggplot2}-object ## splice:ggplot-assembly:start + ## calculate directions for bull + ## and bear candles constructed_indicator$direction <- constructed_indicator$MACDSignal >= constructed_indicator$MACD layers <- list( @@ -365,19 +375,10 @@ fixed_moving_average_convergence_divergence.ggplot <- function( .chart_variables$bearish_body ) ), - list( - y = "MACDSignal", - name = sprintf( - "Signal(%d)", - if (is.list(signal)) signal$n else signal - ) - ), - list( - y = "MACD", - name = sprintf("MACD(%d, %d)", 12, 26) - ) + list(y = "MACDSignal", name = sprintf("Signal(%d)", signalPeriod)), + list(y = "MACD", name = sprintf("MACD(%d, %d)", 12, 26)) ) - name <- sprintf("MACD(%d)", if (is.list(signal)) signal$n else signal) + name <- sprintf("MACD(%d)", signalPeriod) ## splice:ggplot-assembly:end ggplot_object <- add_last_value_gg( @@ -394,7 +395,7 @@ fixed_moving_average_convergence_divergence.ggplot <- function( ), data = constructed_indicator, title = if (missing(title)) { - "Moving Average Convergence Divergence (Fixed)" + "Moving Average Convergence/Divergence Fix 12/26" } else { title } diff --git a/R/ta_MAMA.R b/R/ta_MAMA.R index 7918e21e9..a7105b918 100644 --- a/R/ta_MAMA.R +++ b/R/ta_MAMA.R @@ -1,17 +1,14 @@ #' @export -#' @family Overlap Study +#' @family Overlap Studies #' #' @title MESA Adaptive Moving Average #' @templateVar .title MESA Adaptive Moving Average #' @templateVar .author Serkan Korkmaz #' @templateVar .fun mesa_adaptive_moving_average -#' @templateVar .family Overlap Study +#' @templateVar .family Overlap Studies #' @templateVar .formula ~close #' ## splice:documentation:start -#' @param n ([integer]). Present only for interface uniformity with the other Moving Average specifications (see e.g. [simple_moving_average]) so that every MA spec exposes a uniform `n` field to downstream consumers (e.g. [bollinger_bands], [stochastic], [extended_moving_average_convergence_divergence]). **`n` has no effect on the standalone calculation of [mesa_adaptive_moving_average]** - the actual smoothing is controlled entirely by `fast` and `slow`. -#' @param fast ([double]). Upper limit of the adaptive smoothing factor (alpha) used in the MESA algorithm. A [double] in `[0.01, 0.99]`. `0.5` by default. -#' @param slow ([double]). Lower limit of the adaptive smoothing factor (alpha) used in the MESA algorithm. A [double] in `[0.01, 0.99]`. `0.05` by default. ## splice:documentation:end #' #' @details @@ -21,13 +18,15 @@ #' indicators that supports various Moving Average specifications. #' #' @template description +#' @param fastLimit ([double]). Upper limit use in the adaptive algorithm. Defaults to `0.5`. +#' @param slowLimit ([double]). Lower limit use in the adaptive algorithm. Defaults to `0.05`. #' @template returns mesa_adaptive_moving_average <- function( x, cols, - n = 30, - fast = 0.5, - slow = 0.05, + timePeriod = 30, + fastLimit = 0.5, + slowLimit = 0.05, na.bridge = FALSE, ... ) { @@ -38,15 +37,29 @@ mesa_adaptive_moving_average <- function( ## from call x <- structure( list( - n = if (missing(n)) 30L else as.integer(n), - fast = if (missing(fast)) 0.5 else as.double(fast), - slow = if (missing(slow)) 0.05 else as.double(slow), + timePeriod = if (missing(timePeriod)) { + 30L + } else { + as.integer(timePeriod) + }, + fastLimit = if (missing(fastLimit)) { + 0.5 + } else { + as.double(fastLimit) + }, + slowLimit = if (missing(slowLimit)) { + 0.05 + } else { + as.double(slowLimit) + }, maType = 7L - ) + ), + class = "maType" ) return(x) } + UseMethod("mesa_adaptive_moving_average") } @@ -57,6 +70,13 @@ mesa_adaptive_moving_average <- function( #' @aliases mesa_adaptive_moving_average MAMA <- mesa_adaptive_moving_average +#' @export +#' @usage NULL +#' @rdname mesa_adaptive_moving_average +#' +#' @aliases mesa_adaptive_moving_average +mesaAdaptiveMovingAverage <- mesa_adaptive_moving_average + #' @usage NULL #' @aliases mesa_adaptive_moving_average #' @@ -64,9 +84,9 @@ MAMA <- mesa_adaptive_moving_average mesa_adaptive_moving_average.default <- function( x, cols, - n = 30, - fast = 0.5, - slow = 0.05, + timePeriod = 30, + fastLimit = 0.5, + slowLimit = 0.05, na.bridge = FALSE, ... ) { @@ -93,9 +113,9 @@ mesa_adaptive_moving_average.default <- function( ## return as data.frame x <- .Call( C_impl_ta_MAMA, - as.double(constructed_series[[1]]), - as.double(fast), - as.double(slow), + constructed_series[[1]], + as.double(fastLimit), + as.double(slowLimit), as.logical(na.bridge) ) @@ -113,14 +133,22 @@ mesa_adaptive_moving_average.default <- function( mesa_adaptive_moving_average.data.frame <- function( x, cols, - n = 30, - fast = 0.5, - slow = 0.05, + timePeriod = 30, + fastLimit = 0.5, + slowLimit = 0.05, na.bridge = FALSE, ... ) { map_dfr( - NextMethod() + mesa_adaptive_moving_average.default( + x = x, + cols = cols, + timePeriod = timePeriod, + fastLimit = fastLimit, + slowLimit = slowLimit, + na.bridge = na.bridge, + ... + ) ) } @@ -131,21 +159,18 @@ mesa_adaptive_moving_average.data.frame <- function( mesa_adaptive_moving_average.matrix <- function( x, cols, - n = 30, - fast = 0.5, - slow = 0.05, + timePeriod = 30, + fastLimit = 0.5, + slowLimit = 0.05, na.bridge = FALSE, ... ) { - ## pass directly to - ## mesa_adaptive_moving_average.default to avoid - ## shenanigans with NextMethod() mesa_adaptive_moving_average.default( x = x, cols = cols, - n = n, - fast = fast, - slow = slow, + timePeriod = timePeriod, + fastLimit = fastLimit, + slowLimit = slowLimit, na.bridge = na.bridge, ... ) @@ -158,9 +183,9 @@ mesa_adaptive_moving_average.matrix <- function( mesa_adaptive_moving_average.numeric <- function( x, cols, - n = 30, - fast = 0.5, - slow = 0.05, + timePeriod = 30, + fastLimit = 0.5, + slowLimit = 0.05, na.bridge = FALSE, ... ) { @@ -177,26 +202,36 @@ mesa_adaptive_moving_average.numeric <- function( x <- .Call( C_impl_ta_MAMA, as.double(x), - as.double(fast), - as.double(slow), + as.double(fastLimit), + as.double(slowLimit), 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 <- mesaAdaptiveMovingAverage_lookback <- mesa_adaptive_moving_average_lookback <- function( + x, + cols, + timePeriod = 30, + fastLimit = 0.5, + slowLimit = 0.05, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_MAMA_lookback, + as.double(fastLimit), + as.double(slowLimit) + ) +} + + #' @usage NULL #' @aliases mesa_adaptive_moving_average #' @@ -204,9 +239,9 @@ mesa_adaptive_moving_average.numeric <- function( mesa_adaptive_moving_average.plotly <- function( x, cols, - n = 30, - fast = 0.5, - slow = 0.05, + timePeriod = 30, + fastLimit = 0.5, + slowLimit = 0.05, na.bridge = FALSE, ... ) { @@ -236,9 +271,10 @@ mesa_adaptive_moving_average.plotly <- function( cols = rebuild_formula( names(constructed_series) ), - n = n, - fast = fast, - slow = slow + timePeriod = timePeriod, + fastLimit = fastLimit, + slowLimit = slowLimit, + na.bridge = TRUE ) ## add conditional idx @@ -261,15 +297,15 @@ mesa_adaptive_moving_average.plotly <- function( ) ) ), - name = label("MAMA", fast, slow), - decorators = list() + name = label("MAMA", fastLimit, slowLimit), + decorators = list(), + data = constructed_indicator ) state[["main"]] <- plotly_object plotly_object } - #' @usage NULL #' @aliases mesa_adaptive_moving_average #' @@ -277,9 +313,9 @@ mesa_adaptive_moving_average.plotly <- function( mesa_adaptive_moving_average.ggplot <- function( x, cols, - n = 30, - fast = 0.5, - slow = 0.05, + timePeriod = 30, + fastLimit = 0.5, + slowLimit = 0.05, na.bridge = FALSE, ... ) { @@ -308,9 +344,10 @@ mesa_adaptive_moving_average.ggplot <- function( cols = rebuild_formula( names(constructed_series) ), - n = n, - fast = fast, - slow = slow + timePeriod = timePeriod, + fastLimit = fastLimit, + slowLimit = slowLimit, + na.bridge = TRUE ) ## add conditional idx @@ -327,7 +364,7 @@ mesa_adaptive_moving_average.ggplot <- function( y = "MAMA" ) ), - name = label("MAMA", fast, slow), + name = label("MAMA", fastLimit, slowLimit), decorators = list(), data = constructed_indicator ) diff --git a/R/ta_MAVP.R b/R/ta_MAVP.R new file mode 100644 index 000000000..cc6135e12 --- /dev/null +++ b/R/ta_MAVP.R @@ -0,0 +1,382 @@ +#' @export +#' @family Overlap Studies +#' +#' @title Moving average with variable period +#' @templateVar .title Moving average with variable period +#' @templateVar .author Serkan Korkmaz +#' @templateVar .fun variable_moving_average_period +#' @templateVar .family Overlap Studies +#' @templateVar .formula ~close +#' +## splice:documentation:start +#' @templateVar .custom_example TRUE +#' @example man/examples/MAVP-example.R +## splice:documentation:end +#' +#' @template description +#' @param periods ([numeric]). Vector of periods, one per observation of the input series. +#' @param minimumPeriod ([integer]). Value less than minimum will be changed to Minimum period. Defaults to `2`. +#' @param maximumPeriod ([integer]). Value higher than maximum will be changed to Maximum period. Defaults to `30`. +#' @param maType ([integer]). Type of Moving Average. Defaults to `0` ([SMA]). Can also be passed as talib::SMA. +#' @template returns +variable_moving_average_period <- function( + x, + cols, + periods, + minimumPeriod = 2, + maximumPeriod = 30, + maType = 0, + na.bridge = FALSE, + ... +) { + UseMethod("variable_moving_average_period") +} + +#' @export +#' @usage NULL +#' @rdname variable_moving_average_period +#' +#' @aliases variable_moving_average_period +MAVP <- variable_moving_average_period + +#' @export +#' @usage NULL +#' @rdname variable_moving_average_period +#' +#' @aliases variable_moving_average_period +variableMovingAveragePeriod <- variable_moving_average_period + +#' @usage NULL +#' @aliases variable_moving_average_period +#' +#' @export +variable_moving_average_period.default <- function( + x, + cols, + periods, + minimumPeriod = 2, + maximumPeriod = 30, + maType = 0, + na.bridge = FALSE, + ... +) { + ## 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, + ... + ) + + ## extract rownames + ## for later attachment + x_names <- rownames(constructed_series) + + ## calculate indicator and + ## return as data.frame + x <- .Call( + C_impl_ta_MAVP, + constructed_series[[1]], + as.double(periods), + as.integer(minimumPeriod), + as.integer(maximumPeriod), + as.maType(maType), + as.logical(na.bridge) + ) + + ## readd rownames + set_rownames(x, x_names) + + ## return indicator + x +} + +#' @usage NULL +#' @aliases variable_moving_average_period +#' +#' @export +variable_moving_average_period.data.frame <- function( + x, + cols, + periods, + minimumPeriod = 2, + maximumPeriod = 30, + maType = 0, + na.bridge = FALSE, + ... +) { + map_dfr( + variable_moving_average_period.default( + x = x, + cols = cols, + periods = periods, + minimumPeriod = minimumPeriod, + maximumPeriod = maximumPeriod, + maType = maType, + na.bridge = na.bridge, + ... + ) + ) +} + +#' @usage NULL +#' @aliases variable_moving_average_period +#' +#' @export +variable_moving_average_period.matrix <- function( + x, + cols, + periods, + minimumPeriod = 2, + maximumPeriod = 30, + maType = 0, + na.bridge = FALSE, + ... +) { + variable_moving_average_period.default( + x = x, + cols = cols, + periods = periods, + minimumPeriod = minimumPeriod, + maximumPeriod = maximumPeriod, + maType = maType, + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +MAVP_lookback <- variableMovingAveragePeriod_lookback <- variable_moving_average_period_lookback <- function( + x, + cols, + periods, + minimumPeriod = 2, + maximumPeriod = 30, + maType = 0, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_MAVP_lookback, + as.integer(minimumPeriod), + as.integer(maximumPeriod), + as.maType(maType) + ) +} + +#' @usage NULL +#' @aliases variable_moving_average_period +#' +#' @export +variable_moving_average_period.numeric <- function( + x, + cols, + periods, + minimumPeriod = 2, + maximumPeriod = 30, + maType = 0, + na.bridge = FALSE, + ... +) { + ## warn if 'cols' have been + ## passed just to make sure + ## the user knows its not possible + ## or relevant + if (!missing(cols)) { + warning("'cols' is passed but is unused for vectors.") + } + + ## pass the argument directly + ## to 'C' + x <- .Call( + C_impl_ta_MAVP, + as.double(x), + as.double(periods), + as.integer(minimumPeriod), + as.integer(maximumPeriod), + as.maType(maType), + as.logical(na.bridge) + ) + + if (dim(x)[2] == 1L) { + dim(x) <- NULL + } + + x +} + +#' @usage NULL +#' @aliases variable_moving_average_period +#' +#' @export +variable_moving_average_period.plotly <- function( + x, + cols, + periods, + minimumPeriod = 2, + maximumPeriod = 30, + maType = 0, + na.bridge = FALSE, + ## splice:optional-plotly:start + ## splice:optional-plotly:end + ... +) { + ## check that input value + ## 'x' is -object + assert_plotly_object(x) + + ## check that input value + ## 'cols' is a -objet + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series from + ## {plotly}-object + constructed_series <- series( + x = x, + formula = cols, + default_formula = ~close, + ... + ) + + ## construct indicator + ## from the series + constructed_indicator <- variable_moving_average_period( + x = constructed_series, + cols = rebuild_formula( + names(constructed_series) + ), + periods = periods, + minimumPeriod = minimumPeriod, + maximumPeriod = maximumPeriod, + maType = maType, + na.bridge = TRUE + ) + + ## add conditional idx + constructed_indicator[["idx"]] <- add_idx( + constructed_series + ) + + ## construct {plotly}-object + ## splice:plotly-assembly:start + traces <- lapply( + setdiff(colnames(constructed_indicator), "idx"), + function(col) { + list( + y = stats::as.formula( + paste0("~", col) + ), + name = col + ) + } + ) + name <- sprintf( + "MAVP(%d, %d, %s)", + min(minimumPeriod, maximumPeriod), + max(minimumPeriod, maximumPeriod), + mapMaType(maType) + ) + ## splice:plotly-assembly:end + + state <- .chart_state() + plotly_object <- build_plotly( + init = state[["main"]], + traces = traces, + decorators = list(), + name = get0( + x = "name", + ifnotfound = NULL + ), + data = constructed_indicator + ) + state[["main"]] <- plotly_object + + plotly_object +} + +#' @usage NULL +#' @aliases variable_moving_average_period +#' +#' @export +variable_moving_average_period.ggplot <- function( + x, + cols, + periods, + minimumPeriod = 2, + maximumPeriod = 30, + maType = 0, + na.bridge = FALSE, + ## splice:optional-ggplot:start + ## splice:optional-ggplot:end + ... +) { + ## check ggplot2 availability + assert_ggplot2() + + ## check that input value + ## 'cols' is a -objet + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series from + ## {ggplot}-object + constructed_series <- series( + x = x, + formula = cols, + default_formula = ~close, + ... + ) + + ## construct indicator + ## from the series + constructed_indicator <- variable_moving_average_period( + x = constructed_series, + cols = rebuild_formula( + names(constructed_series) + ), + periods = periods, + minimumPeriod = minimumPeriod, + maximumPeriod = maximumPeriod, + maType = maType, + na.bridge = TRUE + ) + + ## add conditional idx + constructed_indicator[["idx"]] <- add_idx( + constructed_series + ) + + ## construct {ggplot2}-object + ## splice:ggplot-assembly:start + layers <- lapply( + setdiff(colnames(constructed_indicator), "idx"), + function(col) list(y = col) + ) + name <- "MAVP" + ## splice:ggplot-assembly:end + + state <- .chart_state() + ggplot_object <- build_ggplot( + init = state[["main"]], + layers = layers, + decorators = list(), + name = get0( + x = "name", + ifnotfound = NULL + ), + data = constructed_indicator + ) + state[["main"]] <- ggplot_object + + ggplot_object +} diff --git a/R/ta_MAX.R b/R/ta_MAX.R index 4f65c5298..c76d35519 100644 --- a/R/ta_MAX.R +++ b/R/ta_MAX.R @@ -1,39 +1,49 @@ #' @export -#' @family Rolling Statistic +#' @family Rolling Statistics #' -#' @title Rolling Max -#' @templateVar .title Rolling Max +#' @title Highest value over a specified period +#' @templateVar .title Highest value over a specified period #' @templateVar .author Serkan Korkmaz -#' @templateVar .fun rolling_max +#' @templateVar .fun rolling_maximum #' ## splice:documentation:start ## splice:documentation:end #' #' @template rolling_description +#' #' @template rolling_returns -rolling_max <- function( +rolling_maximum <- function( x, - n = 30, - na.bridge = FALSE + timePeriod = 30, + na.bridge = FALSE, + ... ) { - UseMethod("rolling_max") + UseMethod("rolling_maximum") } #' @export #' @usage NULL -#' @rdname rolling_max +#' @rdname rolling_maximum #' -#' @aliases rolling_max -MAX <- rolling_max +#' @aliases rolling_maximum +MAX <- rolling_maximum +#' @export #' @usage NULL -#' @aliases rolling_max +#' @rdname rolling_maximum +#' +#' @aliases rolling_maximum +rollingMaximum <- rolling_maximum + +#' @usage NULL +#' @aliases rolling_maximum #' #' @export -rolling_max.default <- function( +rolling_maximum.default <- function( x, - n = 30, - na.bridge = FALSE + timePeriod = 30, + na.bridge = FALSE, + ... ) { ## calculate indicator and ## return as data.frame @@ -41,32 +51,56 @@ rolling_max.default <- function( C_impl_ta_MAX, ## splice:call:start as.double(x), - as.integer(n), + as.integer(timePeriod), ## splice:call:end as.logical(na.bridge) ) + ## strip dimensions + ## while preserving + ## attributes + dim(x) <- NULL + ## return indicator - as.double(x) + x } #' @usage NULL -#' @aliases rolling_max +#' @aliases rolling_maximum #' #' @export -rolling_max.numeric <- function( +rolling_maximum.numeric <- function( x, - n = 30, - na.bridge = FALSE + timePeriod = 30, + na.bridge = FALSE, + ... ) { ## calculate indicator and ## return as data.frame - x <- rolling_max.default( + x <- rolling_maximum.default( x = x, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge ) + ## strip dimensions + ## while preserving + ## attributes + dim(x) <- NULL + ## return indicator - as.double(x) + x +} + +#' @usage NULL +MAX_lookback <- rollingMaximum_lookback <- rolling_maximum_lookback <- function( + x, + timePeriod = 30, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_MAX_lookback, + as.integer(timePeriod) + ) } diff --git a/R/ta_MEDPRICE.R b/R/ta_MEDPRICE.R index d3dbb04dc..a81bd341b 100644 --- a/R/ta_MEDPRICE.R +++ b/R/ta_MEDPRICE.R @@ -12,6 +12,7 @@ ## splice:documentation:end #' #' @template description +#' #' @template returns median_price <- function( x, @@ -29,6 +30,13 @@ median_price <- function( #' @aliases median_price MEDPRICE <- median_price +#' @export +#' @usage NULL +#' @rdname median_price +#' +#' @aliases median_price +medianPrice <- median_price + #' @usage NULL #' @aliases median_price #' @@ -62,10 +70,8 @@ median_price.default <- function( ## return as data.frame x <- .Call( C_impl_ta_MEDPRICE, - ## splice:call:start constructed_series[[1]], constructed_series[[2]], - ## splice:call:end as.logical(na.bridge) ) @@ -113,3 +119,15 @@ median_price.matrix <- function( ... ) } + +#' @usage NULL +MEDPRICE_lookback <- medianPrice_lookback <- median_price_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_MEDPRICE_lookback + ) +} diff --git a/R/ta_MFI.R b/R/ta_MFI.R index 7849841d2..d3262386d 100644 --- a/R/ta_MFI.R +++ b/R/ta_MFI.R @@ -1,22 +1,23 @@ #' @export -#' @family Momentum Indicator +#' @family Momentum Indicators #' #' @title Money Flow Index #' @templateVar .title Money Flow Index #' @templateVar .author Serkan Korkmaz #' @templateVar .fun money_flow_index -#' @templateVar .family Momentum Indicator -#' @templateVar .formula ~ high + low + close + volume +#' @templateVar .family Momentum Indicators +#' @templateVar .formula ~high + low + close + volume #' ## splice:documentation:start ## splice:documentation:end #' #' @template description +#' #' @template returns money_flow_index <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -30,6 +31,13 @@ money_flow_index <- function( #' @aliases money_flow_index MFI <- money_flow_index +#' @export +#' @usage NULL +#' @rdname money_flow_index +#' +#' @aliases money_flow_index +moneyFlowIndex <- money_flow_index + #' @usage NULL #' @aliases money_flow_index #' @@ -37,7 +45,7 @@ MFI <- money_flow_index money_flow_index.default <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -64,13 +72,11 @@ money_flow_index.default <- function( ## return as data.frame x <- .Call( C_impl_ta_MFI, - ## splice:call:start constructed_series[[1]], constructed_series[[2]], constructed_series[[3]], constructed_series[[4]], - as.integer(n), - ## splice:call:end + as.integer(timePeriod), as.logical(na.bridge) ) @@ -88,7 +94,7 @@ money_flow_index.default <- function( money_flow_index.data.frame <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -96,7 +102,7 @@ money_flow_index.data.frame <- function( money_flow_index.default( x = x, cols = cols, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge, ... ) @@ -110,19 +116,32 @@ money_flow_index.data.frame <- function( money_flow_index.matrix <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { money_flow_index.default( x = x, cols = cols, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge, ... ) } +#' @usage NULL +MFI_lookback <- moneyFlowIndex_lookback <- money_flow_index_lookback <- function( + x, + cols, + timePeriod = 14, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_MFI_lookback, + as.integer(timePeriod) + ) +} #' @usage NULL #' @aliases money_flow_index @@ -131,7 +150,7 @@ money_flow_index.matrix <- function( money_flow_index.plotly <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ## splice:optional-plotly:start lower_bound = -20, @@ -166,7 +185,7 @@ money_flow_index.plotly <- function( cols = rebuild_formula( names(constructed_series) ), - n = n, + timePeriod = timePeriod, na.bridge = TRUE ) @@ -185,7 +204,7 @@ money_flow_index.plotly <- function( ## splice:plotly-assembly:start name <- sprintf( "MFI(%d)", - n + timePeriod ) traces <- list( @@ -215,7 +234,8 @@ money_flow_index.plotly <- function( } ), data = constructed_indicator[, values_to_extract, drop = FALSE], - values_to_extract = values_to_extract + values_to_extract = values_to_extract, + name = get0(x = "name", ifnotfound = NULL) ) state <- .chart_state() @@ -231,11 +251,11 @@ money_flow_index.plotly <- function( money_flow_index.ggplot <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, + title, ## splice:optional-ggplot:start ## splice:optional-ggplot:end - title, ... ) { ## check ggplot2 availability @@ -263,7 +283,7 @@ money_flow_index.ggplot <- function( cols = rebuild_formula( names(constructed_series) ), - n = n, + timePeriod = timePeriod, na.bridge = TRUE ) @@ -285,7 +305,7 @@ money_flow_index.ggplot <- function( ggplot_line(80), list(y = "MFI") ) - name <- sprintf("MFI(%d)", n) + name <- sprintf("MFI(%d)", timePeriod) ## splice:ggplot-assembly:end ggplot_object <- add_last_value_gg( diff --git a/R/ta_ROC.R b/R/ta_MIDPOINT.R similarity index 53% rename from R/ta_ROC.R rename to R/ta_MIDPOINT.R index 65a5b4325..12e43cce5 100644 --- a/R/ta_ROC.R +++ b/R/ta_MIDPOINT.R @@ -1,43 +1,51 @@ #' @export -#' @family Momentum Indicator +#' @family Overlap Studies #' -#' @title Rate of Change -#' @templateVar .title Rate of Change +#' @title MidPoint over period +#' @templateVar .title MidPoint over period #' @templateVar .author Serkan Korkmaz -#' @templateVar .fun rate_of_change -#' @templateVar .family Momentum Indicator +#' @templateVar .fun midpoint_period +#' @templateVar .family Overlap Studies #' @templateVar .formula ~close #' ## splice:documentation:start ## splice:documentation:end #' #' @template description +#' #' @template returns -rate_of_change <- function( +midpoint_period <- function( x, cols, - n = 10, + timePeriod = 14, na.bridge = FALSE, ... ) { - UseMethod("rate_of_change") + UseMethod("midpoint_period") } #' @export #' @usage NULL -#' @rdname rate_of_change +#' @rdname midpoint_period #' -#' @aliases rate_of_change -ROC <- rate_of_change +#' @aliases midpoint_period +MIDPOINT <- midpoint_period +#' @export #' @usage NULL -#' @aliases rate_of_change +#' @rdname midpoint_period +#' +#' @aliases midpoint_period +midpointPeriod <- midpoint_period + +#' @usage NULL +#' @aliases midpoint_period #' #' @export -rate_of_change.default <- function( +midpoint_period.default <- function( x, cols, - n = 10, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -63,11 +71,9 @@ rate_of_change.default <- function( ## calculate indicator and ## return as data.frame x <- .Call( - C_impl_ta_ROC, - ## splice:call:start + C_impl_ta_MIDPOINT, constructed_series[[1]], - as.integer(n), - ## splice:call:end + as.integer(timePeriod), as.logical(na.bridge) ) @@ -79,21 +85,21 @@ rate_of_change.default <- function( } #' @usage NULL -#' @aliases rate_of_change +#' @aliases midpoint_period #' #' @export -rate_of_change.data.frame <- function( +midpoint_period.data.frame <- function( x, cols, - n = 10, + timePeriod = 14, na.bridge = FALSE, ... ) { map_dfr( - rate_of_change.default( + midpoint_period.default( x = x, cols = cols, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge, ... ) @@ -101,34 +107,47 @@ rate_of_change.data.frame <- function( } #' @usage NULL -#' @aliases rate_of_change +#' @aliases midpoint_period #' #' @export -rate_of_change.matrix <- function( +midpoint_period.matrix <- function( x, cols, - n = 10, + timePeriod = 14, na.bridge = FALSE, ... ) { - rate_of_change.default( + midpoint_period.default( x = x, cols = cols, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge, ... ) } +#' @usage NULL +MIDPOINT_lookback <- midpointPeriod_lookback <- midpoint_period_lookback <- function( + x, + cols, + timePeriod = 14, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_MIDPOINT_lookback, + as.integer(timePeriod) + ) +} #' @usage NULL -#' @aliases rate_of_change +#' @aliases midpoint_period #' #' @export -rate_of_change.numeric <- function( +midpoint_period.numeric <- function( x, cols, - n = 10, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -143,42 +162,30 @@ rate_of_change.numeric <- function( ## pass the argument directly ## to 'C' x <- .Call( - C_impl_ta_ROC, - ## splice:numeric:start + C_impl_ta_MIDPOINT, as.double(x), - as.integer(n), - ## splice:numeric:end + as.integer(timePeriod), 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 -#' @aliases rate_of_change +#' @aliases midpoint_period #' #' @export -rate_of_change.plotly <- function( +midpoint_period.plotly <- function( x, cols, - n = 10, + timePeriod = 14, na.bridge = FALSE, ## splice:optional-plotly:start ## splice:optional-plotly:end - title, ... ) { ## check that input value @@ -202,21 +209,15 @@ rate_of_change.plotly <- function( ## construct indicator ## from the series - constructed_indicator <- rate_of_change( + constructed_indicator <- midpoint_period( x = constructed_series, cols = rebuild_formula( names(constructed_series) ), - n = n, + timePeriod = timePeriod, na.bridge = TRUE ) - ## the constructed indicator - ## always returns excpected - ## columns which can be passed - ## down to add_last_values() - values_to_extract <- colnames(constructed_indicator) - ## add conditional idx constructed_indicator[["idx"]] <- add_idx( constructed_series @@ -224,59 +225,47 @@ rate_of_change.plotly <- function( ## construct {plotly}-object ## splice:plotly-assembly:start - name <- sprintf( - "ROC(%d)", - n - ) - - traces <- list( - list( - y = ~ROC - ) + traces <- lapply( + setdiff(colnames(constructed_indicator), "idx"), + function(col) { + list( + y = stats::as.formula( + paste0("~", col) + ), + name = col + ) + } ) + name <- "MIDPOINT" ## splice:plotly-assembly:end - plotly_object <- add_last_value_ly( - build_plotly( - init = plotly_init(), - traces = traces, - decorators = get0( - x = "decorators", - ifnotfound = list() - ), - name = get0( - x = "name", - ifnotfound = NULL - ), - data = constructed_indicator, - title = if (missing(title)) { - "Rate of Change" - } else { - title - } + state <- .chart_state() + plotly_object <- build_plotly( + init = state[["main"]], + traces = traces, + decorators = list(), + name = get0( + x = "name", + ifnotfound = NULL ), - data = constructed_indicator[, values_to_extract, drop = FALSE], - values_to_extract = values_to_extract + data = constructed_indicator ) - - state <- .chart_state() - state$sub <- c(state$sub, list(plotly_object)) + state[["main"]] <- plotly_object plotly_object } #' @usage NULL -#' @aliases rate_of_change +#' @aliases midpoint_period #' #' @export -rate_of_change.ggplot <- function( +midpoint_period.ggplot <- function( x, cols, - n = 10, + timePeriod = 14, na.bridge = FALSE, ## splice:optional-ggplot:start ## splice:optional-ggplot:end - title, ... ) { ## check ggplot2 availability @@ -299,21 +288,15 @@ rate_of_change.ggplot <- function( ## construct indicator ## from the series - constructed_indicator <- rate_of_change( + constructed_indicator <- midpoint_period( x = constructed_series, cols = rebuild_formula( names(constructed_series) ), - n = n, + timePeriod = timePeriod, na.bridge = TRUE ) - ## the constructed indicator - ## always returns expected - ## columns which can be passed - ## down to add_last_value_gg() - values_to_extract <- colnames(constructed_indicator) - ## add conditional idx constructed_indicator[["idx"]] <- add_idx( constructed_series @@ -325,35 +308,21 @@ rate_of_change.ggplot <- function( setdiff(colnames(constructed_indicator), "idx"), function(col) list(y = col) ) - name <- sprintf("ROC(%d)", n) + name <- "MIDPOINT" ## splice:ggplot-assembly:end - ggplot_object <- add_last_value_gg( - build_ggplot( - init = ggplot_init(), - layers = layers, - decorators = get0( - x = "decorators", - ifnotfound = list() - ), - name = get0( - x = "name", - ifnotfound = NULL - ), - data = constructed_indicator, - title = if (missing(title)) { - "Rate of Change" - } else { - title - } + state <- .chart_state() + ggplot_object <- build_ggplot( + init = state[["main"]], + layers = layers, + decorators = list(), + name = get0( + x = "name", + ifnotfound = NULL ), - data = constructed_indicator[, values_to_extract, drop = FALSE], - values_to_extract = values_to_extract, - name = get0(x = "name", ifnotfound = NULL) + data = constructed_indicator ) - - state <- .chart_state() - state$sub <- c(state$sub, list(ggplot_object)) + state[["main"]] <- ggplot_object ggplot_object } diff --git a/R/ta_MIDPRICE.R b/R/ta_MIDPRICE.R index ef6a798fe..9905c4812 100644 --- a/R/ta_MIDPRICE.R +++ b/R/ta_MIDPRICE.R @@ -1,22 +1,23 @@ #' @export -#' @family Price Transform +#' @family Overlap Studies #' -#' @title Midpoint Price -#' @templateVar .title Midpoint Price +#' @title Midpoint Price over period +#' @templateVar .title Midpoint Price over period #' @templateVar .author Serkan Korkmaz #' @templateVar .fun midpoint_price -#' @templateVar .family Price Transform +#' @templateVar .family Overlap Studies #' @templateVar .formula ~high + low #' ## splice:documentation:start ## splice:documentation:end #' #' @template description +#' #' @template returns midpoint_price <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -30,6 +31,13 @@ midpoint_price <- function( #' @aliases midpoint_price MIDPRICE <- midpoint_price +#' @export +#' @usage NULL +#' @rdname midpoint_price +#' +#' @aliases midpoint_price +midpointPrice <- midpoint_price + #' @usage NULL #' @aliases midpoint_price #' @@ -37,7 +45,7 @@ MIDPRICE <- midpoint_price midpoint_price.default <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -64,11 +72,9 @@ midpoint_price.default <- function( ## return as data.frame x <- .Call( C_impl_ta_MIDPRICE, - ## splice:call:start constructed_series[[1]], constructed_series[[2]], - as.integer(n), - ## splice:call:end + as.integer(timePeriod), as.logical(na.bridge) ) @@ -86,7 +92,7 @@ midpoint_price.default <- function( midpoint_price.data.frame <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -94,7 +100,7 @@ midpoint_price.data.frame <- function( midpoint_price.default( x = x, cols = cols, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge, ... ) @@ -108,15 +114,181 @@ midpoint_price.data.frame <- function( midpoint_price.matrix <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { midpoint_price.default( x = x, cols = cols, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge, ... ) } + +#' @usage NULL +MIDPRICE_lookback <- midpointPrice_lookback <- midpoint_price_lookback <- function( + x, + cols, + timePeriod = 14, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_MIDPRICE_lookback, + as.integer(timePeriod) + ) +} + +#' @usage NULL +#' @aliases midpoint_price +#' +#' @export +midpoint_price.plotly <- function( + x, + cols, + timePeriod = 14, + na.bridge = FALSE, + ## splice:optional-plotly:start + ## splice:optional-plotly:end + ... +) { + ## check that input value + ## 'x' is -object + assert_plotly_object(x) + + ## check that input value + ## 'cols' is a -objet + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series from + ## {plotly}-object + constructed_series <- series( + x = x, + formula = cols, + default_formula = ~ high + low, + ... + ) + + ## construct indicator + ## from the series + constructed_indicator <- midpoint_price( + x = constructed_series, + cols = rebuild_formula( + names(constructed_series) + ), + timePeriod = timePeriod, + na.bridge = TRUE + ) + + ## add conditional idx + constructed_indicator[["idx"]] <- add_idx( + constructed_series + ) + + ## construct {plotly}-object + ## splice:plotly-assembly:start + traces <- lapply( + setdiff(colnames(constructed_indicator), "idx"), + function(col) { + list( + y = stats::as.formula( + paste0("~", col) + ), + name = col + ) + } + ) + name <- "MIDPRICE" + ## splice:plotly-assembly:end + + state <- .chart_state() + plotly_object <- build_plotly( + init = state[["main"]], + traces = traces, + decorators = list(), + name = get0( + x = "name", + ifnotfound = NULL + ), + data = constructed_indicator + ) + state[["main"]] <- plotly_object + + plotly_object +} + +#' @usage NULL +#' @aliases midpoint_price +#' +#' @export +midpoint_price.ggplot <- function( + x, + cols, + timePeriod = 14, + na.bridge = FALSE, + ## splice:optional-ggplot:start + ## splice:optional-ggplot:end + ... +) { + ## check ggplot2 availability + assert_ggplot2() + + ## check that input value + ## 'cols' is a -objet + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series from + ## {ggplot}-object + constructed_series <- series( + x = x, + formula = cols, + default_formula = ~ high + low, + ... + ) + + ## construct indicator + ## from the series + constructed_indicator <- midpoint_price( + x = constructed_series, + cols = rebuild_formula( + names(constructed_series) + ), + timePeriod = timePeriod, + na.bridge = TRUE + ) + + ## add conditional idx + constructed_indicator[["idx"]] <- add_idx( + constructed_series + ) + + ## construct {ggplot2}-object + ## splice:ggplot-assembly:start + layers <- lapply( + setdiff(colnames(constructed_indicator), "idx"), + function(col) list(y = col) + ) + name <- "MIDPRICE" + ## splice:ggplot-assembly:end + + state <- .chart_state() + ggplot_object <- build_ggplot( + init = state[["main"]], + layers = layers, + decorators = list(), + name = get0( + x = "name", + ifnotfound = NULL + ), + data = constructed_indicator + ) + state[["main"]] <- ggplot_object + + ggplot_object +} diff --git a/R/ta_MIN.R b/R/ta_MIN.R index d9535346e..52d0d4db2 100644 --- a/R/ta_MIN.R +++ b/R/ta_MIN.R @@ -1,39 +1,49 @@ #' @export -#' @family Rolling Statistic +#' @family Rolling Statistics #' -#' @title Rolling Min -#' @templateVar .title Rolling Min +#' @title Lowest value over a specified period +#' @templateVar .title Lowest value over a specified period #' @templateVar .author Serkan Korkmaz -#' @templateVar .fun rolling_min +#' @templateVar .fun rolling_minimum #' ## splice:documentation:start ## splice:documentation:end #' #' @template rolling_description +#' #' @template rolling_returns -rolling_min <- function( +rolling_minimum <- function( x, - n = 30, - na.bridge = FALSE + timePeriod = 30, + na.bridge = FALSE, + ... ) { - UseMethod("rolling_min") + UseMethod("rolling_minimum") } #' @export #' @usage NULL -#' @rdname rolling_min +#' @rdname rolling_minimum #' -#' @aliases rolling_min -MIN <- rolling_min +#' @aliases rolling_minimum +MIN <- rolling_minimum +#' @export #' @usage NULL -#' @aliases rolling_min +#' @rdname rolling_minimum +#' +#' @aliases rolling_minimum +rollingMinimum <- rolling_minimum + +#' @usage NULL +#' @aliases rolling_minimum #' #' @export -rolling_min.default <- function( +rolling_minimum.default <- function( x, - n = 30, - na.bridge = FALSE + timePeriod = 30, + na.bridge = FALSE, + ... ) { ## calculate indicator and ## return as data.frame @@ -41,32 +51,56 @@ rolling_min.default <- function( C_impl_ta_MIN, ## splice:call:start as.double(x), - as.integer(n), + as.integer(timePeriod), ## splice:call:end as.logical(na.bridge) ) + ## strip dimensions + ## while preserving + ## attributes + dim(x) <- NULL + ## return indicator - as.double(x) + x } #' @usage NULL -#' @aliases rolling_min +#' @aliases rolling_minimum #' #' @export -rolling_min.numeric <- function( +rolling_minimum.numeric <- function( x, - n = 30, - na.bridge = FALSE + timePeriod = 30, + na.bridge = FALSE, + ... ) { ## calculate indicator and ## return as data.frame - x <- rolling_min.default( + x <- rolling_minimum.default( x = x, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge ) + ## strip dimensions + ## while preserving + ## attributes + dim(x) <- NULL + ## return indicator - as.double(x) + x +} + +#' @usage NULL +MIN_lookback <- rollingMinimum_lookback <- rolling_minimum_lookback <- function( + x, + timePeriod = 30, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_MIN_lookback, + as.integer(timePeriod) + ) } diff --git a/R/ta_MINUS_DI.R b/R/ta_MINUS_DI.R index 22dcea0d3..2499c2134 100644 --- a/R/ta_MINUS_DI.R +++ b/R/ta_MINUS_DI.R @@ -1,22 +1,23 @@ #' @export -#' @family Momentum Indicator +#' @family Momentum Indicators #' #' @title Minus Directional Indicator #' @templateVar .title Minus Directional Indicator #' @templateVar .author Serkan Korkmaz #' @templateVar .fun minus_directional_indicator -#' @templateVar .family Momentum Indicator +#' @templateVar .family Momentum Indicators #' @templateVar .formula ~high + low + close #' ## splice:documentation:start ## splice:documentation:end #' #' @template description +#' #' @template returns minus_directional_indicator <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -30,6 +31,13 @@ minus_directional_indicator <- function( #' @aliases minus_directional_indicator MINUS_DI <- minus_directional_indicator +#' @export +#' @usage NULL +#' @rdname minus_directional_indicator +#' +#' @aliases minus_directional_indicator +minusDirectionalIndicator <- minus_directional_indicator + #' @usage NULL #' @aliases minus_directional_indicator #' @@ -37,7 +45,7 @@ MINUS_DI <- minus_directional_indicator minus_directional_indicator.default <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -64,12 +72,10 @@ minus_directional_indicator.default <- function( ## return as data.frame x <- .Call( C_impl_ta_MINUS_DI, - ## splice:call:start constructed_series[[1]], constructed_series[[2]], constructed_series[[3]], - as.integer(n), - ## splice:call:end + as.integer(timePeriod), as.logical(na.bridge) ) @@ -87,7 +93,7 @@ minus_directional_indicator.default <- function( minus_directional_indicator.data.frame <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -95,7 +101,7 @@ minus_directional_indicator.data.frame <- function( minus_directional_indicator.default( x = x, cols = cols, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge, ... ) @@ -109,19 +115,32 @@ minus_directional_indicator.data.frame <- function( minus_directional_indicator.matrix <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { minus_directional_indicator.default( x = x, cols = cols, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge, ... ) } +#' @usage NULL +MINUS_DI_lookback <- minusDirectionalIndicator_lookback <- minus_directional_indicator_lookback <- function( + x, + cols, + timePeriod = 14, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_MINUS_DI_lookback, + as.integer(timePeriod) + ) +} #' @usage NULL #' @aliases minus_directional_indicator @@ -130,7 +149,7 @@ minus_directional_indicator.matrix <- function( minus_directional_indicator.plotly <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ## splice:optional-plotly:start ## splice:optional-plotly:end @@ -163,7 +182,7 @@ minus_directional_indicator.plotly <- function( cols = rebuild_formula( names(constructed_series) ), - n = n, + timePeriod = timePeriod, na.bridge = TRUE ) @@ -180,7 +199,7 @@ minus_directional_indicator.plotly <- function( ## construct {plotly}-object ## splice:plotly-assembly:start - name <- sprintf("-DI(%d)", n) + name <- sprintf("-DI(%d)", timePeriod) traces <- list( list(y = ~MINUS_DI) @@ -207,7 +226,8 @@ minus_directional_indicator.plotly <- function( } ), data = constructed_indicator[, values_to_extract, drop = FALSE], - values_to_extract = values_to_extract + values_to_extract = values_to_extract, + name = get0(x = "name", ifnotfound = NULL) ) state <- .chart_state() @@ -223,11 +243,11 @@ minus_directional_indicator.plotly <- function( minus_directional_indicator.ggplot <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, + title, ## splice:optional-ggplot:start ## splice:optional-ggplot:end - title, ... ) { ## check ggplot2 availability @@ -255,7 +275,7 @@ minus_directional_indicator.ggplot <- function( cols = rebuild_formula( names(constructed_series) ), - n = n, + timePeriod = timePeriod, na.bridge = TRUE ) @@ -276,7 +296,7 @@ minus_directional_indicator.ggplot <- function( setdiff(colnames(constructed_indicator), "idx"), function(col) list(y = col) ) - name <- sprintf("-DI(%d)", n) + name <- sprintf("-DI(%d)", timePeriod) ## splice:ggplot-assembly:end ggplot_object <- add_last_value_gg( diff --git a/R/ta_MINUS_DM.R b/R/ta_MINUS_DM.R index c46367eee..b31275164 100644 --- a/R/ta_MINUS_DM.R +++ b/R/ta_MINUS_DM.R @@ -1,22 +1,23 @@ #' @export -#' @family Momentum Indicator +#' @family Momentum Indicators #' #' @title Minus Directional Movement #' @templateVar .title Minus Directional Movement #' @templateVar .author Serkan Korkmaz #' @templateVar .fun minus_directional_movement -#' @templateVar .family Momentum Indicator +#' @templateVar .family Momentum Indicators #' @templateVar .formula ~high + low #' ## splice:documentation:start ## splice:documentation:end #' #' @template description +#' #' @template returns minus_directional_movement <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -30,6 +31,13 @@ minus_directional_movement <- function( #' @aliases minus_directional_movement MINUS_DM <- minus_directional_movement +#' @export +#' @usage NULL +#' @rdname minus_directional_movement +#' +#' @aliases minus_directional_movement +minusDirectionalMovement <- minus_directional_movement + #' @usage NULL #' @aliases minus_directional_movement #' @@ -37,7 +45,7 @@ MINUS_DM <- minus_directional_movement minus_directional_movement.default <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -64,11 +72,9 @@ minus_directional_movement.default <- function( ## return as data.frame x <- .Call( C_impl_ta_MINUS_DM, - ## splice:call:start constructed_series[[1]], constructed_series[[2]], - as.integer(n), - ## splice:call:end + as.integer(timePeriod), as.logical(na.bridge) ) @@ -86,7 +92,7 @@ minus_directional_movement.default <- function( minus_directional_movement.data.frame <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -94,7 +100,7 @@ minus_directional_movement.data.frame <- function( minus_directional_movement.default( x = x, cols = cols, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge, ... ) @@ -108,19 +114,32 @@ minus_directional_movement.data.frame <- function( minus_directional_movement.matrix <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { minus_directional_movement.default( x = x, cols = cols, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge, ... ) } +#' @usage NULL +MINUS_DM_lookback <- minusDirectionalMovement_lookback <- minus_directional_movement_lookback <- function( + x, + cols, + timePeriod = 14, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_MINUS_DM_lookback, + as.integer(timePeriod) + ) +} #' @usage NULL #' @aliases minus_directional_movement @@ -129,7 +148,7 @@ minus_directional_movement.matrix <- function( minus_directional_movement.plotly <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ## splice:optional-plotly:start ## splice:optional-plotly:end @@ -162,7 +181,7 @@ minus_directional_movement.plotly <- function( cols = rebuild_formula( names(constructed_series) ), - n = n, + timePeriod = timePeriod, na.bridge = TRUE ) @@ -179,7 +198,7 @@ minus_directional_movement.plotly <- function( ## construct {plotly}-object ## splice:plotly-assembly:start - name <- sprintf("-DM(%d)", n) + name <- sprintf("-DM(%d)", timePeriod) traces <- list( list(y = ~MINUS_DM) @@ -206,7 +225,8 @@ minus_directional_movement.plotly <- function( } ), data = constructed_indicator[, values_to_extract, drop = FALSE], - values_to_extract = values_to_extract + values_to_extract = values_to_extract, + name = get0(x = "name", ifnotfound = NULL) ) state <- .chart_state() @@ -222,11 +242,11 @@ minus_directional_movement.plotly <- function( minus_directional_movement.ggplot <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, + title, ## splice:optional-ggplot:start ## splice:optional-ggplot:end - title, ... ) { ## check ggplot2 availability @@ -254,7 +274,7 @@ minus_directional_movement.ggplot <- function( cols = rebuild_formula( names(constructed_series) ), - n = n, + timePeriod = timePeriod, na.bridge = TRUE ) @@ -275,7 +295,7 @@ minus_directional_movement.ggplot <- function( setdiff(colnames(constructed_indicator), "idx"), function(col) list(y = col) ) - name <- sprintf("-DM(%d)", n) + name <- sprintf("-DM(%d)", timePeriod) ## splice:ggplot-assembly:end ggplot_object <- add_last_value_gg( diff --git a/R/ta_MOM.R b/R/ta_MOM.R index df7120207..0b55a4ec5 100644 --- a/R/ta_MOM.R +++ b/R/ta_MOM.R @@ -1,22 +1,23 @@ #' @export -#' @family Momentum Indicator +#' @family Momentum Indicators #' #' @title Momentum #' @templateVar .title Momentum #' @templateVar .author Serkan Korkmaz #' @templateVar .fun momentum -#' @templateVar .family Momentum Indicator -#' @templateVar .formula ~ close +#' @templateVar .family Momentum Indicators +#' @templateVar .formula ~close #' ## splice:documentation:start ## splice:documentation:end #' #' @template description +#' #' @template returns momentum <- function( x, cols, - n = 10, + timePeriod = 10, na.bridge = FALSE, ... ) { @@ -37,7 +38,7 @@ MOM <- momentum momentum.default <- function( x, cols, - n = 10, + timePeriod = 10, na.bridge = FALSE, ... ) { @@ -64,10 +65,8 @@ momentum.default <- function( ## return as data.frame x <- .Call( C_impl_ta_MOM, - ## splice:call:start constructed_series[[1]], - as.integer(n), - ## splice:call:end + as.integer(timePeriod), as.logical(na.bridge) ) @@ -85,7 +84,7 @@ momentum.default <- function( momentum.data.frame <- function( x, cols, - n = 10, + timePeriod = 10, na.bridge = FALSE, ... ) { @@ -93,7 +92,7 @@ momentum.data.frame <- function( momentum.default( x = x, cols = cols, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge, ... ) @@ -107,19 +106,32 @@ momentum.data.frame <- function( momentum.matrix <- function( x, cols, - n = 10, + timePeriod = 10, na.bridge = FALSE, ... ) { momentum.default( x = x, cols = cols, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge, ... ) } +#' @usage NULL +MOM_lookback <- momentum_lookback <- function( + x, + cols, + timePeriod = 10, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_MOM_lookback, + as.integer(timePeriod) + ) +} #' @usage NULL #' @aliases momentum @@ -128,7 +140,7 @@ momentum.matrix <- function( momentum.numeric <- function( x, cols, - n = 10, + timePeriod = 10, na.bridge = FALSE, ... ) { @@ -144,29 +156,18 @@ momentum.numeric <- function( ## to 'C' x <- .Call( C_impl_ta_MOM, - ## splice:numeric:start as.double(x), - as.integer(n), - ## splice:numeric:end + as.integer(timePeriod), 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 #' @aliases momentum #' @@ -174,7 +175,7 @@ momentum.numeric <- function( momentum.plotly <- function( x, cols, - n = 10, + timePeriod = 10, na.bridge = FALSE, ## splice:optional-plotly:start ## splice:optional-plotly:end @@ -207,7 +208,7 @@ momentum.plotly <- function( cols = rebuild_formula( names(constructed_series) ), - n = n, + timePeriod = timePeriod, na.bridge = TRUE ) @@ -226,7 +227,7 @@ momentum.plotly <- function( ## splice:plotly-assembly:start name <- sprintf( "MOM(%d)", - n + timePeriod ) traces <- list( @@ -254,7 +255,8 @@ momentum.plotly <- function( } ), data = constructed_indicator[, values_to_extract, drop = FALSE], - values_to_extract = values_to_extract + values_to_extract = values_to_extract, + name = get0(x = "name", ifnotfound = NULL) ) state <- .chart_state() @@ -270,11 +272,11 @@ momentum.plotly <- function( momentum.ggplot <- function( x, cols, - n = 10, + timePeriod = 10, na.bridge = FALSE, + title, ## splice:optional-ggplot:start ## splice:optional-ggplot:end - title, ... ) { ## check ggplot2 availability @@ -302,7 +304,7 @@ momentum.ggplot <- function( cols = rebuild_formula( names(constructed_series) ), - n = n, + timePeriod = timePeriod, na.bridge = TRUE ) @@ -323,7 +325,7 @@ momentum.ggplot <- function( setdiff(colnames(constructed_indicator), "idx"), function(col) list(y = col) ) - name <- sprintf("MOM(%d)", n) + name <- sprintf("MOM(%d)", timePeriod) ## splice:ggplot-assembly:end ggplot_object <- add_last_value_gg( diff --git a/R/ta_NATR.R b/R/ta_NATR.R index aaa630e4a..715281eb9 100644 --- a/R/ta_NATR.R +++ b/R/ta_NATR.R @@ -1,22 +1,23 @@ #' @export -#' @family Volatility Indicator +#' @family Volatility Indicators #' #' @title Normalized Average True Range #' @templateVar .title Normalized Average True Range #' @templateVar .author Serkan Korkmaz #' @templateVar .fun normalized_average_true_range -#' @templateVar .family Volatility Indicator +#' @templateVar .family Volatility Indicators #' @templateVar .formula ~high + low + close #' ## splice:documentation:start ## splice:documentation:end #' #' @template description +#' #' @template returns normalized_average_true_range <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -30,6 +31,13 @@ normalized_average_true_range <- function( #' @aliases normalized_average_true_range NATR <- normalized_average_true_range +#' @export +#' @usage NULL +#' @rdname normalized_average_true_range +#' +#' @aliases normalized_average_true_range +normalizedAverageTrueRange <- normalized_average_true_range + #' @usage NULL #' @aliases normalized_average_true_range #' @@ -37,7 +45,7 @@ NATR <- normalized_average_true_range normalized_average_true_range.default <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -64,12 +72,10 @@ normalized_average_true_range.default <- function( ## return as data.frame x <- .Call( C_impl_ta_NATR, - ## splice:call:start constructed_series[[1]], constructed_series[[2]], constructed_series[[3]], - as.integer(n), - ## splice:call:end + as.integer(timePeriod), as.logical(na.bridge) ) @@ -87,7 +93,7 @@ normalized_average_true_range.default <- function( normalized_average_true_range.data.frame <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -95,7 +101,7 @@ normalized_average_true_range.data.frame <- function( normalized_average_true_range.default( x = x, cols = cols, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge, ... ) @@ -109,19 +115,32 @@ normalized_average_true_range.data.frame <- function( normalized_average_true_range.matrix <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { normalized_average_true_range.default( x = x, cols = cols, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge, ... ) } +#' @usage NULL +NATR_lookback <- normalizedAverageTrueRange_lookback <- normalized_average_true_range_lookback <- function( + x, + cols, + timePeriod = 14, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_NATR_lookback, + as.integer(timePeriod) + ) +} #' @usage NULL #' @aliases normalized_average_true_range @@ -130,7 +149,7 @@ normalized_average_true_range.matrix <- function( normalized_average_true_range.plotly <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ## splice:optional-plotly:start ## splice:optional-plotly:end @@ -163,7 +182,7 @@ normalized_average_true_range.plotly <- function( cols = rebuild_formula( names(constructed_series) ), - n = n, + timePeriod = timePeriod, na.bridge = TRUE ) @@ -180,7 +199,7 @@ normalized_average_true_range.plotly <- function( ## construct {plotly}-object ## splice:plotly-assembly:start - name <- sprintf("NATR(%d)", n) + name <- sprintf("NATR(%d)", timePeriod) traces <- list( list(y = ~NATR) ) @@ -206,7 +225,8 @@ normalized_average_true_range.plotly <- function( } ), data = constructed_indicator[, values_to_extract, drop = FALSE], - values_to_extract = values_to_extract + values_to_extract = values_to_extract, + name = get0(x = "name", ifnotfound = NULL) ) state <- .chart_state() @@ -222,11 +242,11 @@ normalized_average_true_range.plotly <- function( normalized_average_true_range.ggplot <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, + title, ## splice:optional-ggplot:start ## splice:optional-ggplot:end - title, ... ) { ## check ggplot2 availability @@ -254,7 +274,7 @@ normalized_average_true_range.ggplot <- function( cols = rebuild_formula( names(constructed_series) ), - n = n, + timePeriod = timePeriod, na.bridge = TRUE ) @@ -275,7 +295,7 @@ normalized_average_true_range.ggplot <- function( setdiff(colnames(constructed_indicator), "idx"), function(col) list(y = col) ) - name <- sprintf("NATR(%d)", n) + name <- sprintf("NATR(%d)", timePeriod) ## splice:ggplot-assembly:end ggplot_object <- add_last_value_gg( diff --git a/R/ta_OBV.R b/R/ta_OBV.R index 829fb3365..a821dc4f2 100644 --- a/R/ta_OBV.R +++ b/R/ta_OBV.R @@ -1,17 +1,18 @@ #' @export -#' @family Volume Indicator +#' @family Volume Indicators #' -#' @title On-Balance Volume -#' @templateVar .title On-Balance Volume +#' @title On Balance Volume +#' @templateVar .title On Balance Volume #' @templateVar .author Serkan Korkmaz #' @templateVar .fun on_balance_volume -#' @templateVar .family Volume Indicator -#' @templateVar .formula ~close+volume +#' @templateVar .family Volume Indicators +#' @templateVar .formula ~close + volume #' ## splice:documentation:start ## splice:documentation:end #' #' @template description +#' #' @template returns on_balance_volume <- function( x, @@ -29,6 +30,13 @@ on_balance_volume <- function( #' @aliases on_balance_volume OBV <- on_balance_volume +#' @export +#' @usage NULL +#' @rdname on_balance_volume +#' +#' @aliases on_balance_volume +onBalanceVolume <- on_balance_volume + #' @usage NULL #' @aliases on_balance_volume #' @@ -62,10 +70,8 @@ on_balance_volume.default <- function( ## return as data.frame x <- .Call( C_impl_ta_OBV, - ## splice:call:start constructed_series[[1]], constructed_series[[2]], - ## splice:call:end as.logical(na.bridge) ) @@ -114,6 +120,17 @@ on_balance_volume.matrix <- function( ) } +#' @usage NULL +OBV_lookback <- onBalanceVolume_lookback <- on_balance_volume_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_OBV_lookback + ) +} #' @usage NULL #' @aliases on_balance_volume @@ -188,13 +205,14 @@ on_balance_volume.plotly <- function( ), data = constructed_indicator, title = if (missing(title)) { - "On-Balance Volume" + "On Balance Volume" } else { title } ), data = constructed_indicator[, values_to_extract, drop = FALSE], - values_to_extract = values_to_extract + values_to_extract = values_to_extract, + name = get0(x = "name", ifnotfound = NULL) ) state <- .chart_state() @@ -211,9 +229,9 @@ on_balance_volume.ggplot <- function( x, cols, na.bridge = FALSE, + title, ## splice:optional-ggplot:start ## splice:optional-ggplot:end - title, ... ) { ## check ggplot2 availability @@ -278,7 +296,7 @@ on_balance_volume.ggplot <- function( ), data = constructed_indicator, title = if (missing(title)) { - "On-Balance Volume" + "On Balance Volume" } else { title } diff --git a/R/ta_PLUS_DI.R b/R/ta_PLUS_DI.R index 98563a504..f5ac7c5c4 100644 --- a/R/ta_PLUS_DI.R +++ b/R/ta_PLUS_DI.R @@ -1,22 +1,23 @@ #' @export -#' @family Momentum Indicator +#' @family Momentum Indicators #' #' @title Plus Directional Indicator #' @templateVar .title Plus Directional Indicator #' @templateVar .author Serkan Korkmaz #' @templateVar .fun plus_directional_indicator -#' @templateVar .family Momentum Indicator +#' @templateVar .family Momentum Indicators #' @templateVar .formula ~high + low + close #' ## splice:documentation:start ## splice:documentation:end #' #' @template description +#' #' @template returns plus_directional_indicator <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -30,6 +31,13 @@ plus_directional_indicator <- function( #' @aliases plus_directional_indicator PLUS_DI <- plus_directional_indicator +#' @export +#' @usage NULL +#' @rdname plus_directional_indicator +#' +#' @aliases plus_directional_indicator +plusDirectionalIndicator <- plus_directional_indicator + #' @usage NULL #' @aliases plus_directional_indicator #' @@ -37,7 +45,7 @@ PLUS_DI <- plus_directional_indicator plus_directional_indicator.default <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -64,12 +72,10 @@ plus_directional_indicator.default <- function( ## return as data.frame x <- .Call( C_impl_ta_PLUS_DI, - ## splice:call:start constructed_series[[1]], constructed_series[[2]], constructed_series[[3]], - as.integer(n), - ## splice:call:end + as.integer(timePeriod), as.logical(na.bridge) ) @@ -87,7 +93,7 @@ plus_directional_indicator.default <- function( plus_directional_indicator.data.frame <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -95,7 +101,7 @@ plus_directional_indicator.data.frame <- function( plus_directional_indicator.default( x = x, cols = cols, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge, ... ) @@ -109,19 +115,32 @@ plus_directional_indicator.data.frame <- function( plus_directional_indicator.matrix <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { plus_directional_indicator.default( x = x, cols = cols, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge, ... ) } +#' @usage NULL +PLUS_DI_lookback <- plusDirectionalIndicator_lookback <- plus_directional_indicator_lookback <- function( + x, + cols, + timePeriod = 14, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_PLUS_DI_lookback, + as.integer(timePeriod) + ) +} #' @usage NULL #' @aliases plus_directional_indicator @@ -130,7 +149,7 @@ plus_directional_indicator.matrix <- function( plus_directional_indicator.plotly <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ## splice:optional-plotly:start ## splice:optional-plotly:end @@ -163,7 +182,7 @@ plus_directional_indicator.plotly <- function( cols = rebuild_formula( names(constructed_series) ), - n = n, + timePeriod = timePeriod, na.bridge = TRUE ) @@ -180,7 +199,7 @@ plus_directional_indicator.plotly <- function( ## construct {plotly}-object ## splice:plotly-assembly:start - name <- sprintf("+DI(%d)", n) + name <- sprintf("+DI(%d)", timePeriod) traces <- list( list(y = ~PLUS_DI) @@ -207,7 +226,8 @@ plus_directional_indicator.plotly <- function( } ), data = constructed_indicator[, values_to_extract, drop = FALSE], - values_to_extract = values_to_extract + values_to_extract = values_to_extract, + name = get0(x = "name", ifnotfound = NULL) ) state <- .chart_state() @@ -223,11 +243,11 @@ plus_directional_indicator.plotly <- function( plus_directional_indicator.ggplot <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, + title, ## splice:optional-ggplot:start ## splice:optional-ggplot:end - title, ... ) { ## check ggplot2 availability @@ -255,7 +275,7 @@ plus_directional_indicator.ggplot <- function( cols = rebuild_formula( names(constructed_series) ), - n = n, + timePeriod = timePeriod, na.bridge = TRUE ) @@ -276,7 +296,7 @@ plus_directional_indicator.ggplot <- function( setdiff(colnames(constructed_indicator), "idx"), function(col) list(y = col) ) - name <- sprintf("+DI(%d)", n) + name <- sprintf("+DI(%d)", timePeriod) ## splice:ggplot-assembly:end ggplot_object <- add_last_value_gg( diff --git a/R/ta_PLUS_DM.R b/R/ta_PLUS_DM.R index b24dd5c7e..c3bddf9a9 100644 --- a/R/ta_PLUS_DM.R +++ b/R/ta_PLUS_DM.R @@ -1,22 +1,23 @@ #' @export -#' @family Momentum Indicator +#' @family Momentum Indicators #' #' @title Plus Directional Movement #' @templateVar .title Plus Directional Movement #' @templateVar .author Serkan Korkmaz #' @templateVar .fun plus_directional_movement -#' @templateVar .family Momentum Indicator +#' @templateVar .family Momentum Indicators #' @templateVar .formula ~high + low #' ## splice:documentation:start ## splice:documentation:end #' #' @template description +#' #' @template returns plus_directional_movement <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -30,6 +31,13 @@ plus_directional_movement <- function( #' @aliases plus_directional_movement PLUS_DM <- plus_directional_movement +#' @export +#' @usage NULL +#' @rdname plus_directional_movement +#' +#' @aliases plus_directional_movement +plusDirectionalMovement <- plus_directional_movement + #' @usage NULL #' @aliases plus_directional_movement #' @@ -37,7 +45,7 @@ PLUS_DM <- plus_directional_movement plus_directional_movement.default <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -64,11 +72,9 @@ plus_directional_movement.default <- function( ## return as data.frame x <- .Call( C_impl_ta_PLUS_DM, - ## splice:call:start constructed_series[[1]], constructed_series[[2]], - as.integer(n), - ## splice:call:end + as.integer(timePeriod), as.logical(na.bridge) ) @@ -86,7 +92,7 @@ plus_directional_movement.default <- function( plus_directional_movement.data.frame <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -94,7 +100,7 @@ plus_directional_movement.data.frame <- function( plus_directional_movement.default( x = x, cols = cols, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge, ... ) @@ -108,19 +114,32 @@ plus_directional_movement.data.frame <- function( plus_directional_movement.matrix <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { plus_directional_movement.default( x = x, cols = cols, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge, ... ) } +#' @usage NULL +PLUS_DM_lookback <- plusDirectionalMovement_lookback <- plus_directional_movement_lookback <- function( + x, + cols, + timePeriod = 14, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_PLUS_DM_lookback, + as.integer(timePeriod) + ) +} #' @usage NULL #' @aliases plus_directional_movement @@ -129,7 +148,7 @@ plus_directional_movement.matrix <- function( plus_directional_movement.plotly <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ## splice:optional-plotly:start ## splice:optional-plotly:end @@ -162,7 +181,7 @@ plus_directional_movement.plotly <- function( cols = rebuild_formula( names(constructed_series) ), - n = n, + timePeriod = timePeriod, na.bridge = TRUE ) @@ -179,7 +198,7 @@ plus_directional_movement.plotly <- function( ## construct {plotly}-object ## splice:plotly-assembly:start - name <- sprintf("+DM(%d)", n) + name <- sprintf("+DM(%d)", timePeriod) traces <- list( list(y = ~PLUS_DM) @@ -206,7 +225,8 @@ plus_directional_movement.plotly <- function( } ), data = constructed_indicator[, values_to_extract, drop = FALSE], - values_to_extract = values_to_extract + values_to_extract = values_to_extract, + name = get0(x = "name", ifnotfound = NULL) ) state <- .chart_state() @@ -222,11 +242,11 @@ plus_directional_movement.plotly <- function( plus_directional_movement.ggplot <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, + title, ## splice:optional-ggplot:start ## splice:optional-ggplot:end - title, ... ) { ## check ggplot2 availability @@ -254,7 +274,7 @@ plus_directional_movement.ggplot <- function( cols = rebuild_formula( names(constructed_series) ), - n = n, + timePeriod = timePeriod, na.bridge = TRUE ) @@ -275,7 +295,7 @@ plus_directional_movement.ggplot <- function( setdiff(colnames(constructed_indicator), "idx"), function(col) list(y = col) ) - name <- sprintf("+DM(%d)", n) + name <- sprintf("+DM(%d)", timePeriod) ## splice:ggplot-assembly:end ggplot_object <- add_last_value_gg( diff --git a/R/ta_PPO.R b/R/ta_PPO.R index 0b54a3a7f..765cdf511 100644 --- a/R/ta_PPO.R +++ b/R/ta_PPO.R @@ -1,27 +1,27 @@ #' @export -#' @family Momentum Indicator +#' @family Momentum Indicators #' #' @title Percentage Price Oscillator #' @templateVar .title Percentage Price Oscillator #' @templateVar .author Serkan Korkmaz #' @templateVar .fun percentage_price_oscillator -#' @templateVar .family Momentum Indicator +#' @templateVar .family Momentum Indicators #' @templateVar .formula ~close #' ## splice:documentation:start -#' @param fast ([integer]). Period for the fast Moving Average (MA). -#' @param slow ([integer]). Period for the slow Moving Average (MA). -#' @param ma ([list]). The type of Moving Average (MA) used for the `fast` and `slow` MA. [SMA] by default. ## splice:documentation:end #' #' @template description +#' @param fastPeriod ([integer]). Number of period for the fast MA. Defaults to `12`. +#' @param slowPeriod ([integer]). Number of period for the slow MA. Defaults to `26`. +#' @param maType ([integer]). Type of Moving Average. Defaults to `0` ([SMA]). Can also be passed as talib::SMA. #' @template returns percentage_price_oscillator <- function( x, cols, - fast = 12, - slow = 26, - ma = SMA(n = 9), + fastPeriod = 12, + slowPeriod = 26, + maType = 0, na.bridge = FALSE, ... ) { @@ -35,6 +35,13 @@ percentage_price_oscillator <- function( #' @aliases percentage_price_oscillator PPO <- percentage_price_oscillator +#' @export +#' @usage NULL +#' @rdname percentage_price_oscillator +#' +#' @aliases percentage_price_oscillator +percentagePriceOscillator <- percentage_price_oscillator + #' @usage NULL #' @aliases percentage_price_oscillator #' @@ -42,9 +49,9 @@ PPO <- percentage_price_oscillator percentage_price_oscillator.default <- function( x, cols, - fast = 12, - slow = 26, - ma = SMA(n = 9), + fastPeriod = 12, + slowPeriod = 26, + maType = 0, na.bridge = FALSE, ... ) { @@ -71,12 +78,10 @@ percentage_price_oscillator.default <- function( ## return as data.frame x <- .Call( C_impl_ta_PPO, - ## splice:call:start constructed_series[[1]], - as.integer(fast), - as.integer(slow), - ma$maType, - ## splice:call:end + as.integer(fastPeriod), + as.integer(slowPeriod), + as.maType(maType), as.logical(na.bridge) ) @@ -94,9 +99,9 @@ percentage_price_oscillator.default <- function( percentage_price_oscillator.data.frame <- function( x, cols, - fast = 12, - slow = 26, - ma = SMA(n = 9), + fastPeriod = 12, + slowPeriod = 26, + maType = 0, na.bridge = FALSE, ... ) { @@ -104,9 +109,9 @@ percentage_price_oscillator.data.frame <- function( percentage_price_oscillator.default( x = x, cols = cols, - fast = fast, - slow = slow, - ma = ma, + fastPeriod = fastPeriod, + slowPeriod = slowPeriod, + maType = maType, na.bridge = na.bridge, ... ) @@ -120,23 +125,40 @@ percentage_price_oscillator.data.frame <- function( percentage_price_oscillator.matrix <- function( x, cols, - fast = 12, - slow = 26, - ma = SMA(n = 9), + fastPeriod = 12, + slowPeriod = 26, + maType = 0, na.bridge = FALSE, ... ) { percentage_price_oscillator.default( x = x, cols = cols, - fast = fast, - slow = slow, - ma = ma, + fastPeriod = fastPeriod, + slowPeriod = slowPeriod, + maType = maType, na.bridge = na.bridge, ... ) } +#' @usage NULL +PPO_lookback <- percentagePriceOscillator_lookback <- percentage_price_oscillator_lookback <- function( + x, + cols, + fastPeriod = 12, + slowPeriod = 26, + maType = 0, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_PPO_lookback, + as.integer(fastPeriod), + as.integer(slowPeriod), + as.maType(maType) + ) +} #' @usage NULL #' @aliases percentage_price_oscillator @@ -145,9 +167,9 @@ percentage_price_oscillator.matrix <- function( percentage_price_oscillator.numeric <- function( x, cols, - fast = 12, - slow = 26, - ma = SMA(n = 9), + fastPeriod = 12, + slowPeriod = 26, + maType = 0, na.bridge = FALSE, ... ) { @@ -163,31 +185,20 @@ percentage_price_oscillator.numeric <- function( ## to 'C' x <- .Call( C_impl_ta_PPO, - ## splice:numeric:start as.double(x), - as.integer(fast), - as.integer(slow), - ma$maType, - ## splice:numeric:end + as.integer(fastPeriod), + as.integer(slowPeriod), + as.maType(maType), 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 #' @aliases percentage_price_oscillator #' @@ -195,9 +206,9 @@ percentage_price_oscillator.numeric <- function( percentage_price_oscillator.plotly <- function( x, cols, - fast = 12, - slow = 26, - ma = SMA(n = 9), + fastPeriod = 12, + slowPeriod = 26, + maType = 0, na.bridge = FALSE, ## splice:optional-plotly:start ## splice:optional-plotly:end @@ -230,9 +241,9 @@ percentage_price_oscillator.plotly <- function( cols = rebuild_formula( names(constructed_series) ), - fast = fast, - slow = slow, - ma = ma, + fastPeriod = fastPeriod, + slowPeriod = slowPeriod, + maType = maType, na.bridge = TRUE ) @@ -251,8 +262,8 @@ percentage_price_oscillator.plotly <- function( ## splice:plotly-assembly:start name <- sprintf( "PPO(%d, %d)", - fast, - slow + fastPeriod, + slowPeriod ) traces <- list( @@ -280,7 +291,8 @@ percentage_price_oscillator.plotly <- function( } ), data = constructed_indicator[, values_to_extract, drop = FALSE], - values_to_extract = values_to_extract + values_to_extract = values_to_extract, + name = get0(x = "name", ifnotfound = NULL) ) state <- .chart_state() @@ -296,13 +308,13 @@ percentage_price_oscillator.plotly <- function( percentage_price_oscillator.ggplot <- function( x, cols, - fast = 12, - slow = 26, - ma = SMA(n = 9), + fastPeriod = 12, + slowPeriod = 26, + maType = 0, na.bridge = FALSE, + title, ## splice:optional-ggplot:start ## splice:optional-ggplot:end - title, ... ) { ## check ggplot2 availability @@ -330,9 +342,9 @@ percentage_price_oscillator.ggplot <- function( cols = rebuild_formula( names(constructed_series) ), - fast = fast, - slow = slow, - ma = ma, + fastPeriod = fastPeriod, + slowPeriod = slowPeriod, + maType = maType, na.bridge = TRUE ) @@ -353,7 +365,7 @@ percentage_price_oscillator.ggplot <- function( ggplot_line(0), list(y = "PPO") ) - name <- sprintf("PPO(%d, %d)", fast, slow) + name <- sprintf("PPO(%d, %d)", fastPeriod, slowPeriod) ## splice:ggplot-assembly:end ggplot_object <- add_last_value_gg( diff --git a/R/ta_ROCR.R b/R/ta_ROCR.R index a387f2573..3fc951278 100644 --- a/R/ta_ROCR.R +++ b/R/ta_ROCR.R @@ -1,22 +1,23 @@ #' @export -#' @family Momentum Indicator +#' @family Momentum Indicators #' -#' @title Ratio of Change -#' @templateVar .title Ratio of Change +#' @title Rate of change ratio: (price/prevPrice) +#' @templateVar .title Rate of change ratio: (price/prevPrice) #' @templateVar .author Serkan Korkmaz #' @templateVar .fun ratio_of_change -#' @templateVar .family Momentum Indicator +#' @templateVar .family Momentum Indicators #' @templateVar .formula ~close #' ## splice:documentation:start ## splice:documentation:end #' #' @template description +#' #' @template returns ratio_of_change <- function( x, cols, - n = 10, + timePeriod = 10, na.bridge = FALSE, ... ) { @@ -30,6 +31,13 @@ ratio_of_change <- function( #' @aliases ratio_of_change ROCR <- ratio_of_change +#' @export +#' @usage NULL +#' @rdname ratio_of_change +#' +#' @aliases ratio_of_change +ratioOfChange <- ratio_of_change + #' @usage NULL #' @aliases ratio_of_change #' @@ -37,7 +45,7 @@ ROCR <- ratio_of_change ratio_of_change.default <- function( x, cols, - n = 10, + timePeriod = 10, na.bridge = FALSE, ... ) { @@ -64,10 +72,8 @@ ratio_of_change.default <- function( ## return as data.frame x <- .Call( C_impl_ta_ROCR, - ## splice:call:start constructed_series[[1]], - as.integer(n), - ## splice:call:end + as.integer(timePeriod), as.logical(na.bridge) ) @@ -85,7 +91,7 @@ ratio_of_change.default <- function( ratio_of_change.data.frame <- function( x, cols, - n = 10, + timePeriod = 10, na.bridge = FALSE, ... ) { @@ -93,7 +99,7 @@ ratio_of_change.data.frame <- function( ratio_of_change.default( x = x, cols = cols, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge, ... ) @@ -107,19 +113,32 @@ ratio_of_change.data.frame <- function( ratio_of_change.matrix <- function( x, cols, - n = 10, + timePeriod = 10, na.bridge = FALSE, ... ) { ratio_of_change.default( x = x, cols = cols, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge, ... ) } +#' @usage NULL +ROCR_lookback <- ratioOfChange_lookback <- ratio_of_change_lookback <- function( + x, + cols, + timePeriod = 10, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_ROCR_lookback, + as.integer(timePeriod) + ) +} #' @usage NULL #' @aliases ratio_of_change @@ -128,7 +147,7 @@ ratio_of_change.matrix <- function( ratio_of_change.numeric <- function( x, cols, - n = 10, + timePeriod = 10, na.bridge = FALSE, ... ) { @@ -144,29 +163,18 @@ ratio_of_change.numeric <- function( ## to 'C' x <- .Call( C_impl_ta_ROCR, - ## splice:numeric:start as.double(x), - as.integer(n), - ## splice:numeric:end + as.integer(timePeriod), 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 #' @aliases ratio_of_change #' @@ -174,7 +182,7 @@ ratio_of_change.numeric <- function( ratio_of_change.plotly <- function( x, cols, - n = 10, + timePeriod = 10, na.bridge = FALSE, ## splice:optional-plotly:start ## splice:optional-plotly:end @@ -207,7 +215,7 @@ ratio_of_change.plotly <- function( cols = rebuild_formula( names(constructed_series) ), - n = n, + timePeriod = timePeriod, na.bridge = TRUE ) @@ -224,16 +232,18 @@ ratio_of_change.plotly <- function( ## construct {plotly}-object ## splice:plotly-assembly:start - name <- sprintf( - "ROCR(%d)", - n - ) - - traces <- list( - list( - y = ~ROCR - ) + traces <- lapply( + setdiff(colnames(constructed_indicator), "idx"), + function(col) { + list( + y = stats::as.formula( + paste0("~", col) + ), + name = col + ) + } ) + name <- "ROCR" ## splice:plotly-assembly:end plotly_object <- add_last_value_ly( @@ -250,13 +260,14 @@ ratio_of_change.plotly <- function( ), data = constructed_indicator, title = if (missing(title)) { - "Ratio of Change" + "Rate of change ratio: (price/prevPrice)" } else { title } ), data = constructed_indicator[, values_to_extract, drop = FALSE], - values_to_extract = values_to_extract + values_to_extract = values_to_extract, + name = get0(x = "name", ifnotfound = NULL) ) state <- .chart_state() @@ -272,11 +283,11 @@ ratio_of_change.plotly <- function( ratio_of_change.ggplot <- function( x, cols, - n = 10, + timePeriod = 10, na.bridge = FALSE, + title, ## splice:optional-ggplot:start ## splice:optional-ggplot:end - title, ... ) { ## check ggplot2 availability @@ -304,7 +315,7 @@ ratio_of_change.ggplot <- function( cols = rebuild_formula( names(constructed_series) ), - n = n, + timePeriod = timePeriod, na.bridge = TRUE ) @@ -325,7 +336,7 @@ ratio_of_change.ggplot <- function( setdiff(colnames(constructed_indicator), "idx"), function(col) list(y = col) ) - name <- sprintf("ROCR(%d)", n) + name <- "ROCR" ## splice:ggplot-assembly:end ggplot_object <- add_last_value_gg( @@ -342,7 +353,7 @@ ratio_of_change.ggplot <- function( ), data = constructed_indicator, title = if (missing(title)) { - "Ratio of Change" + "Rate of change ratio: (price/prevPrice)" } else { title } diff --git a/R/ta_RSI.R b/R/ta_RSI.R index 557646de3..92a06e855 100644 --- a/R/ta_RSI.R +++ b/R/ta_RSI.R @@ -1,22 +1,23 @@ #' @export -#' @family Momentum Indicator +#' @family Momentum Indicators #' #' @title Relative Strength Index #' @templateVar .title Relative Strength Index #' @templateVar .author Serkan Korkmaz #' @templateVar .fun relative_strength_index -#' @templateVar .family Momentum Indicator +#' @templateVar .family Momentum Indicators #' @templateVar .formula ~close #' ## splice:documentation:start ## splice:documentation:end #' #' @template description +#' #' @template returns relative_strength_index <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -30,6 +31,13 @@ relative_strength_index <- function( #' @aliases relative_strength_index RSI <- relative_strength_index +#' @export +#' @usage NULL +#' @rdname relative_strength_index +#' +#' @aliases relative_strength_index +relativeStrengthIndex <- relative_strength_index + #' @usage NULL #' @aliases relative_strength_index #' @@ -37,7 +45,7 @@ RSI <- relative_strength_index relative_strength_index.default <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -64,10 +72,8 @@ relative_strength_index.default <- function( ## return as data.frame x <- .Call( C_impl_ta_RSI, - ## splice:call:start constructed_series[[1]], - as.integer(n), - ## splice:call:end + as.integer(timePeriod), as.logical(na.bridge) ) @@ -85,7 +91,7 @@ relative_strength_index.default <- function( relative_strength_index.data.frame <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -93,7 +99,7 @@ relative_strength_index.data.frame <- function( relative_strength_index.default( x = x, cols = cols, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge, ... ) @@ -107,19 +113,32 @@ relative_strength_index.data.frame <- function( relative_strength_index.matrix <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { relative_strength_index.default( x = x, cols = cols, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge, ... ) } +#' @usage NULL +RSI_lookback <- relativeStrengthIndex_lookback <- relative_strength_index_lookback <- function( + x, + cols, + timePeriod = 14, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_RSI_lookback, + as.integer(timePeriod) + ) +} #' @usage NULL #' @aliases relative_strength_index @@ -128,7 +147,7 @@ relative_strength_index.matrix <- function( relative_strength_index.numeric <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -144,29 +163,18 @@ relative_strength_index.numeric <- function( ## to 'C' x <- .Call( C_impl_ta_RSI, - ## splice:numeric:start as.double(x), - as.integer(n), - ## splice:numeric:end + as.integer(timePeriod), 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 #' @aliases relative_strength_index #' @@ -174,7 +182,7 @@ relative_strength_index.numeric <- function( relative_strength_index.plotly <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ## splice:optional-plotly:start lower_bound = 20, @@ -209,7 +217,7 @@ relative_strength_index.plotly <- function( cols = rebuild_formula( names(constructed_series) ), - n = n, + timePeriod = timePeriod, na.bridge = TRUE ) @@ -228,7 +236,7 @@ relative_strength_index.plotly <- function( ## splice:plotly-assembly:start name <- sprintf( "RSI(%d)", - n + timePeriod ) decorators <- list( @@ -262,7 +270,8 @@ relative_strength_index.plotly <- function( } ), data = constructed_indicator[, values_to_extract, drop = FALSE], - values_to_extract = values_to_extract + values_to_extract = values_to_extract, + name = get0(x = "name", ifnotfound = NULL) ) state <- .chart_state() @@ -278,11 +287,11 @@ relative_strength_index.plotly <- function( relative_strength_index.ggplot <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, + title, ## splice:optional-ggplot:start ## splice:optional-ggplot:end - title, ... ) { ## check ggplot2 availability @@ -310,7 +319,7 @@ relative_strength_index.ggplot <- function( cols = rebuild_formula( names(constructed_series) ), - n = n, + timePeriod = timePeriod, na.bridge = TRUE ) @@ -335,7 +344,7 @@ relative_strength_index.ggplot <- function( ggplot_line(80), list(y = "RSI") ) - name <- sprintf("RSI(%d)", n) + name <- sprintf("RSI(%d)", timePeriod) ## splice:ggplot-assembly:end ggplot_object <- add_last_value_gg( diff --git a/R/ta_SAR.R b/R/ta_SAR.R index 948915275..7c39d7922 100644 --- a/R/ta_SAR.R +++ b/R/ta_SAR.R @@ -1,25 +1,25 @@ #' @export -#' @family Overlap Study +#' @family Overlap Studies #' -#' @title Parabolic Stop and Reverse (SAR) -#' @templateVar .title Parabolic Stop and Reverse (SAR) +#' @title Parabolic SAR +#' @templateVar .title Parabolic SAR #' @templateVar .author Serkan Korkmaz #' @templateVar .fun parabolic_stop_and_reverse -#' @templateVar .family Overlap Study -#' @templateVar .formula ~high+low +#' @templateVar .family Overlap Studies +#' @templateVar .formula ~high + low #' ## splice:documentation:start -#' @param acceleration ([double]). Acceleration factor used up to the maximum value. -#' @param maximum ([double]). Acceleration factor maximum value. ## splice:documentation:end #' #' @template description +#' @param accelerationFactor ([double]). Acceleration Factor used up to the Maximum value. Defaults to `0.02`. +#' @param afMaximum ([double]). Acceleration Factor Maximum value. Defaults to `0.2`. #' @template returns parabolic_stop_and_reverse <- function( x, cols, - acceleration = 0.02, - maximum = 0.2, + accelerationFactor = 0.02, + afMaximum = 0.2, na.bridge = FALSE, ... ) { @@ -33,6 +33,13 @@ parabolic_stop_and_reverse <- function( #' @aliases parabolic_stop_and_reverse SAR <- parabolic_stop_and_reverse +#' @export +#' @usage NULL +#' @rdname parabolic_stop_and_reverse +#' +#' @aliases parabolic_stop_and_reverse +parabolicStopAndReverse <- parabolic_stop_and_reverse + #' @usage NULL #' @aliases parabolic_stop_and_reverse #' @@ -40,8 +47,8 @@ SAR <- parabolic_stop_and_reverse parabolic_stop_and_reverse.default <- function( x, cols, - acceleration = 0.02, - maximum = 0.2, + accelerationFactor = 0.02, + afMaximum = 0.2, na.bridge = FALSE, ... ) { @@ -68,12 +75,10 @@ parabolic_stop_and_reverse.default <- function( ## return as data.frame x <- .Call( C_impl_ta_SAR, - ## splice:call:start constructed_series[[1]], constructed_series[[2]], - as.double(acceleration), - as.double(maximum), - ## splice:call:end + as.double(accelerationFactor), + as.double(afMaximum), as.logical(na.bridge) ) @@ -91,8 +96,8 @@ parabolic_stop_and_reverse.default <- function( parabolic_stop_and_reverse.data.frame <- function( x, cols, - acceleration = 0.02, - maximum = 0.2, + accelerationFactor = 0.02, + afMaximum = 0.2, na.bridge = FALSE, ... ) { @@ -100,8 +105,8 @@ parabolic_stop_and_reverse.data.frame <- function( parabolic_stop_and_reverse.default( x = x, cols = cols, - acceleration = acceleration, - maximum = maximum, + accelerationFactor = accelerationFactor, + afMaximum = afMaximum, na.bridge = na.bridge, ... ) @@ -115,21 +120,36 @@ parabolic_stop_and_reverse.data.frame <- function( parabolic_stop_and_reverse.matrix <- function( x, cols, - acceleration = 0.02, - maximum = 0.2, + accelerationFactor = 0.02, + afMaximum = 0.2, na.bridge = FALSE, ... ) { parabolic_stop_and_reverse.default( x = x, cols = cols, - acceleration = acceleration, - maximum = maximum, + accelerationFactor = accelerationFactor, + afMaximum = afMaximum, na.bridge = na.bridge, ... ) } +#' @usage NULL +SAR_lookback <- parabolicStopAndReverse_lookback <- parabolic_stop_and_reverse_lookback <- function( + x, + cols, + accelerationFactor = 0.02, + afMaximum = 0.2, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_SAR_lookback, + as.double(accelerationFactor), + as.double(afMaximum) + ) +} #' @usage NULL #' @aliases parabolic_stop_and_reverse @@ -138,8 +158,8 @@ parabolic_stop_and_reverse.matrix <- function( parabolic_stop_and_reverse.plotly <- function( x, cols, - acceleration = 0.02, - maximum = 0.2, + accelerationFactor = 0.02, + afMaximum = 0.2, na.bridge = FALSE, ## splice:optional-plotly:start ## splice:optional-plotly:end @@ -171,8 +191,8 @@ parabolic_stop_and_reverse.plotly <- function( cols = rebuild_formula( names(constructed_series) ), - acceleration = acceleration, - maximum = maximum, + accelerationFactor = accelerationFactor, + afMaximum = afMaximum, na.bridge = TRUE ) @@ -245,8 +265,8 @@ parabolic_stop_and_reverse.plotly <- function( parabolic_stop_and_reverse.ggplot <- function( x, cols, - acceleration = 0.02, - maximum = 0.2, + accelerationFactor = 0.02, + afMaximum = 0.2, na.bridge = FALSE, ## splice:optional-ggplot:start ## splice:optional-ggplot:end @@ -277,8 +297,8 @@ parabolic_stop_and_reverse.ggplot <- function( cols = rebuild_formula( names(constructed_series) ), - acceleration = acceleration, - maximum = maximum, + accelerationFactor = accelerationFactor, + afMaximum = afMaximum, na.bridge = TRUE ) diff --git a/R/ta_SAREXT.R b/R/ta_SAREXT.R index 36b24f643..195a39fa1 100644 --- a/R/ta_SAREXT.R +++ b/R/ta_SAREXT.R @@ -1,37 +1,37 @@ #' @export -#' @family Overlap Study +#' @family Overlap Studies #' -#' @title Parabolic Stop and Reverse (SAR) - Extended -#' @templateVar .title Parabolic Stop and Reverse (SAR) - Extended +#' @title Parabolic SAR - Extended +#' @templateVar .title Parabolic SAR - Extended #' @templateVar .author Serkan Korkmaz #' @templateVar .fun extended_parabolic_stop_and_reverse -#' @templateVar .family Overlap Study -#' @templateVar .formula ~high+low +#' @templateVar .family Overlap Studies +#' @templateVar .formula ~high + low #' ## splice:documentation:start -#' @param init ([double]). Start value and direction. 0 for Auto, >0 for Long, <0 for Short. -#' @param offset ([double]). Offset added/removed to initial stop on short/long reversal. -#' @param init_long ([double]). Acceleration factor initial value for the Long direction. -#' @param long ([double]). Acceleration factor for the Long direction. -#' @param max_long ([double]). Acceleration factor maximum value for the Long direction. -#' @param init_short ([double]). Acceleration factor initial value for the Short direction. -#' @param short ([double]). Acceleration factor for the Short direction. -#' @param max_short ([double]). Acceleration factor maximum value for the Short direction. ## splice:documentation:end #' #' @template description +#' @param startValue ([double]). Start value and direction. 0 for Auto, >0 for Long, <0 for Short. Defaults to `0`. +#' @param offsetOnReverse ([double]). Percent offset added/removed to initial stop on short/long reversal. Defaults to `0`. +#' @param afInitLong ([double]). Acceleration Factor initial value for the Long direction. Defaults to `0.02`. +#' @param afLong ([double]). Acceleration Factor for the Long direction. Defaults to `0.02`. +#' @param afMaxLong ([double]). Acceleration Factor maximum value for the Long direction. Defaults to `0.2`. +#' @param afInitShort ([double]). Acceleration Factor initial value for the Short direction. Defaults to `0.02`. +#' @param afShort ([double]). Acceleration Factor for the Short direction. Defaults to `0.02`. +#' @param afMaxShort ([double]). Acceleration Factor maximum value for the Short direction. Defaults to `0.2`. #' @template returns extended_parabolic_stop_and_reverse <- 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, + startValue = 0, + offsetOnReverse = 0, + afInitLong = 0.02, + afLong = 0.02, + afMaxLong = 0.2, + afInitShort = 0.02, + afShort = 0.02, + afMaxShort = 0.2, na.bridge = FALSE, ... ) { @@ -45,6 +45,13 @@ extended_parabolic_stop_and_reverse <- function( #' @aliases extended_parabolic_stop_and_reverse SAREXT <- extended_parabolic_stop_and_reverse +#' @export +#' @usage NULL +#' @rdname extended_parabolic_stop_and_reverse +#' +#' @aliases extended_parabolic_stop_and_reverse +extendedParabolicStopAndReverse <- extended_parabolic_stop_and_reverse + #' @usage NULL #' @aliases extended_parabolic_stop_and_reverse #' @@ -52,14 +59,14 @@ SAREXT <- extended_parabolic_stop_and_reverse extended_parabolic_stop_and_reverse.default <- 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, + startValue = 0, + offsetOnReverse = 0, + afInitLong = 0.02, + afLong = 0.02, + afMaxLong = 0.2, + afInitShort = 0.02, + afShort = 0.02, + afMaxShort = 0.2, na.bridge = FALSE, ... ) { @@ -86,18 +93,16 @@ extended_parabolic_stop_and_reverse.default <- function( ## return as data.frame x <- .Call( C_impl_ta_SAREXT, - ## splice:call:start constructed_series[[1]], constructed_series[[2]], - init, - offset, - init_long, - long, - max_long, - init_short, - short, - max_short, - ## splice:call:end + as.double(startValue), + as.double(offsetOnReverse), + as.double(afInitLong), + as.double(afLong), + as.double(afMaxLong), + as.double(afInitShort), + as.double(afShort), + as.double(afMaxShort), as.logical(na.bridge) ) @@ -115,14 +120,14 @@ extended_parabolic_stop_and_reverse.default <- function( extended_parabolic_stop_and_reverse.data.frame <- 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, + startValue = 0, + offsetOnReverse = 0, + afInitLong = 0.02, + afLong = 0.02, + afMaxLong = 0.2, + afInitShort = 0.02, + afShort = 0.02, + afMaxShort = 0.2, na.bridge = FALSE, ... ) { @@ -130,14 +135,14 @@ extended_parabolic_stop_and_reverse.data.frame <- function( extended_parabolic_stop_and_reverse.default( x = x, cols = cols, - init = init, - offset = offset, - init_long = init_long, - long = long, - max_long = max_long, - init_short = init_short, - short = short, - max_short = max_short, + startValue = startValue, + offsetOnReverse = offsetOnReverse, + afInitLong = afInitLong, + afLong = afLong, + afMaxLong = afMaxLong, + afInitShort = afInitShort, + afShort = afShort, + afMaxShort = afMaxShort, na.bridge = na.bridge, ... ) @@ -151,33 +156,60 @@ extended_parabolic_stop_and_reverse.data.frame <- function( extended_parabolic_stop_and_reverse.matrix <- 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, + startValue = 0, + offsetOnReverse = 0, + afInitLong = 0.02, + afLong = 0.02, + afMaxLong = 0.2, + afInitShort = 0.02, + afShort = 0.02, + afMaxShort = 0.2, na.bridge = FALSE, ... ) { extended_parabolic_stop_and_reverse.default( x = x, cols = cols, - init = init, - offset = offset, - init_long = init_long, - long = long, - max_long = max_long, - init_short = init_short, - short = short, - max_short = max_short, + startValue = startValue, + offsetOnReverse = offsetOnReverse, + afInitLong = afInitLong, + afLong = afLong, + afMaxLong = afMaxLong, + afInitShort = afInitShort, + afShort = afShort, + afMaxShort = afMaxShort, na.bridge = na.bridge, ... ) } +#' @usage NULL +SAREXT_lookback <- extendedParabolicStopAndReverse_lookback <- extended_parabolic_stop_and_reverse_lookback <- function( + x, + cols, + startValue = 0, + offsetOnReverse = 0, + afInitLong = 0.02, + afLong = 0.02, + afMaxLong = 0.2, + afInitShort = 0.02, + afShort = 0.02, + afMaxShort = 0.2, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_SAREXT_lookback, + as.double(startValue), + as.double(offsetOnReverse), + as.double(afInitLong), + as.double(afLong), + as.double(afMaxLong), + as.double(afInitShort), + as.double(afShort), + as.double(afMaxShort) + ) +} #' @usage NULL #' @aliases extended_parabolic_stop_and_reverse @@ -186,14 +218,14 @@ extended_parabolic_stop_and_reverse.matrix <- function( extended_parabolic_stop_and_reverse.plotly <- 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, + startValue = 0, + offsetOnReverse = 0, + afInitLong = 0.02, + afLong = 0.02, + afMaxLong = 0.2, + afInitShort = 0.02, + afShort = 0.02, + afMaxShort = 0.2, na.bridge = FALSE, ## splice:optional-plotly:start ## splice:optional-plotly:end @@ -225,14 +257,14 @@ extended_parabolic_stop_and_reverse.plotly <- function( cols = rebuild_formula( names(constructed_series) ), - init = init, - offset = offset, - init_long = init_long, - long = long, - max_long = max_long, - init_short = init_short, - short = short, - max_short = max_short, + startValue = startValue, + offsetOnReverse = offsetOnReverse, + afInitLong = afInitLong, + afLong = afLong, + afMaxLong = afMaxLong, + afInitShort = afInitShort, + afShort = afShort, + afMaxShort = afMaxShort, na.bridge = TRUE ) @@ -305,14 +337,14 @@ extended_parabolic_stop_and_reverse.plotly <- function( extended_parabolic_stop_and_reverse.ggplot <- 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, + startValue = 0, + offsetOnReverse = 0, + afInitLong = 0.02, + afLong = 0.02, + afMaxLong = 0.2, + afInitShort = 0.02, + afShort = 0.02, + afMaxShort = 0.2, na.bridge = FALSE, ## splice:optional-ggplot:start ## splice:optional-ggplot:end @@ -343,14 +375,14 @@ extended_parabolic_stop_and_reverse.ggplot <- function( cols = rebuild_formula( names(constructed_series) ), - init = init, - offset = offset, - init_long = init_long, - long = long, - max_long = max_long, - init_short = init_short, - short = short, - max_short = max_short, + startValue = startValue, + offsetOnReverse = offsetOnReverse, + afInitLong = afInitLong, + afLong = afLong, + afMaxLong = afMaxLong, + afInitShort = afInitShort, + afShort = afShort, + afMaxShort = afMaxShort, na.bridge = TRUE ) diff --git a/R/ta_SMA.R b/R/ta_SMA.R index da7f19954..a62d2bc9e 100644 --- a/R/ta_SMA.R +++ b/R/ta_SMA.R @@ -1,11 +1,11 @@ #' @export -#' @family Overlap Study +#' @family Overlap Studies #' #' @title Simple Moving Average #' @templateVar .title Simple Moving Average #' @templateVar .author Serkan Korkmaz #' @templateVar .fun simple_moving_average -#' @templateVar .family Overlap Study +#' @templateVar .family Overlap Studies #' @templateVar .formula ~close #' ## splice:documentation:start @@ -18,11 +18,12 @@ #' indicators that supports various Moving Average specifications. #' #' @template description +#' #' @template returns simple_moving_average <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, ... ) { @@ -33,13 +34,19 @@ simple_moving_average <- function( ## from call x <- structure( list( - n = if (missing(n)) 30L else as.integer(n), + timePeriod = if (missing(timePeriod)) { + 30L + } else { + as.integer(timePeriod) + }, maType = 0L - ) + ), + class = "maType" ) return(x) } + UseMethod("simple_moving_average") } @@ -50,6 +57,13 @@ simple_moving_average <- function( #' @aliases simple_moving_average SMA <- simple_moving_average +#' @export +#' @usage NULL +#' @rdname simple_moving_average +#' +#' @aliases simple_moving_average +simpleMovingAverage <- simple_moving_average + #' @usage NULL #' @aliases simple_moving_average #' @@ -57,7 +71,7 @@ SMA <- simple_moving_average simple_moving_average.default <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, ... ) { @@ -84,8 +98,8 @@ simple_moving_average.default <- function( ## return as data.frame x <- .Call( C_impl_ta_SMA, - as.double(constructed_series[[1]]), - as.integer(n), + constructed_series[[1]], + as.integer(timePeriod), as.logical(na.bridge) ) @@ -103,12 +117,18 @@ simple_moving_average.default <- function( simple_moving_average.data.frame <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, ... ) { map_dfr( - NextMethod() + simple_moving_average.default( + x = x, + cols = cols, + timePeriod = timePeriod, + na.bridge = na.bridge, + ... + ) ) } @@ -119,17 +139,14 @@ simple_moving_average.data.frame <- function( simple_moving_average.matrix <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, ... ) { - ## pass directly to - ## simple_moving_average.default to avoid - ## shenanigans with NextMethod() simple_moving_average.default( x = x, cols = cols, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge, ... ) @@ -142,7 +159,7 @@ simple_moving_average.matrix <- function( simple_moving_average.numeric <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, ... ) { @@ -159,25 +176,32 @@ simple_moving_average.numeric <- function( x <- .Call( C_impl_ta_SMA, as.double(x), - as.integer(n), + as.integer(timePeriod), 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 <- simpleMovingAverage_lookback <- simple_moving_average_lookback <- function( + x, + cols, + timePeriod = 30, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_SMA_lookback, + as.integer(timePeriod) + ) +} + + #' @usage NULL #' @aliases simple_moving_average #' @@ -185,7 +209,7 @@ simple_moving_average.numeric <- function( simple_moving_average.plotly <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, ... ) { @@ -215,7 +239,8 @@ simple_moving_average.plotly <- function( cols = rebuild_formula( names(constructed_series) ), - n = n + timePeriod = timePeriod, + na.bridge = TRUE ) ## add conditional idx @@ -238,15 +263,15 @@ simple_moving_average.plotly <- function( ) ) ), - name = label("SMA", n), - decorators = list() + name = label("SMA", timePeriod), + decorators = list(), + data = constructed_indicator ) state[["main"]] <- plotly_object plotly_object } - #' @usage NULL #' @aliases simple_moving_average #' @@ -254,7 +279,7 @@ simple_moving_average.plotly <- function( simple_moving_average.ggplot <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, ... ) { @@ -283,7 +308,8 @@ simple_moving_average.ggplot <- function( cols = rebuild_formula( names(constructed_series) ), - n = n + timePeriod = timePeriod, + na.bridge = TRUE ) ## add conditional idx @@ -300,7 +326,7 @@ simple_moving_average.ggplot <- function( y = "SMA" ) ), - name = label("SMA", n), + name = label("SMA", timePeriod), decorators = list(), data = constructed_indicator ) diff --git a/R/ta_STDDEV.R b/R/ta_STDDEV.R index 4bc21d5ad..611bed189 100644 --- a/R/ta_STDDEV.R +++ b/R/ta_STDDEV.R @@ -1,22 +1,23 @@ #' @export -#' @family Rolling Statistic +#' @family Rolling Statistics #' -#' @title Rolling Standard Deviation -#' @templateVar .title Rolling Standard Deviation +#' @title Standard Deviation +#' @templateVar .title Standard Deviation #' @templateVar .author Serkan Korkmaz #' @templateVar .fun rolling_standard_deviation #' ## splice:documentation:start -#' @param k ([double]). Multiplier for the standard deviation. ## splice:documentation:end #' #' @template rolling_description +#' @param deviations ([double]). Number of deviations. Defaults to `1`. #' @template rolling_returns rolling_standard_deviation <- function( x, - n = 5, - k = 1, - na.bridge = FALSE + timePeriod = 5, + deviations = 1, + na.bridge = FALSE, + ... ) { UseMethod("rolling_standard_deviation") } @@ -28,15 +29,23 @@ rolling_standard_deviation <- function( #' @aliases rolling_standard_deviation STDDEV <- rolling_standard_deviation +#' @export +#' @usage NULL +#' @rdname rolling_standard_deviation +#' +#' @aliases rolling_standard_deviation +rollingStandardDeviation <- rolling_standard_deviation + #' @usage NULL #' @aliases rolling_standard_deviation #' #' @export rolling_standard_deviation.default <- function( x, - n = 5, - k = 1, - na.bridge = FALSE + timePeriod = 5, + deviations = 1, + na.bridge = FALSE, + ... ) { ## calculate indicator and ## return as data.frame @@ -44,14 +53,19 @@ rolling_standard_deviation.default <- function( C_impl_ta_STDDEV, ## splice:call:start as.double(x), - as.integer(n), - as.double(k), + as.integer(timePeriod), + as.double(deviations), ## splice:call:end as.logical(na.bridge) ) + ## strip dimensions + ## while preserving + ## attributes + dim(x) <- NULL + ## return indicator - as.double(x) + x } #' @usage NULL @@ -60,19 +74,40 @@ rolling_standard_deviation.default <- function( #' @export rolling_standard_deviation.numeric <- function( x, - n = 5, - k = 1, - na.bridge = FALSE + timePeriod = 5, + deviations = 1, + na.bridge = FALSE, + ... ) { ## calculate indicator and ## return as data.frame x <- rolling_standard_deviation.default( x = x, - n = n, - k = k, + timePeriod = timePeriod, + deviations = deviations, na.bridge = na.bridge ) + ## strip dimensions + ## while preserving + ## attributes + dim(x) <- NULL + ## return indicator - as.double(x) + x +} + +#' @usage NULL +STDDEV_lookback <- rollingStandardDeviation_lookback <- rolling_standard_deviation_lookback <- function( + x, + timePeriod = 5, + deviations = 1, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_STDDEV_lookback, + as.integer(timePeriod), + as.double(deviations) + ) } diff --git a/R/ta_STOCH.R b/R/ta_STOCH.R index 735c6aa5d..81303093c 100644 --- a/R/ta_STOCH.R +++ b/R/ta_STOCH.R @@ -1,27 +1,31 @@ #' @export -#' @family Momentum Indicator +#' @family Momentum Indicators #' #' @title Stochastic #' @templateVar .title Stochastic #' @templateVar .author Serkan Korkmaz #' @templateVar .fun stochastic -#' @templateVar .family Momentum Indicator -#' @templateVar .formula ~ high + low + close +#' @templateVar .family Momentum Indicators +#' @templateVar .formula ~high + low + close #' ## splice:documentation:start -#' @param fastk ([integer]). Period for the fast-k line. -#' @param slowk ([list]). Period and Moving Average (MA) type for the slow-k line. [SMA] by default. -#' @param slowd ([list]). Period and Moving Average (MA) type for the slow-d line. [SMA] by default. ## splice:documentation:end #' #' @template description +#' @param fastKPeriod ([integer]). Time period for building the Fast-K line. Defaults to `5`. +#' @param slowKPeriod ([integer]). Smoothing for making the Slow-K line. Usually set to 3. Defaults to `3`. +#' @param slowKMa ([integer]). Type of Moving Average for Slow-K. Defaults to `0` ([SMA]). Can also be passed as talib::SMA. +#' @param slowDPeriod ([integer]). Smoothing for making the Slow-D line. Defaults to `3`. +#' @param slowDMa ([integer]). Type of Moving Average for Slow-D. Defaults to `0` ([SMA]). Can also be passed as talib::SMA. #' @template returns stochastic <- function( x, cols, - fastk = 5, - slowk = SMA(n = 3), - slowd = SMA(n = 3), + fastKPeriod = 5, + slowKPeriod = 3, + slowKMa = 0, + slowDPeriod = 3, + slowDMa = 0, na.bridge = FALSE, ... ) { @@ -42,9 +46,11 @@ STOCH <- stochastic stochastic.default <- function( x, cols, - fastk = 5, - slowk = SMA(n = 3), - slowd = SMA(n = 3), + fastKPeriod = 5, + slowKPeriod = 3, + slowKMa = 0, + slowDPeriod = 3, + slowDMa = 0, na.bridge = FALSE, ... ) { @@ -71,16 +77,14 @@ stochastic.default <- function( ## return as data.frame x <- .Call( C_impl_ta_STOCH, - ## splice:call: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:call:end + as.integer(fastKPeriod), + as.integer(slowKPeriod), + as.maType(slowKMa), + as.integer(slowDPeriod), + as.maType(slowDMa), as.logical(na.bridge) ) @@ -98,9 +102,11 @@ stochastic.default <- function( stochastic.data.frame <- function( x, cols, - fastk = 5, - slowk = SMA(n = 3), - slowd = SMA(n = 3), + fastKPeriod = 5, + slowKPeriod = 3, + slowKMa = 0, + slowDPeriod = 3, + slowDMa = 0, na.bridge = FALSE, ... ) { @@ -108,9 +114,11 @@ stochastic.data.frame <- function( stochastic.default( x = x, cols = cols, - fastk = fastk, - slowk = slowk, - slowd = slowd, + fastKPeriod = fastKPeriod, + slowKPeriod = slowKPeriod, + slowKMa = slowKMa, + slowDPeriod = slowDPeriod, + slowDMa = slowDMa, na.bridge = na.bridge, ... ) @@ -124,23 +132,48 @@ stochastic.data.frame <- function( stochastic.matrix <- function( x, cols, - fastk = 5, - slowk = SMA(n = 3), - slowd = SMA(n = 3), + fastKPeriod = 5, + slowKPeriod = 3, + slowKMa = 0, + slowDPeriod = 3, + slowDMa = 0, na.bridge = FALSE, ... ) { stochastic.default( x = x, cols = cols, - fastk = fastk, - slowk = slowk, - slowd = slowd, + fastKPeriod = fastKPeriod, + slowKPeriod = slowKPeriod, + slowKMa = slowKMa, + slowDPeriod = slowDPeriod, + slowDMa = slowDMa, na.bridge = na.bridge, ... ) } +#' @usage NULL +STOCH_lookback <- stochastic_lookback <- function( + x, + cols, + fastKPeriod = 5, + slowKPeriod = 3, + slowKMa = 0, + slowDPeriod = 3, + slowDMa = 0, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_STOCH_lookback, + as.integer(fastKPeriod), + as.integer(slowKPeriod), + as.maType(slowKMa), + as.integer(slowDPeriod), + as.maType(slowDMa) + ) +} #' @usage NULL #' @aliases stochastic @@ -149,9 +182,11 @@ stochastic.matrix <- function( stochastic.plotly <- function( x, cols, - fastk = 5, - slowk = SMA(n = 3), - slowd = SMA(n = 3), + fastKPeriod = 5, + slowKPeriod = 3, + slowKMa = 0, + slowDPeriod = 3, + slowDMa = 0, na.bridge = FALSE, ## splice:optional-plotly:start lower_bound = 20, @@ -186,9 +221,11 @@ stochastic.plotly <- function( cols = rebuild_formula( names(constructed_series) ), - fastk = fastk, - slowk = slowk, - slowd = slowd, + fastKPeriod = fastKPeriod, + slowKPeriod = slowKPeriod, + slowKMa = slowKMa, + slowDPeriod = slowDPeriod, + slowDMa = slowDMa, na.bridge = TRUE ) @@ -207,7 +244,7 @@ stochastic.plotly <- function( ## splice:plotly-assembly:start name <- sprintf( "Stochastic(%d)", - fastk + fastKPeriod ) decorators <- list( @@ -242,7 +279,8 @@ stochastic.plotly <- function( } ), data = constructed_indicator[, values_to_extract, drop = FALSE], - values_to_extract = values_to_extract + values_to_extract = values_to_extract, + name = get0(x = "name", ifnotfound = NULL) ) state <- .chart_state() @@ -258,13 +296,15 @@ stochastic.plotly <- function( stochastic.ggplot <- function( x, cols, - fastk = 5, - slowk = SMA(n = 3), - slowd = SMA(n = 3), + fastKPeriod = 5, + slowKPeriod = 3, + slowKMa = 0, + slowDPeriod = 3, + slowDMa = 0, na.bridge = FALSE, + title, ## splice:optional-ggplot:start ## splice:optional-ggplot:end - title, ... ) { ## check ggplot2 availability @@ -292,9 +332,11 @@ stochastic.ggplot <- function( cols = rebuild_formula( names(constructed_series) ), - fastk = fastk, - slowk = slowk, - slowd = slowd, + fastKPeriod = fastKPeriod, + slowKPeriod = slowKPeriod, + slowKMa = slowKMa, + slowDPeriod = slowDPeriod, + slowDMa = slowDMa, na.bridge = TRUE ) @@ -320,7 +362,7 @@ stochastic.ggplot <- function( list(y = "SlowK"), list(y = "SlowD") ) - name <- sprintf("Stochastic(%d)", fastk) + name <- sprintf("Stochastic(%d)", fastKPeriod) ## splice:ggplot-assembly:end ggplot_object <- add_last_value_gg( diff --git a/R/ta_STOCHF.R b/R/ta_STOCHF.R index 77fe43ad0..8b7d58b7e 100644 --- a/R/ta_STOCHF.R +++ b/R/ta_STOCHF.R @@ -1,25 +1,27 @@ #' @export -#' @family Momentum Indicator +#' @family Momentum Indicators #' -#' @title Fast Stochastic -#' @templateVar .title Fast Stochastic +#' @title Stochastic Fast +#' @templateVar .title Stochastic Fast #' @templateVar .author Serkan Korkmaz #' @templateVar .fun fast_stochastic -#' @templateVar .family Momentum Indicator -#' @templateVar .formula ~ high + low + close +#' @templateVar .family Momentum Indicators +#' @templateVar .formula ~high + low + close #' ## splice:documentation:start -#' @param fastk ([integer]). Period for the fast-k line. -#' @param fastd ([list]). Period and Moving Average (MA) type for the fast-d line. [SMA] by default. ## splice:documentation:end #' #' @template description +#' @param fastKPeriod ([integer]). Time period for building the Fast-K line. Defaults to `5`. +#' @param fastDPeriod ([integer]). Smoothing for making the Fast-D line. Usually set to 3. Defaults to `3`. +#' @param fastDMa ([integer]). Type of Moving Average for Fast-D. Defaults to `0` ([SMA]). Can also be passed as talib::SMA. #' @template returns fast_stochastic <- function( x, cols, - fastk = 5, - fastd = SMA(n = 3), + fastKPeriod = 5, + fastDPeriod = 3, + fastDMa = 0, na.bridge = FALSE, ... ) { @@ -33,6 +35,13 @@ fast_stochastic <- function( #' @aliases fast_stochastic STOCHF <- fast_stochastic +#' @export +#' @usage NULL +#' @rdname fast_stochastic +#' +#' @aliases fast_stochastic +fastStochastic <- fast_stochastic + #' @usage NULL #' @aliases fast_stochastic #' @@ -40,8 +49,9 @@ STOCHF <- fast_stochastic fast_stochastic.default <- function( x, cols, - fastk = 5, - fastd = SMA(n = 3), + fastKPeriod = 5, + fastDPeriod = 3, + fastDMa = 0, na.bridge = FALSE, ... ) { @@ -68,14 +78,12 @@ fast_stochastic.default <- function( ## return as data.frame x <- .Call( C_impl_ta_STOCHF, - ## splice:call:start constructed_series[[1]], constructed_series[[2]], constructed_series[[3]], - as.integer(fastk), - as.integer(fastd$n), - as.integer(fastd$maType), - ## splice:call:end + as.integer(fastKPeriod), + as.integer(fastDPeriod), + as.maType(fastDMa), as.logical(na.bridge) ) @@ -93,8 +101,9 @@ fast_stochastic.default <- function( fast_stochastic.data.frame <- function( x, cols, - fastk = 5, - fastd = SMA(n = 3), + fastKPeriod = 5, + fastDPeriod = 3, + fastDMa = 0, na.bridge = FALSE, ... ) { @@ -102,8 +111,9 @@ fast_stochastic.data.frame <- function( fast_stochastic.default( x = x, cols = cols, - fastk = fastk, - fastd = fastd, + fastKPeriod = fastKPeriod, + fastDPeriod = fastDPeriod, + fastDMa = fastDMa, na.bridge = na.bridge, ... ) @@ -117,21 +127,40 @@ fast_stochastic.data.frame <- function( fast_stochastic.matrix <- function( x, cols, - fastk = 5, - fastd = SMA(n = 3), + fastKPeriod = 5, + fastDPeriod = 3, + fastDMa = 0, na.bridge = FALSE, ... ) { fast_stochastic.default( x = x, cols = cols, - fastk = fastk, - fastd = fastd, + fastKPeriod = fastKPeriod, + fastDPeriod = fastDPeriod, + fastDMa = fastDMa, na.bridge = na.bridge, ... ) } +#' @usage NULL +STOCHF_lookback <- fastStochastic_lookback <- fast_stochastic_lookback <- function( + x, + cols, + fastKPeriod = 5, + fastDPeriod = 3, + fastDMa = 0, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_STOCHF_lookback, + as.integer(fastKPeriod), + as.integer(fastDPeriod), + as.maType(fastDMa) + ) +} #' @usage NULL #' @aliases fast_stochastic @@ -140,8 +169,9 @@ fast_stochastic.matrix <- function( fast_stochastic.plotly <- function( x, cols, - fastk = 5, - fastd = SMA(n = 3), + fastKPeriod = 5, + fastDPeriod = 3, + fastDMa = 0, na.bridge = FALSE, ## splice:optional-plotly:start lower_bound = 20, @@ -176,8 +206,9 @@ fast_stochastic.plotly <- function( cols = rebuild_formula( names(constructed_series) ), - fastk = fastk, - fastd = fastd, + fastKPeriod = fastKPeriod, + fastDPeriod = fastDPeriod, + fastDMa = fastDMa, na.bridge = TRUE ) @@ -195,7 +226,7 @@ fast_stochastic.plotly <- function( ## construct {plotly}-object ## splice:plotly-assembly:start - name <- "" + name <- sprintf("StochF(%d)", fastKPeriod) decorators <- list( function(p) add_limit_ly(p, y_range = c(0, 100)) @@ -223,13 +254,14 @@ fast_stochastic.plotly <- function( ), data = constructed_indicator, title = if (missing(title)) { - "Fast Stochastic" + "Stochastic Fast" } else { title } ), data = constructed_indicator[, values_to_extract, drop = FALSE], - values_to_extract = values_to_extract + values_to_extract = values_to_extract, + name = get0(x = "name", ifnotfound = NULL) ) state <- .chart_state() @@ -245,12 +277,13 @@ fast_stochastic.plotly <- function( fast_stochastic.ggplot <- function( x, cols, - fastk = 5, - fastd = SMA(n = 3), + fastKPeriod = 5, + fastDPeriod = 3, + fastDMa = 0, na.bridge = FALSE, + title, ## splice:optional-ggplot:start ## splice:optional-ggplot:end - title, ... ) { ## check ggplot2 availability @@ -278,8 +311,9 @@ fast_stochastic.ggplot <- function( cols = rebuild_formula( names(constructed_series) ), - fastk = fastk, - fastd = fastd, + fastKPeriod = fastKPeriod, + fastDPeriod = fastDPeriod, + fastDMa = fastDMa, na.bridge = TRUE ) @@ -305,7 +339,7 @@ fast_stochastic.ggplot <- function( list(y = "FastK"), list(y = "FastD") ) - name <- sprintf("StochF(%d)", fastk) + name <- sprintf("StochF(%d)", fastKPeriod) ## splice:ggplot-assembly:end ggplot_object <- add_last_value_gg( @@ -322,7 +356,7 @@ fast_stochastic.ggplot <- function( ), data = constructed_indicator, title = if (missing(title)) { - "Fast Stochastic" + "Stochastic Fast" } else { title } diff --git a/R/ta_STOCHRSI.R b/R/ta_STOCHRSI.R index c42c46426..bfc927033 100644 --- a/R/ta_STOCHRSI.R +++ b/R/ta_STOCHRSI.R @@ -1,26 +1,28 @@ #' @export -#' @family Momentum Indicator +#' @family Momentum Indicators #' #' @title Stochastic Relative Strength Index #' @templateVar .title Stochastic Relative Strength Index #' @templateVar .author Serkan Korkmaz #' @templateVar .fun stochastic_relative_strength_index -#' @templateVar .family Momentum Indicator +#' @templateVar .family Momentum Indicators #' @templateVar .formula ~close #' ## splice:documentation:start -#' @param fastk ([integer]). Period for the fast-k line. -#' @param fastd ([list]). Period and Moving Average (MA) type for the fast-d line. [SMA] by default. ## splice:documentation:end #' #' @template description +#' @param fastKPeriod ([integer]). Time period for building the Fast-K line. Defaults to `5`. +#' @param fastDPeriod ([integer]). Smoothing for making the Fast-D line. Usually set to 3. Defaults to `3`. +#' @param fastDMa ([integer]). Type of Moving Average for Fast-D. Defaults to `0` ([SMA]). Can also be passed as talib::SMA. #' @template returns stochastic_relative_strength_index <- function( x, cols, - n = 14, - fastk = 5, - fastd = SMA(n = 3), + timePeriod = 14, + fastKPeriod = 5, + fastDPeriod = 3, + fastDMa = 0, na.bridge = FALSE, ... ) { @@ -34,6 +36,13 @@ stochastic_relative_strength_index <- function( #' @aliases stochastic_relative_strength_index STOCHRSI <- stochastic_relative_strength_index +#' @export +#' @usage NULL +#' @rdname stochastic_relative_strength_index +#' +#' @aliases stochastic_relative_strength_index +stochasticRelativeStrengthIndex <- stochastic_relative_strength_index + #' @usage NULL #' @aliases stochastic_relative_strength_index #' @@ -41,9 +50,10 @@ STOCHRSI <- stochastic_relative_strength_index stochastic_relative_strength_index.default <- function( x, cols, - n = 14, - fastk = 5, - fastd = SMA(n = 3), + timePeriod = 14, + fastKPeriod = 5, + fastDPeriod = 3, + fastDMa = 0, na.bridge = FALSE, ... ) { @@ -70,13 +80,11 @@ stochastic_relative_strength_index.default <- function( ## return as data.frame x <- .Call( C_impl_ta_STOCHRSI, - ## splice:call:start constructed_series[[1]], - as.integer(n), - as.integer(fastk), - as.integer(fastd$n), - as.integer(fastd$maType), - ## splice:call:end + as.integer(timePeriod), + as.integer(fastKPeriod), + as.integer(fastDPeriod), + as.maType(fastDMa), as.logical(na.bridge) ) @@ -94,9 +102,10 @@ stochastic_relative_strength_index.default <- function( stochastic_relative_strength_index.data.frame <- function( x, cols, - n = 14, - fastk = 5, - fastd = SMA(n = 3), + timePeriod = 14, + fastKPeriod = 5, + fastDPeriod = 3, + fastDMa = 0, na.bridge = FALSE, ... ) { @@ -104,9 +113,10 @@ stochastic_relative_strength_index.data.frame <- function( stochastic_relative_strength_index.default( x = x, cols = cols, - n = n, - fastk = fastk, - fastd = fastd, + timePeriod = timePeriod, + fastKPeriod = fastKPeriod, + fastDPeriod = fastDPeriod, + fastDMa = fastDMa, na.bridge = na.bridge, ... ) @@ -120,23 +130,44 @@ stochastic_relative_strength_index.data.frame <- function( stochastic_relative_strength_index.matrix <- function( x, cols, - n = 14, - fastk = 5, - fastd = SMA(n = 3), + timePeriod = 14, + fastKPeriod = 5, + fastDPeriod = 3, + fastDMa = 0, na.bridge = FALSE, ... ) { stochastic_relative_strength_index.default( x = x, cols = cols, - n = n, - fastk = fastk, - fastd = fastd, + timePeriod = timePeriod, + fastKPeriod = fastKPeriod, + fastDPeriod = fastDPeriod, + fastDMa = fastDMa, na.bridge = na.bridge, ... ) } +#' @usage NULL +STOCHRSI_lookback <- stochasticRelativeStrengthIndex_lookback <- stochastic_relative_strength_index_lookback <- function( + x, + cols, + timePeriod = 14, + fastKPeriod = 5, + fastDPeriod = 3, + fastDMa = 0, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_STOCHRSI_lookback, + as.integer(timePeriod), + as.integer(fastKPeriod), + as.integer(fastDPeriod), + as.maType(fastDMa) + ) +} #' @usage NULL #' @aliases stochastic_relative_strength_index @@ -145,9 +176,10 @@ stochastic_relative_strength_index.matrix <- function( stochastic_relative_strength_index.numeric <- function( x, cols, - n = 14, - fastk = 5, - fastd = SMA(n = 3), + timePeriod = 14, + fastKPeriod = 5, + fastDPeriod = 3, + fastDMa = 0, na.bridge = FALSE, ... ) { @@ -163,32 +195,21 @@ stochastic_relative_strength_index.numeric <- function( ## to 'C' x <- .Call( C_impl_ta_STOCHRSI, - ## splice:numeric:start as.double(x), - as.integer(n), - as.integer(fastk), - as.integer(fastd$n), - as.integer(fastd$maType), - ## splice:numeric:end + as.integer(timePeriod), + as.integer(fastKPeriod), + as.integer(fastDPeriod), + as.maType(fastDMa), 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 #' @aliases stochastic_relative_strength_index #' @@ -196,9 +217,10 @@ stochastic_relative_strength_index.numeric <- function( stochastic_relative_strength_index.plotly <- function( x, cols, - n = 14, - fastk = 5, - fastd = SMA(n = 3), + timePeriod = 14, + fastKPeriod = 5, + fastDPeriod = 3, + fastDMa = 0, na.bridge = FALSE, ## splice:optional-plotly:start lower_bound = 20, @@ -233,9 +255,10 @@ stochastic_relative_strength_index.plotly <- function( cols = rebuild_formula( names(constructed_series) ), - n = n, - fastk = fastk, - fastd = fastd, + timePeriod = timePeriod, + fastKPeriod = fastKPeriod, + fastDPeriod = fastDPeriod, + fastDMa = fastDMa, na.bridge = TRUE ) @@ -286,7 +309,8 @@ stochastic_relative_strength_index.plotly <- function( } ), data = constructed_indicator[, values_to_extract, drop = FALSE], - values_to_extract = values_to_extract + values_to_extract = values_to_extract, + name = get0(x = "name", ifnotfound = NULL) ) state <- .chart_state() @@ -302,13 +326,14 @@ stochastic_relative_strength_index.plotly <- function( stochastic_relative_strength_index.ggplot <- function( x, cols, - n = 14, - fastk = 5, - fastd = SMA(n = 3), + timePeriod = 14, + fastKPeriod = 5, + fastDPeriod = 3, + fastDMa = 0, na.bridge = FALSE, + title, ## splice:optional-ggplot:start ## splice:optional-ggplot:end - title, ... ) { ## check ggplot2 availability @@ -336,9 +361,10 @@ stochastic_relative_strength_index.ggplot <- function( cols = rebuild_formula( names(constructed_series) ), - n = n, - fastk = fastk, - fastd = fastd, + timePeriod = timePeriod, + fastKPeriod = fastKPeriod, + fastDPeriod = fastDPeriod, + fastDMa = fastDMa, na.bridge = TRUE ) diff --git a/R/ta_SUM.R b/R/ta_SUM.R index 7cdf8cef3..ab4ea9813 100644 --- a/R/ta_SUM.R +++ b/R/ta_SUM.R @@ -1,8 +1,8 @@ #' @export -#' @family Rolling Statistic +#' @family Rolling Statistics #' -#' @title Rolling Sum -#' @templateVar .title Rolling Sum +#' @title Summation +#' @templateVar .title Summation #' @templateVar .author Serkan Korkmaz #' @templateVar .fun rolling_sum #' @@ -10,11 +10,13 @@ ## splice:documentation:end #' #' @template rolling_description +#' #' @template rolling_returns rolling_sum <- function( x, - n = 30, - na.bridge = FALSE + timePeriod = 30, + na.bridge = FALSE, + ... ) { UseMethod("rolling_sum") } @@ -26,14 +28,22 @@ rolling_sum <- function( #' @aliases rolling_sum SUM <- rolling_sum +#' @export +#' @usage NULL +#' @rdname rolling_sum +#' +#' @aliases rolling_sum +rollingSum <- rolling_sum + #' @usage NULL #' @aliases rolling_sum #' #' @export rolling_sum.default <- function( x, - n = 30, - na.bridge = FALSE + timePeriod = 30, + na.bridge = FALSE, + ... ) { ## calculate indicator and ## return as data.frame @@ -41,13 +51,18 @@ rolling_sum.default <- function( C_impl_ta_SUM, ## splice:call:start as.double(x), - as.integer(n), + as.integer(timePeriod), ## splice:call:end as.logical(na.bridge) ) + ## strip dimensions + ## while preserving + ## attributes + dim(x) <- NULL + ## return indicator - as.double(x) + x } #' @usage NULL @@ -56,17 +71,36 @@ rolling_sum.default <- function( #' @export rolling_sum.numeric <- function( x, - n = 30, - na.bridge = FALSE + timePeriod = 30, + na.bridge = FALSE, + ... ) { ## calculate indicator and ## return as data.frame x <- rolling_sum.default( x = x, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge ) + ## strip dimensions + ## while preserving + ## attributes + dim(x) <- NULL + ## return indicator - as.double(x) + x +} + +#' @usage NULL +SUM_lookback <- rollingSum_lookback <- rolling_sum_lookback <- function( + x, + timePeriod = 30, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_SUM_lookback, + as.integer(timePeriod) + ) } diff --git a/R/ta_T3.R b/R/ta_T3.R index 34ac9aca2..fe39a1a3a 100644 --- a/R/ta_T3.R +++ b/R/ta_T3.R @@ -1,15 +1,14 @@ #' @export -#' @family Overlap Study +#' @family Overlap Studies #' #' @title Triple Exponential Moving Average (T3) #' @templateVar .title Triple Exponential Moving Average (T3) #' @templateVar .author Serkan Korkmaz #' @templateVar .fun t3_exponential_moving_average -#' @templateVar .family Overlap Study +#' @templateVar .family Overlap Studies #' @templateVar .formula ~close #' ## splice:documentation:start -#' @param vfactor ([double]). Volume Factor controlling the smoothing weight of the T3 curve. A [double] in `[0, 1]`: `0` collapses T3 to a standard triple EMA, larger values shift the curve closer to a DEMA. `0.7` by default, following Tillson (1998). ## splice:documentation:end #' #' @details @@ -19,12 +18,13 @@ #' indicators that supports various Moving Average specifications. #' #' @template description +#' @param volumeFactor ([double]). Volume Factor. Defaults to `0.7`. #' @template returns t3_exponential_moving_average <- function( x, cols, - n = 5, - vfactor = 0.7, + timePeriod = 5, + volumeFactor = 0.7, na.bridge = FALSE, ... ) { @@ -35,14 +35,24 @@ t3_exponential_moving_average <- function( ## from call x <- structure( list( - n = if (missing(n)) 5L else as.integer(n), - vfactor = if (missing(vfactor)) 0.7 else as.double(vfactor), + timePeriod = if (missing(timePeriod)) { + 5L + } else { + as.integer(timePeriod) + }, + volumeFactor = if (missing(volumeFactor)) { + 0.7 + } else { + as.double(volumeFactor) + }, maType = 8L - ) + ), + class = "maType" ) return(x) } + UseMethod("t3_exponential_moving_average") } @@ -53,6 +63,13 @@ t3_exponential_moving_average <- function( #' @aliases t3_exponential_moving_average T3 <- t3_exponential_moving_average +#' @export +#' @usage NULL +#' @rdname t3_exponential_moving_average +#' +#' @aliases t3_exponential_moving_average +t3ExponentialMovingAverage <- t3_exponential_moving_average + #' @usage NULL #' @aliases t3_exponential_moving_average #' @@ -60,8 +77,8 @@ T3 <- t3_exponential_moving_average t3_exponential_moving_average.default <- function( x, cols, - n = 5, - vfactor = 0.7, + timePeriod = 5, + volumeFactor = 0.7, na.bridge = FALSE, ... ) { @@ -88,9 +105,9 @@ t3_exponential_moving_average.default <- function( ## return as data.frame x <- .Call( C_impl_ta_T3, - as.double(constructed_series[[1]]), - as.integer(n), - as.double(vfactor), + constructed_series[[1]], + as.integer(timePeriod), + as.double(volumeFactor), as.logical(na.bridge) ) @@ -108,13 +125,20 @@ t3_exponential_moving_average.default <- function( t3_exponential_moving_average.data.frame <- function( x, cols, - n = 5, - vfactor = 0.7, + timePeriod = 5, + volumeFactor = 0.7, na.bridge = FALSE, ... ) { map_dfr( - NextMethod() + t3_exponential_moving_average.default( + x = x, + cols = cols, + timePeriod = timePeriod, + volumeFactor = volumeFactor, + na.bridge = na.bridge, + ... + ) ) } @@ -125,19 +149,16 @@ t3_exponential_moving_average.data.frame <- function( t3_exponential_moving_average.matrix <- function( x, cols, - n = 5, - vfactor = 0.7, + timePeriod = 5, + volumeFactor = 0.7, na.bridge = FALSE, ... ) { - ## pass directly to - ## t3_exponential_moving_average.default to avoid - ## shenanigans with NextMethod() t3_exponential_moving_average.default( x = x, cols = cols, - n = n, - vfactor = vfactor, + timePeriod = timePeriod, + volumeFactor = volumeFactor, na.bridge = na.bridge, ... ) @@ -150,8 +171,8 @@ t3_exponential_moving_average.matrix <- function( t3_exponential_moving_average.numeric <- function( x, cols, - n = 5, - vfactor = 0.7, + timePeriod = 5, + volumeFactor = 0.7, na.bridge = FALSE, ... ) { @@ -168,26 +189,35 @@ t3_exponential_moving_average.numeric <- function( x <- .Call( C_impl_ta_T3, as.double(x), - as.integer(n), - as.double(vfactor), + as.integer(timePeriod), + as.double(volumeFactor), 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 <- t3ExponentialMovingAverage_lookback <- t3_exponential_moving_average_lookback <- function( + x, + cols, + timePeriod = 5, + volumeFactor = 0.7, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_T3_lookback, + as.integer(timePeriod), + as.double(volumeFactor) + ) +} + + #' @usage NULL #' @aliases t3_exponential_moving_average #' @@ -195,8 +225,8 @@ t3_exponential_moving_average.numeric <- function( t3_exponential_moving_average.plotly <- function( x, cols, - n = 5, - vfactor = 0.7, + timePeriod = 5, + volumeFactor = 0.7, na.bridge = FALSE, ... ) { @@ -226,8 +256,9 @@ t3_exponential_moving_average.plotly <- function( cols = rebuild_formula( names(constructed_series) ), - n = n, - vfactor = vfactor + timePeriod = timePeriod, + volumeFactor = volumeFactor, + na.bridge = TRUE ) ## add conditional idx @@ -250,15 +281,15 @@ t3_exponential_moving_average.plotly <- function( ) ) ), - name = label("T3", n, vfactor), - decorators = list() + name = label("T3", timePeriod, volumeFactor), + decorators = list(), + data = constructed_indicator ) state[["main"]] <- plotly_object plotly_object } - #' @usage NULL #' @aliases t3_exponential_moving_average #' @@ -266,8 +297,8 @@ t3_exponential_moving_average.plotly <- function( t3_exponential_moving_average.ggplot <- function( x, cols, - n = 5, - vfactor = 0.7, + timePeriod = 5, + volumeFactor = 0.7, na.bridge = FALSE, ... ) { @@ -296,8 +327,9 @@ t3_exponential_moving_average.ggplot <- function( cols = rebuild_formula( names(constructed_series) ), - n = n, - vfactor = vfactor + timePeriod = timePeriod, + volumeFactor = volumeFactor, + na.bridge = TRUE ) ## add conditional idx @@ -314,7 +346,7 @@ t3_exponential_moving_average.ggplot <- function( y = "T3" ) ), - name = label("T3", n, vfactor), + name = label("T3", timePeriod, volumeFactor), decorators = list(), data = constructed_indicator ) diff --git a/R/ta_TEMA.R b/R/ta_TEMA.R index 07c502522..4ee93b851 100644 --- a/R/ta_TEMA.R +++ b/R/ta_TEMA.R @@ -1,11 +1,11 @@ #' @export -#' @family Overlap Study +#' @family Overlap Studies #' #' @title Triple Exponential Moving Average #' @templateVar .title Triple Exponential Moving Average #' @templateVar .author Serkan Korkmaz #' @templateVar .fun triple_exponential_moving_average -#' @templateVar .family Overlap Study +#' @templateVar .family Overlap Studies #' @templateVar .formula ~close #' ## splice:documentation:start @@ -18,11 +18,12 @@ #' indicators that supports various Moving Average specifications. #' #' @template description +#' #' @template returns triple_exponential_moving_average <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, ... ) { @@ -33,13 +34,19 @@ triple_exponential_moving_average <- function( ## from call x <- structure( list( - n = if (missing(n)) 30L else as.integer(n), + timePeriod = if (missing(timePeriod)) { + 30L + } else { + as.integer(timePeriod) + }, maType = 4L - ) + ), + class = "maType" ) return(x) } + UseMethod("triple_exponential_moving_average") } @@ -50,6 +57,13 @@ triple_exponential_moving_average <- function( #' @aliases triple_exponential_moving_average TEMA <- triple_exponential_moving_average +#' @export +#' @usage NULL +#' @rdname triple_exponential_moving_average +#' +#' @aliases triple_exponential_moving_average +tripleExponentialMovingAverage <- triple_exponential_moving_average + #' @usage NULL #' @aliases triple_exponential_moving_average #' @@ -57,7 +71,7 @@ TEMA <- triple_exponential_moving_average triple_exponential_moving_average.default <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, ... ) { @@ -84,8 +98,8 @@ triple_exponential_moving_average.default <- function( ## return as data.frame x <- .Call( C_impl_ta_TEMA, - as.double(constructed_series[[1]]), - as.integer(n), + constructed_series[[1]], + as.integer(timePeriod), as.logical(na.bridge) ) @@ -103,12 +117,18 @@ triple_exponential_moving_average.default <- function( triple_exponential_moving_average.data.frame <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, ... ) { map_dfr( - NextMethod() + triple_exponential_moving_average.default( + x = x, + cols = cols, + timePeriod = timePeriod, + na.bridge = na.bridge, + ... + ) ) } @@ -119,17 +139,14 @@ triple_exponential_moving_average.data.frame <- function( triple_exponential_moving_average.matrix <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, ... ) { - ## pass directly to - ## triple_exponential_moving_average.default to avoid - ## shenanigans with NextMethod() triple_exponential_moving_average.default( x = x, cols = cols, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge, ... ) @@ -142,7 +159,7 @@ triple_exponential_moving_average.matrix <- function( triple_exponential_moving_average.numeric <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, ... ) { @@ -159,25 +176,32 @@ triple_exponential_moving_average.numeric <- function( x <- .Call( C_impl_ta_TEMA, as.double(x), - as.integer(n), + as.integer(timePeriod), 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 <- tripleExponentialMovingAverage_lookback <- triple_exponential_moving_average_lookback <- function( + x, + cols, + timePeriod = 30, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_TEMA_lookback, + as.integer(timePeriod) + ) +} + + #' @usage NULL #' @aliases triple_exponential_moving_average #' @@ -185,7 +209,7 @@ triple_exponential_moving_average.numeric <- function( triple_exponential_moving_average.plotly <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, ... ) { @@ -215,7 +239,8 @@ triple_exponential_moving_average.plotly <- function( cols = rebuild_formula( names(constructed_series) ), - n = n + timePeriod = timePeriod, + na.bridge = TRUE ) ## add conditional idx @@ -238,15 +263,15 @@ triple_exponential_moving_average.plotly <- function( ) ) ), - name = label("TEMA", n), - decorators = list() + name = label("TEMA", timePeriod), + decorators = list(), + data = constructed_indicator ) state[["main"]] <- plotly_object plotly_object } - #' @usage NULL #' @aliases triple_exponential_moving_average #' @@ -254,7 +279,7 @@ triple_exponential_moving_average.plotly <- function( triple_exponential_moving_average.ggplot <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, ... ) { @@ -283,7 +308,8 @@ triple_exponential_moving_average.ggplot <- function( cols = rebuild_formula( names(constructed_series) ), - n = n + timePeriod = timePeriod, + na.bridge = TRUE ) ## add conditional idx @@ -300,7 +326,7 @@ triple_exponential_moving_average.ggplot <- function( y = "TEMA" ) ), - name = label("TEMA", n), + name = label("TEMA", timePeriod), decorators = list(), data = constructed_indicator ) diff --git a/R/ta_TRANGE.R b/R/ta_TRANGE.R index 943ca796c..baf6750c5 100644 --- a/R/ta_TRANGE.R +++ b/R/ta_TRANGE.R @@ -1,17 +1,18 @@ #' @export -#' @family Volatility Indicator +#' @family Volatility Indicators #' #' @title True Range #' @templateVar .title True Range #' @templateVar .author Serkan Korkmaz #' @templateVar .fun true_range -#' @templateVar .family Volatility Indicator +#' @templateVar .family Volatility Indicators #' @templateVar .formula ~high + low + close #' ## splice:documentation:start ## splice:documentation:end #' #' @template description +#' #' @template returns true_range <- function( x, @@ -29,6 +30,13 @@ true_range <- function( #' @aliases true_range TRANGE <- true_range +#' @export +#' @usage NULL +#' @rdname true_range +#' +#' @aliases true_range +trueRange <- true_range + #' @usage NULL #' @aliases true_range #' @@ -62,11 +70,9 @@ true_range.default <- function( ## return as data.frame x <- .Call( C_impl_ta_TRANGE, - ## splice:call:start constructed_series[[1]], constructed_series[[2]], constructed_series[[3]], - ## splice:call:end as.logical(na.bridge) ) @@ -115,6 +121,17 @@ true_range.matrix <- function( ) } +#' @usage NULL +TRANGE_lookback <- trueRange_lookback <- true_range_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_TRANGE_lookback + ) +} #' @usage NULL #' @aliases true_range @@ -198,7 +215,8 @@ true_range.plotly <- function( } ), data = constructed_indicator[, values_to_extract, drop = FALSE], - values_to_extract = values_to_extract + values_to_extract = values_to_extract, + name = get0(x = "name", ifnotfound = NULL) ) state <- .chart_state() @@ -215,9 +233,9 @@ true_range.ggplot <- function( x, cols, na.bridge = FALSE, + title, ## splice:optional-ggplot:start ## splice:optional-ggplot:end - title, ... ) { ## check ggplot2 availability diff --git a/R/ta_TRIMA.R b/R/ta_TRIMA.R index 5b49db271..f891f7f90 100644 --- a/R/ta_TRIMA.R +++ b/R/ta_TRIMA.R @@ -1,11 +1,11 @@ #' @export -#' @family Overlap Study +#' @family Overlap Studies #' #' @title Triangular Moving Average #' @templateVar .title Triangular Moving Average #' @templateVar .author Serkan Korkmaz #' @templateVar .fun triangular_moving_average -#' @templateVar .family Overlap Study +#' @templateVar .family Overlap Studies #' @templateVar .formula ~close #' ## splice:documentation:start @@ -18,11 +18,12 @@ #' indicators that supports various Moving Average specifications. #' #' @template description +#' #' @template returns triangular_moving_average <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, ... ) { @@ -33,13 +34,19 @@ triangular_moving_average <- function( ## from call x <- structure( list( - n = if (missing(n)) 30L else as.integer(n), + timePeriod = if (missing(timePeriod)) { + 30L + } else { + as.integer(timePeriod) + }, maType = 5L - ) + ), + class = "maType" ) return(x) } + UseMethod("triangular_moving_average") } @@ -50,6 +57,13 @@ triangular_moving_average <- function( #' @aliases triangular_moving_average TRIMA <- triangular_moving_average +#' @export +#' @usage NULL +#' @rdname triangular_moving_average +#' +#' @aliases triangular_moving_average +triangularMovingAverage <- triangular_moving_average + #' @usage NULL #' @aliases triangular_moving_average #' @@ -57,7 +71,7 @@ TRIMA <- triangular_moving_average triangular_moving_average.default <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, ... ) { @@ -84,8 +98,8 @@ triangular_moving_average.default <- function( ## return as data.frame x <- .Call( C_impl_ta_TRIMA, - as.double(constructed_series[[1]]), - as.integer(n), + constructed_series[[1]], + as.integer(timePeriod), as.logical(na.bridge) ) @@ -103,12 +117,18 @@ triangular_moving_average.default <- function( triangular_moving_average.data.frame <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, ... ) { map_dfr( - NextMethod() + triangular_moving_average.default( + x = x, + cols = cols, + timePeriod = timePeriod, + na.bridge = na.bridge, + ... + ) ) } @@ -119,17 +139,14 @@ triangular_moving_average.data.frame <- function( triangular_moving_average.matrix <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, ... ) { - ## pass directly to - ## triangular_moving_average.default to avoid - ## shenanigans with NextMethod() triangular_moving_average.default( x = x, cols = cols, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge, ... ) @@ -142,7 +159,7 @@ triangular_moving_average.matrix <- function( triangular_moving_average.numeric <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, ... ) { @@ -159,25 +176,32 @@ triangular_moving_average.numeric <- function( x <- .Call( C_impl_ta_TRIMA, as.double(x), - as.integer(n), + as.integer(timePeriod), 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 <- triangularMovingAverage_lookback <- triangular_moving_average_lookback <- function( + x, + cols, + timePeriod = 30, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_TRIMA_lookback, + as.integer(timePeriod) + ) +} + + #' @usage NULL #' @aliases triangular_moving_average #' @@ -185,7 +209,7 @@ triangular_moving_average.numeric <- function( triangular_moving_average.plotly <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, ... ) { @@ -215,7 +239,8 @@ triangular_moving_average.plotly <- function( cols = rebuild_formula( names(constructed_series) ), - n = n + timePeriod = timePeriod, + na.bridge = TRUE ) ## add conditional idx @@ -238,15 +263,15 @@ triangular_moving_average.plotly <- function( ) ) ), - name = label("TRIMA", n), - decorators = list() + name = label("TRIMA", timePeriod), + decorators = list(), + data = constructed_indicator ) state[["main"]] <- plotly_object plotly_object } - #' @usage NULL #' @aliases triangular_moving_average #' @@ -254,7 +279,7 @@ triangular_moving_average.plotly <- function( triangular_moving_average.ggplot <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, ... ) { @@ -283,7 +308,8 @@ triangular_moving_average.ggplot <- function( cols = rebuild_formula( names(constructed_series) ), - n = n + timePeriod = timePeriod, + na.bridge = TRUE ) ## add conditional idx @@ -300,7 +326,7 @@ triangular_moving_average.ggplot <- function( y = "TRIMA" ) ), - name = label("TRIMA", n), + name = label("TRIMA", timePeriod), decorators = list(), data = constructed_indicator ) diff --git a/R/ta_TRIX.R b/R/ta_TRIX.R index 269a686cd..19c8a6b77 100644 --- a/R/ta_TRIX.R +++ b/R/ta_TRIX.R @@ -1,22 +1,23 @@ #' @export -#' @family Momentum Indicator +#' @family Momentum Indicators #' -#' @title Triple Exponential Average -#' @templateVar .title Triple Exponential Average +#' @title 1-day Rate-Of-Change (ROC) of a Triple Smooth EMA +#' @templateVar .title 1-day Rate-Of-Change (ROC) of a Triple Smooth EMA #' @templateVar .author Serkan Korkmaz #' @templateVar .fun triple_exponential_average -#' @templateVar .family Momentum Indicator +#' @templateVar .family Momentum Indicators #' @templateVar .formula ~close #' ## splice:documentation:start ## splice:documentation:end #' #' @template description +#' #' @template returns triple_exponential_average <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, ... ) { @@ -30,6 +31,13 @@ triple_exponential_average <- function( #' @aliases triple_exponential_average TRIX <- triple_exponential_average +#' @export +#' @usage NULL +#' @rdname triple_exponential_average +#' +#' @aliases triple_exponential_average +tripleExponentialAverage <- triple_exponential_average + #' @usage NULL #' @aliases triple_exponential_average #' @@ -37,7 +45,7 @@ TRIX <- triple_exponential_average triple_exponential_average.default <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, ... ) { @@ -64,10 +72,8 @@ triple_exponential_average.default <- function( ## return as data.frame x <- .Call( C_impl_ta_TRIX, - ## splice:call:start constructed_series[[1]], - as.integer(n), - ## splice:call:end + as.integer(timePeriod), as.logical(na.bridge) ) @@ -85,7 +91,7 @@ triple_exponential_average.default <- function( triple_exponential_average.data.frame <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, ... ) { @@ -93,7 +99,7 @@ triple_exponential_average.data.frame <- function( triple_exponential_average.default( x = x, cols = cols, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge, ... ) @@ -107,19 +113,32 @@ triple_exponential_average.data.frame <- function( triple_exponential_average.matrix <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, ... ) { triple_exponential_average.default( x = x, cols = cols, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge, ... ) } +#' @usage NULL +TRIX_lookback <- tripleExponentialAverage_lookback <- triple_exponential_average_lookback <- function( + x, + cols, + timePeriod = 30, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_TRIX_lookback, + as.integer(timePeriod) + ) +} #' @usage NULL #' @aliases triple_exponential_average @@ -128,7 +147,7 @@ triple_exponential_average.matrix <- function( triple_exponential_average.numeric <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, ... ) { @@ -144,29 +163,18 @@ triple_exponential_average.numeric <- function( ## to 'C' x <- .Call( C_impl_ta_TRIX, - ## splice:numeric:start as.double(x), - as.integer(n), - ## splice:numeric:end + as.integer(timePeriod), 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 #' @aliases triple_exponential_average #' @@ -174,7 +182,7 @@ triple_exponential_average.numeric <- function( triple_exponential_average.plotly <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, ## splice:optional-plotly:start ## splice:optional-plotly:end @@ -207,7 +215,7 @@ triple_exponential_average.plotly <- function( cols = rebuild_formula( names(constructed_series) ), - n = n, + timePeriod = timePeriod, na.bridge = TRUE ) @@ -224,7 +232,7 @@ triple_exponential_average.plotly <- function( ## construct {plotly}-object ## splice:plotly-assembly:start - name <- sprintf("TRIX(%d)", n) + name <- sprintf("TRIX(%d)", timePeriod) decorators <- list() traces <- list( list(y = ~TRIX) @@ -245,13 +253,14 @@ triple_exponential_average.plotly <- function( ), data = constructed_indicator, title = if (missing(title)) { - "Triple Exponential Average" + "1-day Rate-Of-Change (ROC) of a Triple Smooth EMA" } else { title } ), data = constructed_indicator[, values_to_extract, drop = FALSE], - values_to_extract = values_to_extract + values_to_extract = values_to_extract, + name = get0(x = "name", ifnotfound = NULL) ) state <- .chart_state() @@ -267,11 +276,11 @@ triple_exponential_average.plotly <- function( triple_exponential_average.ggplot <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, + title, ## splice:optional-ggplot:start ## splice:optional-ggplot:end - title, ... ) { ## check ggplot2 availability @@ -299,7 +308,7 @@ triple_exponential_average.ggplot <- function( cols = rebuild_formula( names(constructed_series) ), - n = n, + timePeriod = timePeriod, na.bridge = TRUE ) @@ -320,7 +329,7 @@ triple_exponential_average.ggplot <- function( setdiff(colnames(constructed_indicator), "idx"), function(col) list(y = col) ) - name <- sprintf("TRIX(%d)", n) + name <- sprintf("TRIX(%d)", timePeriod) ## splice:ggplot-assembly:end ggplot_object <- add_last_value_gg( @@ -337,7 +346,7 @@ triple_exponential_average.ggplot <- function( ), data = constructed_indicator, title = if (missing(title)) { - "Triple Exponential Average" + "1-day Rate-Of-Change (ROC) of a Triple Smooth EMA" } else { title } diff --git a/R/ta_TYPPRICE.R b/R/ta_TYPPRICE.R index a1628d57f..03bf1d156 100644 --- a/R/ta_TYPPRICE.R +++ b/R/ta_TYPPRICE.R @@ -12,6 +12,7 @@ ## splice:documentation:end #' #' @template description +#' #' @template returns typical_price <- function( x, @@ -29,6 +30,13 @@ typical_price <- function( #' @aliases typical_price TYPPRICE <- typical_price +#' @export +#' @usage NULL +#' @rdname typical_price +#' +#' @aliases typical_price +typicalPrice <- typical_price + #' @usage NULL #' @aliases typical_price #' @@ -62,11 +70,9 @@ typical_price.default <- function( ## return as data.frame x <- .Call( C_impl_ta_TYPPRICE, - ## splice:call:start constructed_series[[1]], constructed_series[[2]], constructed_series[[3]], - ## splice:call:end as.logical(na.bridge) ) @@ -114,3 +120,15 @@ typical_price.matrix <- function( ... ) } + +#' @usage NULL +TYPPRICE_lookback <- typicalPrice_lookback <- typical_price_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_TYPPRICE_lookback + ) +} diff --git a/R/ta_ULTOSC.R b/R/ta_ULTOSC.R index b9792b5b9..270785429 100644 --- a/R/ta_ULTOSC.R +++ b/R/ta_ULTOSC.R @@ -1,22 +1,27 @@ #' @export -#' @family Momentum Indicator +#' @family Momentum Indicators #' #' @title Ultimate Oscillator #' @templateVar .title Ultimate Oscillator #' @templateVar .author Serkan Korkmaz #' @templateVar .fun ultimate_oscillator -#' @templateVar .family Momentum Indicator -#' @templateVar .formula ~ high + low + close +#' @templateVar .family Momentum Indicators +#' @templateVar .formula ~high + low + close #' ## splice:documentation:start ## splice:documentation:end #' #' @template description +#' @param firstPeriod ([integer]). Number of bars for 1st period. Defaults to `7`. +#' @param secondPeriod ([integer]). Number of bars for 2nd period. Defaults to `14`. +#' @param thirdPeriod ([integer]). Number of bars for 3rd period. Defaults to `28`. #' @template returns ultimate_oscillator <- function( x, cols, - n = c(7, 14, 28), + firstPeriod = 7, + secondPeriod = 14, + thirdPeriod = 28, na.bridge = FALSE, ... ) { @@ -30,6 +35,13 @@ ultimate_oscillator <- function( #' @aliases ultimate_oscillator ULTOSC <- ultimate_oscillator +#' @export +#' @usage NULL +#' @rdname ultimate_oscillator +#' +#' @aliases ultimate_oscillator +ultimateOscillator <- ultimate_oscillator + #' @usage NULL #' @aliases ultimate_oscillator #' @@ -37,7 +49,9 @@ ULTOSC <- ultimate_oscillator ultimate_oscillator.default <- function( x, cols, - n = c(7, 14, 28), + firstPeriod = 7, + secondPeriod = 14, + thirdPeriod = 28, na.bridge = FALSE, ... ) { @@ -64,14 +78,12 @@ ultimate_oscillator.default <- function( ## return as data.frame x <- .Call( C_impl_ta_ULTOSC, - ## splice:call:start constructed_series[[1]], constructed_series[[2]], constructed_series[[3]], - as.integer(n[1]), - as.integer(n[2]), - as.integer(n[3]), - ## splice:call:end + as.integer(firstPeriod), + as.integer(secondPeriod), + as.integer(thirdPeriod), as.logical(na.bridge) ) @@ -89,7 +101,9 @@ ultimate_oscillator.default <- function( ultimate_oscillator.data.frame <- function( x, cols, - n = c(7, 14, 28), + firstPeriod = 7, + secondPeriod = 14, + thirdPeriod = 28, na.bridge = FALSE, ... ) { @@ -97,7 +111,9 @@ ultimate_oscillator.data.frame <- function( ultimate_oscillator.default( x = x, cols = cols, - n = n, + firstPeriod = firstPeriod, + secondPeriod = secondPeriod, + thirdPeriod = thirdPeriod, na.bridge = na.bridge, ... ) @@ -111,19 +127,40 @@ ultimate_oscillator.data.frame <- function( ultimate_oscillator.matrix <- function( x, cols, - n = c(7, 14, 28), + firstPeriod = 7, + secondPeriod = 14, + thirdPeriod = 28, na.bridge = FALSE, ... ) { ultimate_oscillator.default( x = x, cols = cols, - n = n, + firstPeriod = firstPeriod, + secondPeriod = secondPeriod, + thirdPeriod = thirdPeriod, na.bridge = na.bridge, ... ) } +#' @usage NULL +ULTOSC_lookback <- ultimateOscillator_lookback <- ultimate_oscillator_lookback <- function( + x, + cols, + firstPeriod = 7, + secondPeriod = 14, + thirdPeriod = 28, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_ULTOSC_lookback, + as.integer(firstPeriod), + as.integer(secondPeriod), + as.integer(thirdPeriod) + ) +} #' @usage NULL #' @aliases ultimate_oscillator @@ -132,7 +169,9 @@ ultimate_oscillator.matrix <- function( ultimate_oscillator.plotly <- function( x, cols, - n = c(7, 14, 28), + firstPeriod = 7, + secondPeriod = 14, + thirdPeriod = 28, na.bridge = FALSE, ## splice:optional-plotly:start lower_bound = 30, @@ -167,7 +206,9 @@ ultimate_oscillator.plotly <- function( cols = rebuild_formula( names(constructed_series) ), - n = n, + firstPeriod = firstPeriod, + secondPeriod = secondPeriod, + thirdPeriod = thirdPeriod, na.bridge = TRUE ) @@ -186,9 +227,9 @@ ultimate_oscillator.plotly <- function( ## splice:plotly-assembly:start name <- sprintf( "UltOsc(%d, %d, %d)", - n[1], - n[2], - n[3] + firstPeriod, + secondPeriod, + thirdPeriod ) decorators <- list( @@ -222,7 +263,8 @@ ultimate_oscillator.plotly <- function( } ), data = constructed_indicator[, values_to_extract, drop = FALSE], - values_to_extract = values_to_extract + values_to_extract = values_to_extract, + name = get0(x = "name", ifnotfound = NULL) ) state <- .chart_state() @@ -238,11 +280,13 @@ ultimate_oscillator.plotly <- function( ultimate_oscillator.ggplot <- function( x, cols, - n = c(7, 14, 28), + firstPeriod = 7, + secondPeriod = 14, + thirdPeriod = 28, na.bridge = FALSE, + title, ## splice:optional-ggplot:start ## splice:optional-ggplot:end - title, ... ) { ## check ggplot2 availability @@ -270,7 +314,9 @@ ultimate_oscillator.ggplot <- function( cols = rebuild_formula( names(constructed_series) ), - n = n, + firstPeriod = firstPeriod, + secondPeriod = secondPeriod, + thirdPeriod = thirdPeriod, na.bridge = TRUE ) @@ -291,7 +337,12 @@ ultimate_oscillator.ggplot <- function( setdiff(colnames(constructed_indicator), "idx"), function(col) list(y = col) ) - name <- sprintf("UltOsc(%d, %d, %d)", n[1], n[2], n[3]) + name <- sprintf( + "UltOsc(%d, %d, %d)", + firstPeriod, + secondPeriod, + thirdPeriod + ) ## splice:ggplot-assembly:end ggplot_object <- add_last_value_gg( diff --git a/R/ta_VAR.R b/R/ta_VAR.R index 092542f11..43d77c849 100644 --- a/R/ta_VAR.R +++ b/R/ta_VAR.R @@ -1,22 +1,23 @@ #' @export -#' @family Rolling Statistic +#' @family Rolling Statistics #' -#' @title Rolling Standard Deviation -#' @templateVar .title Rolling Standard Deviation +#' @title Variance +#' @templateVar .title Variance #' @templateVar .author Serkan Korkmaz #' @templateVar .fun rolling_variance #' ## splice:documentation:start -#' @param k multiplier ## splice:documentation:end #' #' @template rolling_description +#' @param deviations ([double]). Number of deviations. Defaults to `1`. #' @template rolling_returns rolling_variance <- function( x, - n = 5, - k = 1, - na.bridge = FALSE + timePeriod = 5, + deviations = 1, + na.bridge = FALSE, + ... ) { UseMethod("rolling_variance") } @@ -28,15 +29,23 @@ rolling_variance <- function( #' @aliases rolling_variance VAR <- rolling_variance +#' @export +#' @usage NULL +#' @rdname rolling_variance +#' +#' @aliases rolling_variance +rollingVariance <- rolling_variance + #' @usage NULL #' @aliases rolling_variance #' #' @export rolling_variance.default <- function( x, - n = 5, - k = 1, - na.bridge = FALSE + timePeriod = 5, + deviations = 1, + na.bridge = FALSE, + ... ) { ## calculate indicator and ## return as data.frame @@ -44,14 +53,19 @@ rolling_variance.default <- function( C_impl_ta_VAR, ## splice:call:start as.double(x), - as.integer(n), - as.double(k), + as.integer(timePeriod), + as.double(deviations), ## splice:call:end as.logical(na.bridge) ) + ## strip dimensions + ## while preserving + ## attributes + dim(x) <- NULL + ## return indicator - as.double(x) + x } #' @usage NULL @@ -60,19 +74,40 @@ rolling_variance.default <- function( #' @export rolling_variance.numeric <- function( x, - n = 5, - k = 1, - na.bridge = FALSE + timePeriod = 5, + deviations = 1, + na.bridge = FALSE, + ... ) { ## calculate indicator and ## return as data.frame x <- rolling_variance.default( x = x, - n = n, - k = k, + timePeriod = timePeriod, + deviations = deviations, na.bridge = na.bridge ) + ## strip dimensions + ## while preserving + ## attributes + dim(x) <- NULL + ## return indicator - as.double(x) + x +} + +#' @usage NULL +VAR_lookback <- rollingVariance_lookback <- rolling_variance_lookback <- function( + x, + timePeriod = 5, + deviations = 1, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_VAR_lookback, + as.integer(timePeriod), + as.double(deviations) + ) } diff --git a/R/ta_VOLUME.R b/R/ta_VOLUME.R index 11e587d66..89da85349 100644 --- a/R/ta_VOLUME.R +++ b/R/ta_VOLUME.R @@ -1,5 +1,5 @@ #' @export -#' @family Volume Indicator +#' @family Volume Indicators #' #' @title Trading Volume #' @templateVar .title Trading Volume @@ -9,7 +9,7 @@ #' @templateVar .formula ~volume + open + close #' ## splice:documentation:start -#' @param ma A list of MA specifications. +#' @param maType A [list] of maType specifications on the form SMA(timePeriod = 7). ## splice:documentation:end #' #' @template description @@ -17,7 +17,7 @@ trading_volume <- function( x, cols, - ma = list(SMA(n = 7), SMA(n = 15)), + maType = list(SMA(timePeriod = 7), SMA(timePeriod = 15)), na.bridge = FALSE, ... ) { @@ -31,6 +31,13 @@ trading_volume <- function( #' @aliases trading_volume VOLUME <- trading_volume +#' @export +#' @usage NULL +#' @rdname trading_volume +#' +#' @aliases trading_volume +tradingVolume <- trading_volume + #' @usage NULL #' @aliases trading_volume #' @@ -38,7 +45,7 @@ VOLUME <- trading_volume trading_volume.default <- function( x, cols, - ma = list(SMA(n = 7), SMA(n = 15)), + maType = list(SMA(timePeriod = 7), SMA(timePeriod = 15)), na.bridge = FALSE, ... ) { @@ -68,10 +75,10 @@ trading_volume.default <- function( ## splice:call:start as.double(constructed_series[[1]]), lapply( - ma, + maType, function(x) { as.integer( - unlist(x, use.names = FALSE) + x ) } ), @@ -93,7 +100,7 @@ trading_volume.default <- function( trading_volume.data.frame <- function( x, cols, - ma = list(SMA(n = 7), SMA(n = 15)), + maType = list(SMA(timePeriod = 7), SMA(timePeriod = 15)), na.bridge = FALSE, ... ) { @@ -101,7 +108,7 @@ trading_volume.data.frame <- function( trading_volume.default( x = x, cols = cols, - ma = ma, + maType = maType, na.bridge = na.bridge, ... ) @@ -115,14 +122,14 @@ trading_volume.data.frame <- function( trading_volume.matrix <- function( x, cols, - ma = list(SMA(n = 7), SMA(n = 15)), + maType = list(SMA(timePeriod = 7), SMA(timePeriod = 15)), na.bridge = FALSE, ... ) { trading_volume.default( x = x, cols = cols, - ma = ma, + maType = maType, na.bridge = na.bridge, ... ) @@ -136,7 +143,7 @@ trading_volume.matrix <- function( trading_volume.numeric <- function( x, cols, - ma = list(SMA(n = 7), SMA(n = 15)), + maType = list(SMA(timePeriod = 7), SMA(timePeriod = 15)), na.bridge = FALSE, ... ) { @@ -154,21 +161,13 @@ trading_volume.numeric <- function( C_impl_ta_VOLUME, ## splice:numeric:start as.double(x), - ma, + maType, ## splice:numeric:end 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 @@ -182,7 +181,7 @@ trading_volume.numeric <- function( trading_volume.plotly <- function( x, cols, - ma = list(SMA(n = 7), SMA(n = 15)), + maType = list(SMA(timePeriod = 7), SMA(timePeriod = 15)), na.bridge = FALSE, ## splice:optional-plotly:start ## splice:optional-plotly:end @@ -215,7 +214,7 @@ trading_volume.plotly <- function( cols = rebuild_formula( names(constructed_series) ), - ma = ma, + maType = maType, na.bridge = TRUE ) @@ -274,7 +273,7 @@ trading_volume.plotly <- function( ## modify the first trace ## assuming its volume traces[[1]]$color <- ~direction - traces[[1]]$colors = c( + traces[[1]]$colors <- c( .chart_variables$bullish_body, .chart_variables$bearish_body ) @@ -319,7 +318,7 @@ trading_volume.plotly <- function( trading_volume.ggplot <- function( x, cols, - ma = list(SMA(n = 7), SMA(n = 15)), + maType = list(SMA(timePeriod = 7), SMA(timePeriod = 15)), na.bridge = FALSE, ## splice:optional-ggplot:start ## splice:optional-ggplot:end @@ -351,7 +350,7 @@ trading_volume.ggplot <- function( cols = rebuild_formula( names(constructed_series) ), - ma = ma, + maType = maType, na.bridge = TRUE ) @@ -378,7 +377,7 @@ trading_volume.ggplot <- function( list( y = trace_cols[1], geom = "bar", - direction = "direction" + directiotimePeriod = "direction" ) ) if (length(trace_cols) > 1L) { diff --git a/R/ta_WCLPRICE.R b/R/ta_WCLPRICE.R index f0e20bbfe..22243ef6f 100644 --- a/R/ta_WCLPRICE.R +++ b/R/ta_WCLPRICE.R @@ -12,6 +12,7 @@ ## splice:documentation:end #' #' @template description +#' #' @template returns weighted_close_price <- function( x, @@ -29,6 +30,13 @@ weighted_close_price <- function( #' @aliases weighted_close_price WCLPRICE <- weighted_close_price +#' @export +#' @usage NULL +#' @rdname weighted_close_price +#' +#' @aliases weighted_close_price +weightedClosePrice <- weighted_close_price + #' @usage NULL #' @aliases weighted_close_price #' @@ -62,11 +70,9 @@ weighted_close_price.default <- function( ## return as data.frame x <- .Call( C_impl_ta_WCLPRICE, - ## splice:call:start constructed_series[[1]], constructed_series[[2]], constructed_series[[3]], - ## splice:call:end as.logical(na.bridge) ) @@ -114,3 +120,15 @@ weighted_close_price.matrix <- function( ... ) } + +#' @usage NULL +WCLPRICE_lookback <- weightedClosePrice_lookback <- weighted_close_price_lookback <- function( + x, + cols, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_WCLPRICE_lookback + ) +} diff --git a/R/ta_WILLR.R b/R/ta_WILLR.R index 21c0a78de..9e667108c 100644 --- a/R/ta_WILLR.R +++ b/R/ta_WILLR.R @@ -1,22 +1,23 @@ #' @export -#' @family Momentum Indicator +#' @family Momentum Indicators #' -#' @title Williams %R -#' @templateVar .title Williams %R +#' @title Williams' %R +#' @templateVar .title Williams' %R #' @templateVar .author Serkan Korkmaz #' @templateVar .fun williams_oscillator -#' @templateVar .family Momentum Indicator -#' @templateVar .formula ~ high + low + close +#' @templateVar .family Momentum Indicators +#' @templateVar .formula ~high + low + close #' ## splice:documentation:start ## splice:documentation:end #' #' @template description +#' #' @template returns williams_oscillator <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -30,6 +31,13 @@ williams_oscillator <- function( #' @aliases williams_oscillator WILLR <- williams_oscillator +#' @export +#' @usage NULL +#' @rdname williams_oscillator +#' +#' @aliases williams_oscillator +williamsOscillator <- williams_oscillator + #' @usage NULL #' @aliases williams_oscillator #' @@ -37,7 +45,7 @@ WILLR <- williams_oscillator williams_oscillator.default <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -64,12 +72,10 @@ williams_oscillator.default <- function( ## return as data.frame x <- .Call( C_impl_ta_WILLR, - ## splice:call:start constructed_series[[1]], constructed_series[[2]], constructed_series[[3]], - as.integer(n), - ## splice:call:end + as.integer(timePeriod), as.logical(na.bridge) ) @@ -87,7 +93,7 @@ williams_oscillator.default <- function( williams_oscillator.data.frame <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { @@ -95,7 +101,7 @@ williams_oscillator.data.frame <- function( williams_oscillator.default( x = x, cols = cols, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge, ... ) @@ -109,19 +115,32 @@ williams_oscillator.data.frame <- function( williams_oscillator.matrix <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ... ) { williams_oscillator.default( x = x, cols = cols, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge, ... ) } +#' @usage NULL +WILLR_lookback <- williamsOscillator_lookback <- williams_oscillator_lookback <- function( + x, + cols, + timePeriod = 14, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_WILLR_lookback, + as.integer(timePeriod) + ) +} #' @usage NULL #' @aliases williams_oscillator @@ -130,7 +149,7 @@ williams_oscillator.matrix <- function( williams_oscillator.plotly <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, ## splice:optional-plotly:start lower_bound = -20, @@ -165,7 +184,7 @@ williams_oscillator.plotly <- function( cols = rebuild_formula( names(constructed_series) ), - n = n, + timePeriod = timePeriod, na.bridge = TRUE ) @@ -182,7 +201,7 @@ williams_oscillator.plotly <- function( ## construct {plotly}-object ## splice:plotly-assembly:start - name <- paste0("Will %R(", n, ")") + name <- paste0("Will %R(", timePeriod, ")") decorators <- list( function(p) add_limit_ly(p, y_range = c(0, -100)) @@ -209,13 +228,14 @@ williams_oscillator.plotly <- function( ), data = constructed_indicator, title = if (missing(title)) { - "Williams %R" + "Williams' %R" } else { title } ), data = constructed_indicator[, values_to_extract, drop = FALSE], - values_to_extract = values_to_extract + values_to_extract = values_to_extract, + name = get0(x = "name", ifnotfound = NULL) ) state <- .chart_state() @@ -231,11 +251,11 @@ williams_oscillator.plotly <- function( williams_oscillator.ggplot <- function( x, cols, - n = 14, + timePeriod = 14, na.bridge = FALSE, + title, ## splice:optional-ggplot:start ## splice:optional-ggplot:end - title, ... ) { ## check ggplot2 availability @@ -263,7 +283,7 @@ williams_oscillator.ggplot <- function( cols = rebuild_formula( names(constructed_series) ), - n = n, + timePeriod = timePeriod, na.bridge = TRUE ) @@ -288,7 +308,7 @@ williams_oscillator.ggplot <- function( ggplot_line(-80), list(y = "WILLR") ) - name <- sprintf("Will %%R(%d)", n) + name <- sprintf("Will %%R(%d)", timePeriod) ## splice:ggplot-assembly:end ggplot_object <- add_last_value_gg( @@ -305,7 +325,7 @@ williams_oscillator.ggplot <- function( ), data = constructed_indicator, title = if (missing(title)) { - "Williams %R" + "Williams' %R" } else { title } diff --git a/R/ta_WMA.R b/R/ta_WMA.R index e6fcc602a..50b8d38ba 100644 --- a/R/ta_WMA.R +++ b/R/ta_WMA.R @@ -1,11 +1,11 @@ #' @export -#' @family Overlap Study +#' @family Overlap Studies #' #' @title Weighted Moving Average #' @templateVar .title Weighted Moving Average #' @templateVar .author Serkan Korkmaz #' @templateVar .fun weighted_moving_average -#' @templateVar .family Overlap Study +#' @templateVar .family Overlap Studies #' @templateVar .formula ~close #' ## splice:documentation:start @@ -18,11 +18,12 @@ #' indicators that supports various Moving Average specifications. #' #' @template description +#' #' @template returns weighted_moving_average <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, ... ) { @@ -33,13 +34,19 @@ weighted_moving_average <- function( ## from call x <- structure( list( - n = if (missing(n)) 30L else as.integer(n), + timePeriod = if (missing(timePeriod)) { + 30L + } else { + as.integer(timePeriod) + }, maType = 2L - ) + ), + class = "maType" ) return(x) } + UseMethod("weighted_moving_average") } @@ -50,6 +57,13 @@ weighted_moving_average <- function( #' @aliases weighted_moving_average WMA <- weighted_moving_average +#' @export +#' @usage NULL +#' @rdname weighted_moving_average +#' +#' @aliases weighted_moving_average +weightedMovingAverage <- weighted_moving_average + #' @usage NULL #' @aliases weighted_moving_average #' @@ -57,7 +71,7 @@ WMA <- weighted_moving_average weighted_moving_average.default <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, ... ) { @@ -84,8 +98,8 @@ weighted_moving_average.default <- function( ## return as data.frame x <- .Call( C_impl_ta_WMA, - as.double(constructed_series[[1]]), - as.integer(n), + constructed_series[[1]], + as.integer(timePeriod), as.logical(na.bridge) ) @@ -103,12 +117,18 @@ weighted_moving_average.default <- function( weighted_moving_average.data.frame <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, ... ) { map_dfr( - NextMethod() + weighted_moving_average.default( + x = x, + cols = cols, + timePeriod = timePeriod, + na.bridge = na.bridge, + ... + ) ) } @@ -119,17 +139,14 @@ weighted_moving_average.data.frame <- function( weighted_moving_average.matrix <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, ... ) { - ## pass directly to - ## weighted_moving_average.default to avoid - ## shenanigans with NextMethod() weighted_moving_average.default( x = x, cols = cols, - n = n, + timePeriod = timePeriod, na.bridge = na.bridge, ... ) @@ -142,7 +159,7 @@ weighted_moving_average.matrix <- function( weighted_moving_average.numeric <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, ... ) { @@ -159,25 +176,32 @@ weighted_moving_average.numeric <- function( x <- .Call( C_impl_ta_WMA, as.double(x), - as.integer(n), + as.integer(timePeriod), 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 <- weightedMovingAverage_lookback <- weighted_moving_average_lookback <- function( + x, + cols, + timePeriod = 30, + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_WMA_lookback, + as.integer(timePeriod) + ) +} + + #' @usage NULL #' @aliases weighted_moving_average #' @@ -185,7 +209,7 @@ weighted_moving_average.numeric <- function( weighted_moving_average.plotly <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, ... ) { @@ -215,7 +239,8 @@ weighted_moving_average.plotly <- function( cols = rebuild_formula( names(constructed_series) ), - n = n + timePeriod = timePeriod, + na.bridge = TRUE ) ## add conditional idx @@ -238,15 +263,15 @@ weighted_moving_average.plotly <- function( ) ) ), - name = label("WMA", n), - decorators = list() + name = label("WMA", timePeriod), + decorators = list(), + data = constructed_indicator ) state[["main"]] <- plotly_object plotly_object } - #' @usage NULL #' @aliases weighted_moving_average #' @@ -254,7 +279,7 @@ weighted_moving_average.plotly <- function( weighted_moving_average.ggplot <- function( x, cols, - n = 30, + timePeriod = 30, na.bridge = FALSE, ... ) { @@ -283,7 +308,8 @@ weighted_moving_average.ggplot <- function( cols = rebuild_formula( names(constructed_series) ), - n = n + timePeriod = timePeriod, + na.bridge = TRUE ) ## add conditional idx @@ -300,7 +326,7 @@ weighted_moving_average.ggplot <- function( y = "WMA" ) ), - name = label("WMA", n), + name = label("WMA", timePeriod), decorators = list(), data = constructed_indicator ) diff --git a/R/utils.R b/R/utils.R index d31333a58..d34714723 100644 --- a/R/utils.R +++ b/R/utils.R @@ -362,3 +362,42 @@ map_dfr.integer <- function(x) { x } + +mapMaType <- function(x) { + switch( + as.character(x + 1), + `1` = "SMA", + `2` = "EMA", + `3` = "WMA", + `4` = "DEMA", + `5` = "TEMA", + `6` = "TRIMA", + `7` = "KAMA", + `8` = "MAMA", + `9` = "T3", + "Unkown" + ) +} + +## maType +## +## Description: +## A small S3 that helps mapping +## maTypes to and +## +as.maType <- function(x, ...) { + UseMethod("as.maType") +} + +#' @export +as.maType.maType <- function(x, ...) { + as.integer(x$maType) +} + +#' @export +as.maType.double <- function(x, ...) { + as.integer(x) +} + +#' @export +as.maType.integer <- as.maType.double diff --git a/R/zzz.R b/R/zzz.R index 8e81e80f6..8cd72e4a3 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -149,7 +149,7 @@ ) { ## reset candles on ## unload - .Call(C_reset_candle_setting) + .Call(C_reset_candle_setting, NULL) ## shutdown TA-Lib ## on unload diff --git a/README.md b/README.md index b2b2428b5..0424b2a46 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 talib website @@ -16,224 +16,249 @@ 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 -100 +#> 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 -100 +#> 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" + ) + + ## add Bollinger Bands to + ## the existing chart + talib::indicator( + talib::BBANDS + ) + + ## add Simple Moving Averages (SMA) + ## to the chart in a loop + for (timePeriod in seq(5, 15, by = 3)) { + talib::indicator( + talib::SMA, + timePeriod = timePeriod + ) + } + + ## similar subchart indicators + ## like the Relative Strength Index + ## can be grouped to avoid repeated + ## subpanels + talib::indicator( + talib::RSI(timePeriod = 10), + talib::RSI(timePeriod = 14), + talib::RSI(timePeriod = 21) + ) - ## pass multiple calls to combine - ## them on a single sub-panel + ## identify Doji patterns + ## and add them to the chart talib::indicator( - talib::RSI(n = 10), - talib::RSI(n = 14), - talib::RSI(n = 21) + talib::doji ) } ``` - +![](man/figures/README-charting-example-1.png) -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: +## Implementation: {talib} vs upstream (TA-Lib Core) -``` 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) -} -``` +Functions use descriptive snake_case names; each is aliased to its +[TA-Lib](https://github.com/TA-Lib/ta-lib) shorthand for compatibility +with the broader ecosystem, and to a camelCase name for consistency +across R’s finance ecosystem: - +
-## Column selection +| Category | TA-Lib (C) | {talib} | {talib} alias | {talib} camelCase alias | +|:---|:---|:---|:---|:---| +| Overlap Studies | `TA_BBANDS()` | `bollinger_bands()` | `BBANDS()` | `bollingerBands()` | +| Momentum Indicators | `TA_CCI()` | `commodity_channel_index()` | `CCI()` | `commodityChannelIndex()` | +| Volume Indicators | `TA_OBV()` | `on_balance_volume()` | `OBV()` | `onBalanceVolume()` | +| Volatility Indicators | `TA_ATR()` | `average_true_range()` | `ATR()` | `averageTrueRange()` | +| Price Transform | `TA_AVGPRICE()` | `average_price()` | `AVGPRICE()` | `averagePrice()` | +| Cycle Indicators | `TA_HT_SINE()` | `sine_wave()` | `HT_SINE()` | `sineWave()` | +| Pattern Recognition | `TA_CDLHANGINGMAN()` | `hanging_man()` | `CDLHANGINGMAN()` | `hangingMan()` | -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) +### Interface: R vs Python -## remap hi, lo, last to high, low, close -talib::stochastic(x, cols = ~ hi + lo + last) -``` +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. -## Naming +In Python, each series is passed independently: -Functions use descriptive snake_case names, but every function is -aliased to its TA-Lib shorthand for compatibility with the broader -ecosystem: +``` python +import numpy as np +import talib -
+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) -| Category | TA-Lib (C) | {talib} | {talib} alias | -|:----------------------|:---------------------|:----------------------------|:------------------| -| Overlap Studies | `TA_BBANDS()` | `bollinger_bands()` | `BBANDS()` | -| Momentum Indicators | `TA_CCI()` | `commodity_channel_index()` | `CCI()` | -| Volume Indicators | `TA_OBV()` | `on_balance_volume()` | `OBV()` | -| Volatility Indicators | `TA_ATR()` | `average_true_range()` | `ATR()` | -| Price Transform | `TA_AVGPRICE()` | `average_price()` | `AVGPRICE()` | -| Cycle Indicators | `TA_HT_SINE()` | `sine_wave()` | `HT_SINE()` | -| Pattern Recognition | `TA_CDLHANGINGMAN()` | `hanging_man()` | `CDLHANGINGMAN()` | +print( + talib.CDLDOJI(o, h, l, c) +) +``` -
+In R the series are passed as a tabular container: ``` r -## snake_case and TA-Lib aliases -## are identical -all.equal( - target = talib::bollinger_bands(BTC), - current = talib::BBANDS(BTC) +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 ) -#> [1] TRUE ``` -## Installation[^1] +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. -Install the release version from CRAN: +## Contributing and cloning -``` r -install.packages("talib") -``` +Contributions are welcome. For non-trivial changes, please open an issue +first to discuss the proposed design, API impact, and testing approach. -Install the development version from GitHub: +This repository vendors [TA-Lib](https://github.com/TA-Lib/ta-lib) as a +Git submodule. Clone the repository with submodules enabled: -``` r -pak::pak("serkor1/ta-lib-R") +``` sh +git clone --recurse-submodules https://github.com/serkor1/ta-lib-R.git +cd ta-lib-R ``` -### Aggressive optimizations +If you already cloned the repository without submodules, initialize them +with: -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 -install.packages( - "talib", - type = "source", - configure.args = "-O3 -march=native" -) +``` sh +git submodule update --init --recursive ``` -Or from a local clone: +Most indicator wrappers, helper functions, documentation fragments, and +unit tests are generated from the scripts in `codegen/`. The charting +interface is maintained separately. -``` shell -git clone --recursive https://github.com/serkor1/ta-lib-R.git -cd ta-lib-R -R CMD INSTALL . --configure-args="-O3 -march=native" +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 +266,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..fbcda687d 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -13,8 +13,8 @@ template: light-switch: yes opengraph: image: - src: man/figures/logo.png - alt: "talib R package logo" + src: man/figures/social-preview.png + alt: "Candlestick chart with two moving averages in the talib color palette" bslib: primary: '#0054AD' border-radius: 0.5rem @@ -34,31 +34,31 @@ reference: Measure the speed and strength of price movements. Includes oscillators and rate-of-change indicators such as RSI, MACD, Stochastic, CCI, Williams %R, and ADX. -- contents: has_concept('Momentum Indicator') +- contents: has_concept('Momentum Indicators') - title: Overlap Studies desc: > Indicators plotted directly on the price chart. Moving averages (SMA, EMA, WMA, DEMA, TEMA, KAMA), Bollinger Bands, Parabolic SAR, and other trend-following overlays. -- contents: has_concept('Overlap Study') +- contents: has_concept('Overlap Studies') - title: Cycle Indicators desc: > Detect dominant market cycles in price data using Hilbert Transform methods. Estimate cycle period, phase, and the in-phase / quadrature components of the analytic signal. -- contents: has_concept('Cycle Indicator') +- contents: has_concept('Cycle Indicators') - title: Volume Indicators desc: > Analyze trading volume to confirm price trends and spot divergences. Includes On-Balance Volume (OBV), Chaikin A/D Line, and A/D Oscillator. -- contents: has_concept('Volume Indicator') +- contents: has_concept('Volume Indicators') - title: Volatility Indicators desc: > Quantify the degree of price variation over a given period. Includes Average True Range (ATR), Normalized ATR (NATR), and True Range (TRANGE). -- contents: has_concept('Volatility Indicator') +- contents: has_concept('Volatility Indicators') - title: Financial Charts desc: > Build interactive candlestick and OHLC charts with plotly. Layer @@ -70,12 +70,17 @@ reference: Compute rolling (moving-window) descriptive statistics over price or return series. Includes rolling variance, standard deviation, linear regression, and time series forecast. -- contents: has_concept('Rolling Statistic') +- contents: has_concept('Rolling Statistics') - title: Price Transformations desc: > 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/.gitignore b/codegen/.gitignore new file mode 100644 index 000000000..2f7896d1d --- /dev/null +++ b/codegen/.gitignore @@ -0,0 +1 @@ +target/ diff --git a/codegen/Cargo.lock b/codegen/Cargo.lock new file mode 100644 index 000000000..0dc6da228 --- /dev/null +++ b/codegen/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "codegen" +version = "0.1.0" diff --git a/codegen/Cargo.toml b/codegen/Cargo.toml new file mode 100644 index 000000000..c7f0c6dc0 --- /dev/null +++ b/codegen/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "codegen" +description = "A parser for TA-Lib" +version = "0.1.0" +edition = "2024" + +[dependencies] diff --git a/codegen/README.md b/codegen/README.md index 65ac9befe..5d28efd5c 100644 --- a/codegen/README.md +++ b/codegen/README.md @@ -1,267 +1,330 @@ # codegen/ — Code Generation System -This directory contains the meta-programming infrastructure that generates -most of the R wrappers, C wrappers, and unit tests in the package. If you are -reading this because something broke, start at [Quick reference](#quick-reference) +This directory contains the Rust crate that generates most of the R wrappers, +the C binding header, and the unit tests in the package. If you are reading +this because something broke, start at [Quick reference](#quick-reference) and work backwards. ## Quick reference ``` -make gen-code # regenerate R/, src/ta_*.c, and tests/ from metadata -make build # also runs generate_API.sh + generate_FFI.sh -make fmt # format everything (air for R, clang-format for C) +make gen-code # cargo run: regenerate src/TA-Lib.h, R/ta_*.R, tests/ — then make fmt +make build # document + build + install the package +cargo test # unit tests of the generator itself (run from codegen/) ``` +The crate has **zero dependencies** and is driven entirely by three files +from the TA-Lib submodule: + +- `src/ta-lib/ta_func_api.xml` — machine-generated metadata for every + TA-Lib function (names, groups, inputs, optional inputs, outputs) +- `src/ta-lib/include/ta_func.h` + `src/ta-lib/ta_func_list.txt` — the C + prototypes, mined for the binding header + ## How the pieces fit together ``` -indicators.R All 128 indicator definitions (one list) - | - v -generate.R Loops over indicators, calls: - | - +---> utils.R impl_generate_indicator() - | | - | +---> generate_indicator.sh (envsubst on R templates) - | - +---> utils.R impl_generate_test() - | | - | +---> generate_unit-tests.sh (heredoc test files) - | - +---> generate_indicator_core.sh (parses ta_func.h, envsubst on C template) - +---> generate_core_candlestick.sh (candlestick-specific C generation) +ta_func_list.txt + ta_func.h ta_func_api.xml + | | + v v + c_header.rs metadata.rs parse_api() -> Vec + | | + v v + src/TA-Lib.h render.rs render_indicator() + (TA_INDICATOR / TA_LOOKBACK | template dispatch + placeholder fill + X-macro lines, expanded by +--> preserve_regions() (splice) + src/wrapper.h and src/init.c) | + v + R/ta_.R + | + testthat.rs render_test() + | + v + tests/testthat/test-ta_.R ``` -After generation, `make fmt` runs `air format` (R) and `clang-format` (C) to -normalize style. +The exclusions in `tables.rs` filter both paths: excluded indicators get +neither a C wrapper nor an R wrapper. After generation, `make fmt` runs +`air format` (R) and `clang-format` (C) to normalize style. ## Directory layout ``` codegen/ - gen_code/ - indicators.R <- THE metadata: every indicator in one place - generate.R <- driver script (make gen-code calls this) - utils.R <- impl_generate_indicator(), impl_generate_test() + src/ + main.rs Driver: writes src/TA-Lib.h, then runs the + R + test generation loop (with splice preservation) + c_header.rs Mines TA_() / TA__Lookback() prototypes + from ta_func.h and renders the X-macro lines + metadata.rs XML mining: parse_api() -> Vec + render.rs The Templates struct, render_indicator(), the + dual-backend chart rendering (render_backend) + and preserve_regions() (splice) + testthat.rs testthat file generation + tables.rs The hand-maintained lookup tables: FUNCTION_NAMES + (BBANDS -> bollinger_bands), CHART_TYPES (Main + overlay vs Sub panel; absent = not chartable), + MOVING_AVERAGES (TA_MAType index, SMA = 0L), + AGNOSTIC_PATTERNS (fills ${AGNOSTIC}) and + EXCLUDED_INDICATORS / EXCLUDED_GROUPS templates/ - indicator_template.R.in Standard R wrapper (most indicators) - indicator_template.c.in Standard C wrapper (most indicators) - candlestick_template.R.in Candlestick pattern R wrapper - candlestick_template.c.in Candlestick pattern C wrapper - moving_average_template.R.in Moving average R wrapper (includes numeric + plotly) - rolling_template.R.in Rolling statistic R wrapper (simplified) - numeric_template.R.in Appended for univariate .numeric method - plotly_main_template.R.in Plotly method — main chart overlay - plotly_subchart_template.R.in Plotly method — subchart panel - ggplot_main_template.R.in ggplot2 method — main chart overlay - ggplot_subchart_template.R.in ggplot2 method — subchart panel - candlestick_ggplot_template.R.in ggplot2 method for candlesticks - moving_average_ggplot_template.R.in ggplot2 method for moving averages - generate_indicator.sh R template assembler (envsubst + splice) - generate_indicator_core.sh C code generator (parses ta_func.h headers) - generate_core_candlestick.sh C code generator for candlestick patterns - generate_unit-tests.sh Test file generator - generate_API.sh Extracts SEXP prototypes → src/api.h - generate_FFI.sh Builds R_CallMethodDef table → src/init.c - validation/ - validate.R Smoke-tests: compares R output vs raw TA-Lib C calls - validate.c Reference C implementations for validation + indicator_template.R Standard R wrapper (most indicators) + numeric_template.R Appended .numeric method (univariate) + rolling_template.R Rolling statistics (Statistic Functions, + .numeric baked in, not plotable) + moving_average_template.R Moving averages (spec-mode, + .numeric baked in) + candlestick_template.R Candlestick patterns + chart_main_template.R Chart methods — main chart overlay + chart_subchart_template.R Chart methods — own subchart panel + chart_moving_average_template.R Chart methods — moving averages + chart_candlestick_template.R Chart methods — candlestick markers + parity/ + btc_to_csv.R, parity_gen.c, csv_to_rds.R, test_parity_template.R + Parity snapshots: R output vs raw TA-Lib C calls + (make parity-prepare; runs in make test / check) ``` -## Adding a new indicator - -1. **Add one line to `gen_code/indicators.R`** using the appropriate - constructor. Pick the constructor that matches the indicator family: - - | Constructor | Family | Notes | - |-----------------|----------------------|---------------------------------| - | `momentum()` | Momentum Indicator | Most common | - | `candlestick()` | Pattern Recognition | OHLC patterns, boolean output | - | `moving_avg()` | Overlap Study | Each MA gets its own `src/ta_.c` | - | `overlap()` | Overlap Study | Non-MA overlays (BBANDS, SAR) | - | `cycle()` | Cycle Indicator | Hilbert transforms | - | `price_xform()` | Price Transform | No charting, no subchart | - | `volume()` | Volume Indicator | | - | `volatility()` | Volatility Indicator | | - | `rolling()` | Rolling Statistic | Simplified template, no NA handling | +Each `chart_*_template.R` is **dual-backend**: one file describes both the +`.plotly` and the `.ggplot` method and is rendered once per backend (see +[Dual-backend chart templates](#dual-backend-chart-templates)). - Example — adding a new momentum indicator: +## The metadata source - ```r - momentum("Awesome Oscillator", "awesome_oscillator", "AO", - "~high + low", c("fast=5", "slow=34")) - ``` +`metadata::parse_api()` mines `ta_func_api.xml` into one `MetaData` per +``: -2. **Run `make gen-code`**. This generates: - - `R/ta_AO.R` — R wrapper with S3 methods - - `src/ta_AO.c` — C wrapper calling TA-Lib - - `tests/testthat/test-ta_AO.R` — unit tests +- **Required inputs** become column names: price types map to their OHLCV + column (`High` -> `high`), plain double arrays (`inReal`) default to + `close`. The deduplicated columns form `${FORMULA}` + (`~high + low + close`). Any other required input (MAVP: `inPeriods` -> + `periods`) is no price series and becomes a *passthrough*: a required + formal without a default, rendered into the `.Call()` arguments as + `as.double()` instead of a formula column. The generated tests + supply passthrough vectors at every call site via the + `${PASS_SPY}`/`${PASS_BTC}`/`${PASS_ATOM}` placeholders. +- **Optional inputs** become camelCase formals (`Fast-K Period` -> + `fastKPeriod`) with their XML defaults; doubles are reformatted from + scientific notation (`2.000000e-2` -> `0.02`). -3. **Check the splice regions** in the generated R file. If the indicator - needs custom `.Call()` arguments (e.g. constructed series columns), edit the - content between `## splice:call:start` and `## splice:call:end`. This - content is preserved across regenerations. +The outputs are not mined from the XML: the C side gets them from the +header prototypes (see [How C generation works](#how-c-generation-works)) +and the R side does not need them. -4. **Run `make build`** to rebuild (also regenerates `api.h` and `init.c`). +The XML is attribute-free and machine-generated, so the crate uses +hand-rolled `tag_blocks()`/`tag_text()` mining instead of an XML library. ## How R wrapper generation works -`generate_indicator.sh` is the core R assembler. It: - -1. **Receives metadata** as environment variables (`FUN`, `TA_FUN`, `FORMULA`, - `ARGS`, `PLOTLY`, `SUBCHART`, `CANDLESTICK`, `maType`, `ROLLING`, etc.) - and function arguments as positional parameters. - -2. **Selects the main template** based on flags: - - `CANDLESTICK=1` → `candlestick_template.R.in` - - `maType != -1` → `moving_average_template.R.in` - - `ROLLING != 0` → `rolling_template.R.in` - - Otherwise → `indicator_template.R.in` - -3. **Runs `envsubst`** to replace `${VAR}` placeholders in the template. - -4. **Appends optional templates** (if the indicator supports them): - - `numeric_template.R.in` — when `NUMERIC=1` (univariate formula) - - `plotly_*_template.R.in` — when `PLOTLY=1` - - `ggplot_*_template.R.in` — for charting support - -5. **Splices preserved content** from the existing output file. Any code - between `## splice:LABEL:start` and `## splice:LABEL:end` markers in the - current file on disk is re-inserted into the freshly generated version. - This is how hand-written `.Call()` arguments and documentation survive - regeneration. - -### Template variables - -The shell script constructs several argument-related variables from the -positional parameters (the `signature` field in the metadata): - -| Variable | Description | Example (`n=10,vfactor=0.7`) | -|-------------------|-----------------------------------------------|------------------------------------------| -| `${ARGS}` | Signature args with trailing comma | `n=10,vfactor=0.7,` | -| `${PARGS}` | Named forwarding: `key=key,` | `,n=n ,vfactor=vfactor ,` | -| `${CARGS}` | Bare names for `.Call()`: `,key` | `,n ,vfactor` | -| `${CARGS_TYPED}` | Type-coerced names (`as.integer`/`as.double`) | `,as.integer(n) ,as.double(vfactor)` | -| `${PPARGS}` | Named forwarding, no trailing comma (plotly) | `,n=n ,vfactor=vfactor` | -| `${SPEC_FIELDS}` | MA spec-mode list fields, one per signature arg | `n = if (missing(n)) 10L else as.integer(n),\n\t\t\t\tvfactor = if (missing(vfactor)) 0.7 else as.double(vfactor)` | - -## How C wrapper generation works - -### Standard indicators — `generate_indicator_core.sh` - -This 420-line bash script: - -1. **Locates `ta_func.h`** in the TA-Lib submodule headers. -2. **Extracts the `TA_(...)` prototype** using awk (skipping `TA__*` variants). -3. **Classifies each parameter** via regex: - - Input arrays (`const double inArray[]`) → `REAL()` extraction - - Input scalars (`int`, `double`, `TA_MAType`) → `INTEGER()[0]` / `REAL()[0]` - - Output arrays (`double outArray[]`) → allocated in output container - - Skip: `startIdx`, `endIdx`, `outBegIdx`, `outNBElement` (TA-Lib internals) -4. **Extracts the lookback function** `TA__Lookback(...)` parameters. -5. **Exports 16+ environment variables** and runs `envsubst` on - `indicator_template.c.in`. -6. **Writes to stdout** — the caller redirects to `src/ta_.c`. - -### Candlestick patterns — `generate_core_candlestick.sh` - -Simpler variant that: -1. Checks if the pattern has an `optInPenetration` parameter. -2. Uses `sed` to convert `{{VAR}}` → `${VAR}` in the candlestick C template. -3. Runs `envsubst` and writes directly to `src/ta_.c`. - -### Moving averages +`render_indicator()` picks the templates per indicator: + +| Condition | Main template | Chart template | +|----------------------------------|-----------------------------|-----------------------------------| +| Abbreviation starts with `CDL` | `candlestick_template.R` | `chart_candlestick_template.R` | +| Listed in `MOVING_AVERAGES` | `moving_average_template.R` | `chart_moving_average_template.R` | +| GroupId `Statistic Functions` | `rolling_template.R` | — (not plotable) | +| Otherwise | `indicator_template.R` | `chart_main_template.R` or `chart_subchart_template.R` for indicators in `CHART_TYPES` | + +The standard path additionally appends `numeric_template.R` for univariate +indicators (a single input series); moving averages and rolling statistics +carry their own `.numeric` method inside their main template. + +The rendered output ends with **`strip_blank_indentation()`** — dropping +whitespace-only lines left behind by empty multi-entry placeholders (e.g. +the gap between `cols,` and `na.bridge` for argument-less indicators), +which `air` does not reformat away; truly empty separator lines are kept. +`main.rs` then applies **`preserve_regions()`** — splicing hand-edited +content from the existing file on disk back into the fresh render (see +[The splice mechanism](#the-splice-mechanism)). + +### Dual-backend chart templates + +Every chart method exists in a `.plotly` and a `.ggplot` variant that share +almost all of their body. Each `chart_*_template.R` therefore describes +both variants in one file; `render_backend()` renders it once per backend +(`.plotly` first). Backend divergences are expressed two ways: + +- **Backend placeholders**, filled per render: + + | Placeholder | plotly | ggplot | Used for | + |-------------|----------|----------|---------------------------------------------------| + | `${METHOD}` | `plotly` | `ggplot` | S3 class, `build_*`/`*_init` helpers, `*_object` locals, splice-region names | + | `${PKG}` | `plotly` | `ggplot2`| the package name in comments | + | `${SUFFIX}` | `ly` | `gg` | helper suffixes (`add_last_value_ly`, `pattern_gg`) | + +- **Conditional lines** for structurally different code: a line starting + with `#plotly#` or `#ggplot#` (column 0) is kept only when rendering + that backend, with the prefix stripped: + + ```r + #plotly# assert_plotly_object(x) + #ggplot# assert_ggplot2() + ``` + + A marker-shaped line that survives filtering (a typo'd prefix, an + unknown backend name) makes the render panic instead of shipping as a + do-nothing R comment. Note the subchart template's optional-formals + splice region is itself backend-conditional (the two backends order + `title` and the region differently), so template lines placed inside + those markers must carry the backend prefix too. + +### Template placeholders + +| Placeholder | Description | Example (BBANDS) | +|---------------------------|----------------------------------------------------|-----------------------------------------| +| `${FUN}` | snake_case R name (via `FUNCTION_NAMES`) | `bollinger_bands` | +| `${ALIAS}` | TA-Lib abbreviation (uppercase alias, C symbol) | `BBANDS` | +| `${CAMEL}` | camelCase alias (derived from `${FUN}`); its `#camel#`-prefixed block is dropped when identical to `${FUN}` (single-word names like `doji`) | `bollingerBands` | +| `${CAMEL_LOOKBACK}` | camelCase link of the chained lookback assignment, trailing `<- `; empty when `${CAMEL}` is not distinct | `bollingerBands_lookback <- ` | +| `${TITLE}` | `` | `Bollinger Bands` | +| `${FAMILY}` | `` | `Overlap Studies` | +| `${FORMULA}` | Default column formula | `~close` | +| `${PARAM_DOCS}` | `@param` roxygen lines for the optional inputs (`timePeriod`/`penetration` excluded — the man-roxygen templates document those; MAType formals carry the TA_MAType → `[SMA]`…`[T3]` legend) | `#' @param fastPeriod ([integer]). Number of period for the fast MA. Defaults to \`12\`. Can also be passed as talib::SMA().` | +| `${ARGS}` | Formals, one per line, trailing comma per entry | `timePeriod = 5,` | +| `${PARGS}` | Named forwarding, trailing comma per entry | `timePeriod = timePeriod,` | +| `${C_SIGNATURE}` | `.Call()` args: series columns + coerced formals | `constructed_series[[1]],\n as.integer(timePeriod), ...` | +| `${C_NUMERIC}` | `.Call()` args of the numeric/rolling path | `as.double(x),\n as.integer(timePeriod), ...` | +| `${C_SIGNATURE_LOOKBACK}` | Lookback `.Call()` args, **leading** comma per entry | `,\n as.integer(timePeriod)` | +| `${SPEC_FIELDS}` | MA spec-mode list fields | `timePeriod = if (missing(timePeriod)) 5L else as.integer(timePeriod)` | +| `${MA_TYPE}` | TA_MAType index literal (MAs only) | `0L` | +| `${CARGS}` | Bare formals for `label()`, leading comma per entry | `, timePeriod` | +| `${AGNOSTIC}` | OHLC-order agnosticism (candlesticks only) | `TRUE` / `FALSE` | + +The comma conventions matter: `${ARGS}`/`${PARGS}` entries carry their own +**trailing** comma so empty renders leave no dangling comma (the leftover +blank line is removed by `strip_blank_indentation()`), while the lookback +entries carry a **leading** comma because the lookback `.Call()` has no +fixed trailing argument to absorb one. + +**MAMA quirk**: moving averages whose C signature has no period get a +spec-only `timePeriod = 30` formal injected — it appears in `${ARGS}`, +`${PARGS}` and `${SPEC_FIELDS}` so every MA spec carries a period for its +downstream consumers, but it is deliberately absent from the `.Call()` +coercions. + +## Customizing an indicator + +Everything is mined from the XML, so new TA-Lib functions appear +automatically on `make gen-code`. The lookup tables in `tables.rs` tune +the result: + +1. **`FUNCTION_NAMES`** — add the `("ABBREV", "snake_case_name")` + pair. Unmapped abbreviations fall back to the abbreviation itself, + which renders a degenerate `X <- X` alias line. +2. **`CHART_TYPES`** — add `("ABBREV", ChartType::Main | Sub)` to give the + indicator `.plotly`/`.ggplot` methods (and chart-method unit tests). +3. **`MOVING_AVERAGES` / `AGNOSTIC_PATTERNS`** — family classification for + the dedicated templates. +4. **`EXCLUDED_INDICATORS` / `EXCLUDED_GROUPS`** — add the abbreviation + (or its GroupId) to skip generation entirely, in both C and R. + +After `make gen-code`, fill the protected regions of the generated file +(documentation, chart assembly) — the content survives every regeneration. + +## How C generation works + +There are no per-indicator `.c` files. `c_header.rs` mines each +`TA_(...)` prototype (and its `TA__Lookback(...)` companion) +from `ta_func.h` — the output names are stripped of their +`out`/`Real`/`Integer` prefixes (`outRealUpperBand` -> `UpperBand`, a bare +`outReal` takes the indicator name) and an integer output array flags the +indicator as `TA_INTEGER` — and renders one X-macro line per indicator +into `src/TA-Lib.h`: + +```c +TA_INDICATOR(BBANDS, TA_DOUBLE, TA_INPUT(inReal), TA_OPTIONS(...), TA_OUTPUT(...), TA_OUTPUT_NAME(...), NOT_CANDLESTICK) +... +TA_LOOKBACK(BBANDS, TA_OPTIONS(...)) +``` -Each MA type (SMA, EMA, WMA, DEMA, TEMA, TRIMA, KAMA, MAMA, T3) uses the -standard `generate_indicator_core.sh` path and gets its own per-function -`src/ta_.c` calling the TA-Lib entry point directly (e.g. `TA_SMA`, -`TA_MAMA`). The `moving_avg()` helper wires per-MA signatures and routes R -wrappers through `moving_average_template.R.in`, which retains the spec-mode -`missing(x)` branch so `SMA(n = 5)` still returns `list(n, maType)` for -downstream consumers (BBANDS, APO, PPO, MACDEXT, STOCH*). +The hand-written `src/init.c` `#include`s `"TA-Lib.h"` several times with +different `TA_INDICATOR`/`TA_LOOKBACK` macro definitions — composed from +the argument-shape helpers in `src/wrapper.h` — to expand declarations, +`impl_ta_` wrapper definitions and the `.Call()` registration table. Candlesticks (`CANDLESTICK` kind) additionally +take a normalization flag that maps the `[-200, 200]` integer output onto +`[-2, 2]`. ## How test generation works -`generate_unit-tests.sh` writes test files using bash heredocs. Two paths: - -- **Rolling statistics** (`ROLLING=1`): 3 quick tests — runs without error, - length preservation, output type. -- **Everything else**: 10+ tests covering alias equivalence, class - preservation (matrix/data.frame), default formula, row names, NA handling, - and optionally plotly/ggplot/numeric methods. - -The `NUMERIC` environment variable controls whether a numeric-method test -block is appended. It is derived from the formula: if the formula references -exactly one column (e.g. `~close`), `NUMERIC=1`. +`testthat.rs` writes `tests/testthat/test-ta_.R` for every +generated indicator (no protected regions — the files are overwritten on +every run). What a file contains follows from the metadata: -## How API registration works (build-time) - -These run during `make build`, not `make gen-code`: - -1. **`generate_API.sh`** scans all `src/*.c` files for `SEXP` function - definitions, extracts their signatures, and writes `src/api.h` - (a header with all C function prototypes). - -2. **`generate_FFI.sh`** reads `api.h`, counts each function's arguments, - and writes `src/init.c` with `R_CallMethodDef` entries so R's `.Call()` - interface can find them. +- **Rolling statistics** (GroupId `Statistic Functions`): a short + fast-track file — runs without condition, length preservation, output + type — on `SPY[,1]`, with `,y=SPY[,2]` appended for the bivariate + BETA/CORREL. +- **Everything else**: alias equivalence, class preservation + (matrix/data.frame), default formula, row names, and `na.bridge` length + checks; plus `.plotly`/`.ggplot` method tests for chartable indicators + (including candlesticks and moving averages, which are always + chartable) and a `.numeric` test for univariate indicators. ## The splice mechanism -The splice mechanism in `generate_indicator.sh` lets you keep hand-written -code inside generated files. Any content between matched markers is preserved -across regenerations: +`preserve_regions()` keeps hand-written code inside generated files. Any +content between matched markers in the file **on disk** replaces the +template's default content in the fresh render: ```r -## splice:call:start -constructed_series[, 1], -constructed_series[, 2], -## splice:call:end +## splice:documentation:start +#' @param timePeriod [integer] rolling window +## splice:documentation:end ``` -The awk script (lines 158-207 of `generate_indicator.sh`) does a two-pass -process: -- **Pass 1**: Read the existing output file and harvest the body of each - labeled splice region. -- **Pass 2**: Write the newly generated template, but when a splice region - is encountered, substitute the harvested content from pass 1 instead of - the template's default content. +It is name-generic: every `## splice::start` / `## splice::end` +pair discovered in the rendered output is preserved, so new region names +added to a template work without generator changes. Regions absent from the +existing file (first generation) keep the template default. -Current splice labels used: -- `documentation` — custom roxygen2 `@param` documentation -- `call` — arguments passed to `.Call()` in the `.default` method -- `numeric` — arguments passed to `.Call()` in the `.numeric` method +Current labels: -**Warning**: If a generation run produces a file without a splice region that -previously existed (e.g. due to a bug removing the numeric method), the -splice content is lost permanently. There is no recovery other than git. +- `documentation` — custom roxygen2 documentation (indicator, MA, rolling) +- `call` — the `.Call()` arguments of the rolling `.default` method + (prefilled with the univariate default; BETA/CORREL hand-add their `y`) +- `optional-plotly` / `optional-ggplot` — extra chart-only formals + (e.g. `lower_bound = 20,` in RSI) +- `plotly-assembly` / `ggplot-assembly` — the per-indicator `name` / + `decorators` / `traces` (or `layers`) construction -## Validation +**Warning**: if a generation run produces a file without a region that +previously existed, the spliced content is lost. There is no recovery +other than git. -`make validate` compiles `validation/validate.c` against the TA-Lib static -library and runs `validation/validate.R`, which compares the package's R -output against direct C calls for a few key indicators (SMA, RSI, BBANDS, ATR). -This catches regressions where the R↔C binding produces different results -than calling TA-Lib directly. +## Parity testing -## Key design decisions +`make parity-prepare` (run by `make test` / `make check`) compiles +`parity/parity_gen.c` against the TA-Lib static library, snapshots raw C +outputs for the BTC dataset, and stages `tests/testthat/test-parity.R` from +`parity/test_parity_template.R`. The testthat run then compares the +package's R output against those snapshots, catching regressions where the +R↔C binding diverges from calling TA-Lib directly. -- **`envsubst` over R templating**: The templates use `${VAR}` substitution - via the system `envsubst` command rather than R-based templating (whisker, - glue, etc.). This keeps templates as plain R/C files that editors can - syntax-highlight, and avoids escaping issues with R string literals. - -- **Bash for C header parsing**: `generate_indicator_core.sh` parses - `ta_func.h` in bash rather than R. This was a pragmatic choice — the regex - classification of C parameter types is direct in bash. The tradeoff is that - the script is hard to modify (420 lines of careful bash regex). - -- **Formatting as a separate step**: Generated code is intentionally not - pretty. `make fmt` (air + clang-format) handles all formatting as a - post-processing step, so templates don't need to worry about indentation. +## Key design decisions -- **Moving averages share one C file**: TA-Lib's `TA_MA()` accepts a - `TA_MAType` enum, so all 9 MA variants call the same C function. The R - wrappers differ (each sets a different `maType` default) but the C wrapper - is shared. +- **Rust, zero dependencies**: the generator is one `cargo run` with no + crates.io footprint. Templates stay plain R files that editors can + syntax-highlight; placeholders are filled with simple string replacement + rather than a templating engine. +- **Hand-rolled XML mining**: `ta_func_api.xml` is machine-generated and + attribute-free, so `tag_blocks()`/`tag_text()` string scanning is + sufficient and keeps the crate dependency-free. +- **The XML is the metadata**: there is no hand-maintained indicator list; + the lookup tables in `tables.rs` (names, chart types, classifications, + exclusions) are small Rust consts layered on top of what the XML + provides. +- **One template per chart method, not per backend**: the `.plotly` and + `.ggplot` variants of a chart method live in one dual-backend template, + so a change to the shared body is made once instead of twice. +- **X-macros over generated C**: one generated header (`src/TA-Lib.h`) + expanded by hand-written macros replaces per-indicator `.c` files, so C + binding logic lives in exactly one place (`src/wrapper.h`). +- **Formatting as a separate step**: generated code is intentionally not + pretty. `make gen-code` ends with `make fmt` (air + clang-format); + the only whitespace the generator itself fixes is the blank-indentation + lines air would leave behind. +- **Generator is unit-tested**: `cargo test` covers the header and XML + mining, the dual-backend line filtering, every template family render + (including the full-API sweep asserting no unreplaced `${` placeholders + and no unstripped backend prefixes), region preservation, and test-file + rendering. diff --git a/codegen/gen_code/generate.R b/codegen/gen_code/generate.R deleted file mode 100644 index 8293a3aea..000000000 --- a/codegen/gen_code/generate.R +++ /dev/null @@ -1,88 +0,0 @@ -## script: Unified code generator -## objective: -## Single entry point that reads indicators.R metadata -## and generates R wrappers, C wrappers, and unit tests -## for every indicator. -## -## usage: -## Rscript ./codegen/gen_code/generate.R - -## 1) load helpers and metadata -source("codegen/gen_code/utils.R") -source("codegen/gen_code/indicators.R") - -## 2) field accessor with defaults -`%||%` <- function(a, b) if (is.null(a)) b else a - -## 3) generate R wrapper -generate_R <- function(x) { - impl_generate_indicator( - title = x$title, - family = x$family, - fun = x$fun, - ta_fun = x$alias, - formula = x$formula, - args = x$signature, - plotly = x$plotly %||% 1L, - subchart = x$subchart %||% 1L, - agnostic = x$agnostic, - candlestick = x$candlestick %||% 0, - maType = x$maType %||% -1, - rolling = x$rolling %||% 0, - univariate = x$univariate, - n_default = x$n_default %||% 30L - ) -} - -## 4) generate C wrapper -generate_C <- function(x) { - type <- x$c_generator %||% "standard" - - if (type == "skip") { - return(invisible(NULL)) - } - - if (type == "candlestick") { - system2( - command = "bash", - args = c( - "codegen/generate_core_candlestick.sh", - shQuote(x$alias), - shQuote(x$signature %||% "") - ) - ) - return(invisible(NULL)) - } - - ## standard - system2( - command = "bash", - args = c( - "codegen/generate_indicator_core.sh", - paste0(x$alias, " > src/ta_", x$alias, ".c") - ) - ) -} - -## 5) generate unit test -generate_test <- function(x) { - test_plotly <- x$test_plotly %||% (x$plotly %||% 1) - - impl_generate_test( - fun = x$fun, - ta_fun = x$alias, - formula = x$formula, - plotly = test_plotly, - rolling = x$rolling %||% 0, - args = x$signature - ) -} - -## 6) run generation for all indicators -for (x in indicators) { - generate_R(x) - generate_C(x) - generate_test(x) -} - -## end script; diff --git a/codegen/gen_code/indicators.R b/codegen/gen_code/indicators.R deleted file mode 100644 index 6e5bd4dbc..000000000 --- a/codegen/gen_code/indicators.R +++ /dev/null @@ -1,309 +0,0 @@ -## Unified indicator metadata -## -## All indicator definitions in one place. -## Each entry feeds into generate.R which calls -## impl_generate_indicator(), impl_generate_test(), -## and the appropriate C generator. -## -## Fields: -## title - Human-readable indicator name -## fun - R function name (snake_case) -## alias - TA-Lib alias / uppercase short name -## family - Category for roxygen2 grouping -## formula - Default column formula (default: "~close") -## signature - Character vector of function arguments (default: NULL = none) -## subchart - 0 = main chart overlay, 1 = subchart (default: 1) -## plotly - Append plotly template to R wrapper? (default: 1) -## test_plotly - Test plotly/ggplot methods? (default: inherits plotly) -## candlestick - Use candlestick template? (default: 0) -## agnostic - OHLC order agnostic? (default: NULL) -## maType - Moving average type index (default: -1 = not MA) -## rolling - Use rolling template? (default: 0) -## univariate - Force univariate numeric method? (default: NULL) -## c_generator - C generation strategy: -## NULL = standard (generate_indicator_core.sh → stdout) -## "candlestick" = generate_core_candlestick.sh -## "skip" = do not generate C - -## ----------------------------------------------------------- -## Constructor helpers — set per-family defaults so each -## entry only specifies what differs. -## ----------------------------------------------------------- - -momentum <- function( - title, fun, alias, formula, signature, - subchart = 1L, c_generator = NULL -) { - list( - title = title, fun = fun, alias = alias, - family = "Momentum Indicator", - formula = formula, signature = signature, - subchart = subchart, c_generator = c_generator - ) -} - -candlestick <- function(title, fun, alias, signature = "", agnostic = FALSE) { - list( - title = title, fun = fun, alias = alias, - family = "Pattern Recognition", - formula = "~open + high + low + close", - signature = signature, - candlestick = 1, plotly = 0, test_plotly = 1, - c_generator = "candlestick", - agnostic = agnostic - ) -} - -moving_avg <- function(title, fun, alias, ma_type, n_default = 30L, signature = NULL) { - if (is.null(signature)) { - signature <- sprintf("n=%d", as.integer(n_default)) - } - list( - title = title, fun = fun, alias = alias, - family = "Overlap Study", - formula = "~close", - maType = ma_type, - n_default = as.integer(n_default), - signature = signature, - plotly = 0, test_plotly = 1, - univariate = 0, # MA template has built-in numeric method - c_generator = NULL - ) -} - -overlap <- function(title, fun, alias, formula, signature, subchart = 0L) { - list( - title = title, fun = fun, alias = alias, - family = "Overlap Study", - formula = formula, signature = signature, - subchart = subchart - ) -} - -cycle <- function(title, fun, alias, subchart = 1L) { - list( - title = title, fun = fun, alias = alias, - family = "Cycle Indicator", - formula = "~close", - subchart = subchart - ) -} - -price_xform <- function(title, fun, alias, formula, signature = NULL) { - list( - title = title, fun = fun, alias = alias, - family = "Price Transform", - formula = formula, signature = signature, - plotly = 0, rolling = 0 - ) -} - -volume <- function( - title, fun, alias, formula, signature = "", - subchart = 1L, univariate = NULL, c_generator = NULL -) { - list( - title = title, fun = fun, alias = alias, - family = "Volume Indicator", - formula = formula, signature = signature, - subchart = subchart, univariate = univariate, - c_generator = c_generator - ) -} - -volatility <- function(title, fun, alias, formula, signature = "", subchart = 1L) { - list( - title = title, fun = fun, alias = alias, - family = "Volatility Indicator", - formula = formula, signature = signature, - subchart = subchart - ) -} - -rolling <- function(title, fun, alias, signature) { - list( - title = title, fun = fun, alias = alias, - family = "Rolling Statistic", - plotly = 0, rolling = 1, - signature = signature - ) -} - - -## ----------------------------------------------------------- -## Indicator metadata -## ----------------------------------------------------------- - -indicators <- list( - - ## ======================== - ## Cycle Indicators - ## ======================== - cycle("Hilbert Transform - Dominant Cycle Period", "dominant_cycle_period", "HT_DCPERIOD"), - cycle("Hilbert Transform - Dominant Cycle Phase", "dominant_cycle_phase", "HT_DCPHASE"), - cycle("Hilbert Transform - Phasor Components", "phasor_components", "HT_PHASOR"), - cycle("Hilbert Transform - SineWave", "sine_wave", "HT_SINE"), - cycle("Hilbert Transform - Trend vs Cycle Mode", "trend_cycle_mode", "HT_TRENDMODE"), - - ## ======================== - ## Candlestick Patterns - ## ======================== - candlestick("Abandoned Baby", "abandoned_baby", "CDLABANDONEDBABY", signature = "eps = 0"), - candlestick("Advance Block", "advance_block", "CDLADVANCEBLOCK"), - candlestick("Belt Hold", "belt_hold", "CDLBELTHOLD"), - candlestick("Break Away", "break_away", "CDLBREAKAWAY"), - candlestick("Closing Marubozu", "closing_marubozu", "CDLCLOSINGMARUBOZU", agnostic = TRUE), - candlestick("Concealing Baby Swallow", "concealing_baby_swallow", "CDLCONCEALBABYSWALL"), - candlestick("Counter Attack", "counter_attack", "CDLCOUNTERATTACK"), - candlestick("Dark Cloud Cover", "dark_cloud_cover", "CDLDARKCLOUDCOVER", signature = "eps = 0"), - candlestick("Doji", "doji", "CDLDOJI", agnostic = TRUE), - candlestick("Doji Star", "doji_star", "CDLDOJISTAR"), - candlestick("Dragonfly Doji", "dragonfly_doji", "CDLDRAGONFLYDOJI"), - candlestick("Engulfing", "engulfing", "CDLENGULFING"), - candlestick("Evening Doji Star", "evening_doji_star", "CDLEVENINGDOJISTAR", signature = "eps = 0"), - candlestick("Up/Down-gap side-by-side white lines", "gaps_side_white", "CDLGAPSIDESIDEWHITE"), - candlestick("Gravestone Doji", "gravestone_doji", "CDLGRAVESTONEDOJI"), - candlestick("Hammer", "hammer", "CDLHAMMER"), - candlestick("Hanging Man", "hanging_man", "CDLHANGINGMAN"), - candlestick("Harami", "harami", "CDLHARAMI"), - candlestick("Harami Cross", "harami_cross", "CDLHARAMICROSS"), - candlestick("High Wave", "high_wave", "CDLHIGHWAVE", agnostic = TRUE), - candlestick("Hikkake", "hikakke", "CDLHIKKAKE"), - candlestick("Hikkake Modified", "hikakke_mod", "CDLHIKKAKEMOD"), - candlestick("Homing Pigeon", "homing_pigeon", "CDLHOMINGPIGEON"), - candlestick("In Neck", "in_neck", "CDLINNECK"), - candlestick("Inverted Hammer", "inverted_hammer", "CDLINVERTEDHAMMER"), - candlestick("Kicking", "kicking", "CDLKICKING"), - candlestick("Kicking Baby Length", "kicking_baby_length", "CDLKICKINGBYLENGTH", agnostic = TRUE), - candlestick("Long Legged Doji", "long_legged_doji", "CDLLONGLEGGEDDOJI", agnostic = TRUE), - candlestick("Long Line", "long_line", "CDLLONGLINE", agnostic = TRUE), - candlestick("Marubozu", "marubozu", "CDLMARUBOZU"), - candlestick("Mat Hold", "mat_hold", "CDLMATHOLD", signature = "eps=0"), - candlestick("Matching Low", "matching_low", "CDLMATCHINGLOW"), - candlestick("Morning Doji Star", "morning_doji_star", "CDLMORNINGDOJISTAR", signature = "eps=0"), - candlestick("Morning Star", "morning_star", "CDLMORNINGSTAR", signature = "eps = 0"), - candlestick("On-Neck", "on_neck", "CDLONNECK"), - candlestick("Piercing", "piercing", "CDLPIERCING", agnostic = TRUE), - candlestick("Rickshaw Man", "rickshaw_man", "CDLRICKSHAWMAN"), - candlestick("Rising/Falling Three Methods", "rise_fall_3_methods", "CDLRISEFALL3METHODS"), - candlestick("Separating Lines", "separating_lines", "CDLSEPARATINGLINES"), - candlestick("Shooting Star", "shooting_star", "CDLSHOOTINGSTAR", agnostic = TRUE), - candlestick("Short Line Candle", "short_line", "CDLSHORTLINE", agnostic = TRUE), - candlestick("Spinning Top", "spinning_top", "CDLSPINNINGTOP"), - candlestick("Stalled Pattern", "stalled_pattern", "CDLSTALLEDPATTERN"), - candlestick("Stick Sandwich", "stick_sandwich", "CDLSTICKSANDWICH"), - candlestick("Takuri", "takuri", "CDLTAKURI"), - candlestick("Tasuki Gap", "tasuki_gap", "CDLTASUKIGAP"), - candlestick("Three Black Crows", "three_black_crows", "CDL3BLACKCROWS"), - candlestick("Identical Three Crows", "three_identical_crows", "CDLIDENTICAL3CROWS"), - candlestick("Three Inside", "three_inside", "CDL3INSIDE"), - candlestick("Three-Line Strike", "three_line_strike", "CDL3LINESTRIKE"), - candlestick("Three Outside", "three_outside", "CDL3OUTSIDE"), - candlestick("Three Stars in the South", "three_stars_in_the_south", "CDL3STARSINSOUTH"), - candlestick("Three White Soldiers", "three_white_soldiers", "CDL3WHITESOLDIERS"), - candlestick("Thrusting", "thrusting", "CDLTHRUSTING"), - candlestick("Tristar", "tristar", "CDLTRISTAR"), - candlestick("Two Crows", "two_crows", "CDL2CROWS"), - candlestick("Unique Three River", "unique_3_river", "CDLUNIQUE3RIVER"), - candlestick("Upside Gap Two Crows", "upside_gap_2_crows", "CDLUPSIDEGAP2CROWS"), - candlestick("Upside/Downside Gap Three Methods", "xside_gap_3_methods", "CDLXSIDEGAP3METHODS"), - candlestick("Ladder Bottom", "ladder_bottom", "CDLLADDERBOTTOM"), - candlestick("Evening Star", "evening_star", "CDLEVENINGSTAR", signature = "eps = 0"), - - ## ======================== - ## Momentum Indicators - ## ======================== - momentum("Aroon", "aroon", "AROON", "~ high + low", c("n=14")), - momentum("Aroon Oscillator", "aroon_oscillator", "AROONOSC", "~ high + low", c("n=14")), - momentum("Chande Momentum Oscillator", "chande_momentum_oscillator", "CMO", "~ close", c("n=14")), - momentum("Commodity Channel Index", "commodity_channel_index", "CCI", "~ high + low + close", c("n=14"), subchart = 0L), - momentum("Fast Stochastic", "fast_stochastic", "STOCHF", "~ high + low + close", c("fastk=5", "fastd=SMA(n=3)")), - momentum("Money Flow Index", "money_flow_index", "MFI", "~ high + low + close + volume", c("n = 14")), - momentum("Moving Average Convergence Divergence", "moving_average_convergence_divergence", "MACD", "~close", c("fast = 12", "slow = 26", "signal = 9")), - momentum("Moving Average Convergence Divergence (Extended)", "extended_moving_average_convergence_divergence", "MACDEXT", "~close", c("fast = SMA(n = 12)", "slow = SMA(n = 26)", "signal = SMA(n = 9)")), - momentum("Moving Average Convergence Divergence (Fixed)", "fixed_moving_average_convergence_divergence", "MACDFIX", "~close", c("signal=9")), - momentum("Relative Strength Index", "relative_strength_index", "RSI", "~close", c("n=14")), - momentum("Stochastic", "stochastic", "STOCH", "~ high + low + close", c("fastk = 5", "slowk = SMA(n = 3)", "slowd = SMA(n = 3)")), - momentum("Stochastic Relative Strength Index", "stochastic_relative_strength_index", "STOCHRSI", "~close", c("n=14", "fastk=5", "fastd=SMA(n=3)")), - momentum("Ultimate Oscillator", "ultimate_oscillator", "ULTOSC", "~ high + low + close", c("n=c(7, 14, 28)")), - momentum("Average Directional Movement Index", "average_directional_movement_index", "ADX", "~ high + low + close", c("n=14")), - momentum("Average Directional Movement Index Rating", "average_directional_movement_index_rating", "ADXR", "~ high + low + close", c("n=14")), - momentum("Balance of Power", "balance_of_power", "BOP", "~ open + high + low + close", c(character(0))), - momentum("Momentum", "momentum", "MOM", "~ close", c("n=10")), - momentum("Williams %R", "williams_oscillator", "WILLR", "~ high + low + close", c("n=14")), - momentum("Percentage Price Oscillator", "percentage_price_oscillator", "PPO", "~close", c("fast=12", "slow=26", "ma=SMA(n=9)")), - momentum("Triple Exponential Average", "triple_exponential_average", "TRIX", "~close", c("n=30")), - momentum("Directional Movement Index", "directional_movement_index", "DX", "~high + low + close", c("n=14")), - momentum("Intraday Movement Index", "intraday_movement_index", "IMI", "~open + close", c("n=14")), - momentum("Minus Directional Indicator", "minus_directional_indicator", "MINUS_DI", "~high + low + close", c("n=14")), - momentum("Minus Directional Movement", "minus_directional_movement", "MINUS_DM", "~high + low", c("n=14")), - momentum("Plus Directional Indicator", "plus_directional_indicator", "PLUS_DI", "~high + low + close", c("n=14")), - momentum("Plus Directional Movement", "plus_directional_movement", "PLUS_DM", "~high + low", c("n=14")), - momentum("Rate of Change", "rate_of_change", "ROC", "~close", c("n=10")), - momentum("Ratio of Change", "ratio_of_change", "ROCR", "~close", c("n=10")), - momentum("Absolute Price Oscillator", "absolute_price_oscillator", "APO", "~close", c("fast=12", "slow=26", "ma=SMA(n=9)")), - - ## ======================== - ## Moving Averages - ## ======================== - moving_avg("Simple Moving Average", "simple_moving_average", "SMA", "0L"), - moving_avg("Exponential Moving Average", "exponential_moving_average", "EMA", "1L"), - moving_avg("Weighted Moving Average", "weighted_moving_average", "WMA", "2L"), - moving_avg("Double Exponential Moving Average", "double_exponential_moving_average", "DEMA", "3L"), - moving_avg("Triple Exponential Moving Average", "triple_exponential_moving_average", "TEMA", "4L"), - moving_avg("Triangular Moving Average", "triangular_moving_average", "TRIMA", "5L"), - moving_avg("Kaufman Adaptive Moving Average", "kaufman_adaptive_moving_average", "KAMA", "6L"), - moving_avg( - "MESA Adaptive Moving Average", "mesa_adaptive_moving_average", "MAMA", "7L", - signature = c("fast=0.5", "slow=0.05") - ), - moving_avg( - "Triple Exponential Moving Average (T3)", "t3_exponential_moving_average", "T3", "8L", - n_default = 5L, - signature = c("n=5", "vfactor=0.7") - ), - - ## ======================== - ## Overlap Studies - ## ======================== - overlap("Bollinger Bands", "bollinger_bands", "BBANDS", "~close", c("ma=SMA(n=5)", "sd=2", "sd_down", "sd_up")), - overlap("Hilbert Transform - Instantaneous Trendline", "trendline", "HT_TRENDLINE", "~close", ""), - overlap("Parabolic Stop and Reverse (SAR)", "parabolic_stop_and_reverse", "SAR", "~high+low", c("acceleration=0.02", "maximum=0.2")), - overlap("Parabolic Stop and Reverse (SAR) - Extended", "extended_parabolic_stop_and_reverse", "SAREXT", "~high+low", c("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")), - overlap("Acceleration Bands", "acceleration_bands", "ACCBANDS", "~ high + low + close", c("n=20")), - - ## ======================== - ## Volume Indicators - ## ======================== - volume("Chaikin A/D Line", "chaikin_accumulation_distribution_line", "AD", "~high+low+close+volume"), - volume("Chaikin A/D Oscillator", "chaikin_accumulation_distribution_oscillator", "ADOSC", "~high+low+close+volume", signature = c("fast=3", "slow=10")), - volume("On-Balance Volume", "on_balance_volume", "OBV", "~close+volume"), - volume("Trading Volume", "trading_volume", "VOLUME", "~volume + open + close", signature = c("ma = list(SMA(n = 7), SMA(n = 15))"), univariate = 1, c_generator = "skip"), - - ## ======================== - ## Volatility Indicators - ## ======================== - volatility("True Range", "true_range", "TRANGE", "~high + low + close"), - volatility("Average True Range", "average_true_range", "ATR", "~high + low + close", signature = "n=14"), - volatility("Normalized Average True Range", "normalized_average_true_range", "NATR", "~high + low + close", signature = "n=14"), - - ## ======================== - ## Price Transforms - ## ======================== - price_xform("Average Price", "average_price", "AVGPRICE", "~open + high + low + close"), - price_xform("Median Price", "median_price", "MEDPRICE", "~high + low"), - price_xform("Typical Price", "typical_price", "TYPPRICE", "~high + low + close"), - price_xform("Weighted Close Price", "weighted_close_price", "WCLPRICE", "~high + low + close"), - price_xform("Midpoint Price", "midpoint_price", "MIDPRICE", "~high + low", signature = c("n=14")), - - ## ======================== - ## Rolling Statistics - ## ======================== - rolling("Rolling Sum", "rolling_sum", "SUM", "n = 30"), - rolling("Rolling Standard Deviation", "rolling_standard_deviation", "STDDEV", c("n=5", "k = 1")), - rolling("Rolling Standard Deviation", "rolling_variance", "VAR", c("n=5", "k = 1")), - rolling("Rolling Beta", "rolling_beta", "BETA", c("y", "n=5")), - rolling("Rolling Correlation", "rolling_correlation", "CORREL", c("y", "n=30")), - rolling("Rolling Max", "rolling_max", "MAX", c("n=30")), - rolling("Rolling Min", "rolling_min", "MIN", c("n=30")) -) diff --git a/codegen/gen_code/utils.R b/codegen/gen_code/utils.R deleted file mode 100644 index c35be6693..000000000 --- a/codegen/gen_code/utils.R +++ /dev/null @@ -1,93 +0,0 @@ -## script: Generate Functions -## objective: -## Consolidate functions -## for generators -## -## -## 1) main generator function -impl_generate_indicator <- function( - title, - fun, - family, - ta_fun, - formula = "~close", - plotly = 1L, - subchart = 1L, - args, - agnostic = NULL, - candlestick = 0, - maType = -1, - rolling = 0, - univariate = NULL, - n_default = 30L -) { - if (is.null(formula)) formula <- "~close" - if (missing(univariate) | is.null(univariate)) { - has_numeric <- as.integer( - as.logical( - length(all.vars(as.formula(formula))) == 1 - ) - ) - } else { - has_numeric <- univariate - } - - args <- gsub("([()])", "\\\\\\1", args, perl = TRUE) - args <- gsub("\\s+", "", args, perl = TRUE) - system2( - command = "bash", - args = c("./codegen/generate_indicator.sh", args), - env = c( - sprintf("TITLE='%s'", title), - sprintf("FUN='%s'", fun), - sprintf("FAMILY='%s'", family), - sprintf("TA_FUN='%s'", ta_fun), - sprintf("FORMULA='%s'", formula), - sprintf("PLOTLY='%s'", plotly), - sprintf("AGNOSTIC='%s'", agnostic), - sprintf("CANDLESTICK='%s'", candlestick), - sprintf("maType='%s'", maType), - sprintf("ROLLING='%s'", rolling), - sprintf("SUBCHART='%s'", subchart), - sprintf( - "NUMERIC='%s'", - has_numeric - ), - sprintf("N_DEFAULT='%s'", as.integer(n_default)) - ) - ) -} - -impl_generate_test <- function( - fun, - ta_fun, - formula = "~close", - plotly = 1, - rolling = 0, - args = NULL -) { - if (is.null(formula)) formula <- "~close" - args <- gsub("([()])", "\\\\\\1", args, perl = TRUE) - args <- gsub("\\s+", "", args, perl = TRUE) - - system2( - command = "bash", - args = c("./codegen/generate_unit-tests.sh", args), - env = c( - sprintf("FUN='%s'", fun), - sprintf("TA_FUN='%s'", ta_fun), - sprintf("FORMULA='%s'", formula), - sprintf("PLOTLY='%s'", plotly), - sprintf("ROLLING='%s'", rolling), - sprintf( - "NUMERIC='%s'", - as.integer( - as.logical( - length(all.vars(as.formula(formula))) == 1 - ) - ) - ) - ) - ) -} - diff --git a/codegen/generate_API.sh b/codegen/generate_API.sh deleted file mode 100755 index 7fa6829ca..000000000 --- a/codegen/generate_API.sh +++ /dev/null @@ -1,91 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail -IFS=$'\n\t' - -usage() { - cat <&2 -Usage: ${0##*/} [SRC_DIR] [OUT_FILE] - SRC_DIR Directory with .c sources (default: src) - OUT_FILE Header file to generate (default: api.h) -EOF - exit 1 -} - -if [[ $# -gt 2 ]]; then - usage -fi - -SRC_DIR="${1:-src}" -OUT_FILE="${2:-api.h}" - -print_header() { - cat <<'EOF' -// Generated from codegen/generate_API.sh -#ifndef _API_H_ -#define _API_H_ - -#include - -// clang-format off -EOF -} - -extract_signatures() { - awk ' - # start of an SEXP function (skip static — those are TU-local helpers, - # not entry points, and declaring them in a shared header triggers - # -Wunused-function for every TU that does not define them) - /^[[:space:]]*SEXP[[:space:]]+/ { - sig = $0 - - # keep reading until we hit "{" or ";" - while (sig !~ /\{/ && sig !~ /;/) { - if (getline <= 0) break - # skip pure formatter lines while collecting - if ($0 ~ /^[[:space:]]*\/\/[[:space:]]*clang-format[[:space:]]+(on|off)/) - continue - sig = sig " " $0 - } - - # if the formatter marker still got attached at the end of sig, drop it - sub(/[[:space:]]*\/\/[[:space:]]*clang-format[[:space:]]+(on|off)[[:space:]]*$/, "", sig) - - # only handle real definitions (we saw "{") - if (sig ~ /\{/) { - left = gsub(/\(/, "&", sig) - right = gsub(/\)/, "&", sig) - if (left == right) { - sub(/\{.*$/, "", sig) - - gsub(/[[:space:]]+/, " ", sig) - sub(/^[[:space:]]+/, "", sig) - sub(/[[:space:]]+$/, "", sig) - gsub(/\( /, "(", sig) - gsub(/ \)/, ")", sig) - - printf("%s;\n", sig) - } - } - } - ' "${SRC_DIR}"/*.c | sort -u -} - - -print_footer() { - cat <<'EOF' -// clang-format on - -#endif //_API_H -EOF -} - -# === Main driver === -main() { - echo "Generating ${OUT_FILE} from C sources in ${SRC_DIR}/..." - print_header > "${OUT_FILE}" - extract_signatures >> "${OUT_FILE}" - print_footer >> "${OUT_FILE}" - echo "Done: ${OUT_FILE}" -} - -main diff --git a/codegen/generate_FFI.sh b/codegen/generate_FFI.sh deleted file mode 100755 index 3bb032c0a..000000000 --- a/codegen/generate_FFI.sh +++ /dev/null @@ -1,83 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail -IFS=$'\n\t' - -if [[ $# -gt 2 ]]; then - usage -fi - -API_HEADER="${1:-api.h}" -OUT_FILE="${2:-init.c}" - -print_header() { - cat <<'EOF' -// Generated from codegen/generate_FFI.sh -#include -#include -#include -#include - -#include "api.h" - -// clang-format off -#define CALLDEF(name, n) {#name, (DL_FUNC) &name, n} -// clang-format on - -static const R_CallMethodDef CallEntries[] = { -EOF -} - -generate_entries() { - awk ' - # Match prototype lines - /^SEXP[[:space:]]+/ { - sig = $0 - sub(/^SEXP[[:space:]]+/, "", sig) - sub(/;[[:space:]]*$/, "", sig) - - # split name and argument list - split(sig, parts, /\(/) - name = parts[1] - args = parts[2] - sub(/\)$/, "", args) - - # count arguments: commas + 1 (or 0 if empty or "void") - if (args ~ /^[[:space:]]*$/ || args ~ /^[[:space:]]*void[[:space:]]*$/) { - n = 0 - } else { - tmp = args - n = gsub(/,/, ",", tmp) + 1 - } - printf(" CALLDEF(%s, %d),\n", name, n) - } - ' "$API_HEADER" - echo " {NULL, NULL, 0}" -} - -print_footer() { - cat <<'EOF' -}; -EOF -} - -print_init() { - cat < "$OUT_FILE" - generate_entries >> "$OUT_FILE" - print_footer >> "$OUT_FILE" - print_init >> "$OUT_FILE" - echo "Done: $OUT_FILE" -} - -main \ No newline at end of file diff --git a/codegen/generate_core_candlestick.sh b/codegen/generate_core_candlestick.sh deleted file mode 100755 index aff3d78f2..000000000 --- a/codegen/generate_core_candlestick.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -NAME=$1 -SIGNATURE=$2 -TEMPLATE=codegen/templates/candlestick_template.c.in - -if [[ -n "$SIGNATURE" ]]; then - PEN_ARG=$',\n\tSEXP optInPenetration' - PEN_READ='const double penetration = REAL(optInPenetration)[0];' - LOOKBACK="TA_${NAME}_Lookback(penetration);" - PEN_CALL=', penetration' - PEN_TEMP=$'\n//\t\tdouble\toptInPenetration' -else - PEN_ARG='' - PEN_READ='' - LOOKBACK="TA_${NAME}_Lookback();" - PEN_CALL='' - PEN_TEMP=$'' -fi - -export NAME LOOKBACK PEN_READ PEN_ARG PEN_CALL PEN_TEMP - -OUTFILE="src/ta_${NAME}.c" - -# convert {{VAR}} → ${VAR} then envsubst -sed -e 's/{{\([A-Z_][A-Z_0-9]*\)}}/${\1}/g' "$TEMPLATE" \ - | envsubst \ - > "$OUTFILE" diff --git a/codegen/generate_indicator.sh b/codegen/generate_indicator.sh deleted file mode 100755 index 64d63e758..000000000 --- a/codegen/generate_indicator.sh +++ /dev/null @@ -1,265 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -## 1) environment variables -## and templates passed downstream -## -## 1.1) common variables and templates -FAMILY=${FAMILY:-} -TITLE=${TITLE:-} -FUN=${FUN:?} -TA_FUN=${TA_FUN:?} -ALIAS=${ALIAS:-$TA_FUN} -FORMULA=${FORMULA:-"~close"} -PLOTLY=${PLOTLY:-0} -SUBCHART=${SUBCHART:-0} -NUMERIC=${NUMERIC:-1} -OUTPUTFILE=${OUTPUTFILE:-"R/ta_${TA_FUN}.R"} - -## 1.1) conditional templates -## passed downstream -TEMPLATE_MAIN=${TEMPLATE_MAIN:-codegen/templates/indicator_template.R.in} -TEMPLATE_NUMERIC=${NUMERIC_TEMPLATE:-codegen/templates/numeric_template.R.in} - -## 1.2) candlestick specific variables -## passed downstream -AGNOSTIC=${AGNOSTIC:-"TRUE"} -CANDLESTICK=${CANDLESTICK:-0} -if [[ $CANDLESTICK -eq 1 ]]; then - TEMPLATE_MAIN="codegen/templates/candlestick_template.R.in" -fi - -## 1.3) moving average specific -## variables -maType=${maType:--1} # NOTE: -1 is NO MA -if [[ "$maType" != "-1" ]]; then - TEMPLATE_MAIN="codegen/templates/moving_average_template.R.in" -fi - -## 1.4) rolling statistics -ROLLING=${ROLLING:-0} -if [[ "$ROLLING" != "0" ]]; then - TEMPLATE_MAIN="codegen/templates/rolling_template.R.in" -fi - -## 2) arguments passed into -## each function is constructed -## as an array. Has to be passed as -## a vector from R -ARGS_ARRAY=( "$@" ) - -## 2.1) split the arguments by the first -## '=' to avoid using awk -PARGS_ARR=() # arguments inside calls, becomes n = n, or k = k -CARGS_ARR=() # arguments inside .Call, becomes n, k -CARGS_TYPED_ARR=() # arguments inside .Call, type-coerced (as.integer/as.double) -SPEC_FIELDS_ARR=() # fields for MA spec-mode list(...) (key = coerced-or-default) -HAS_N=0 # track whether 'n' is already a formal signature arg -for a in "${ARGS_ARRAY[@]}"; do - if [[ $a == *=* ]]; then - k=${a%%=*} - v=${a#*=} - else - k=$a - v="" - fi - [[ "$k" == "n" ]] && HAS_N=1 - PARGS_ARR+=( ",$k=$k" ) - CARGS_ARR+=( ",$k" ) - ## decide coercion by default-value shape: dot => double, else integer - if [[ "$v" == *.* ]]; then - CARGS_TYPED_ARR+=( ",as.double($k)" ) - SPEC_FIELDS_ARR+=( "$k = if (missing($k)) $v else as.double($k)" ) - else - CARGS_TYPED_ARR+=( ",as.integer($k)" ) - SPEC_FIELDS_ARR+=( "$k = if (missing($k)) ${v}L else as.integer($k)" ) - fi -done - -## 2.1.1) inject 'n' as a spec-only field for MAs whose signature -## lacks it (today: MAMA). Every MA spec carries 'n' so that -## downstream consumers (BBANDS, STOCH, MACDEXT, ...) can -## read ma$n uniformly to drive their calculation period. -## The R function accepts 'n' as a formal arg so MAMA(n = 14) -## parses in spec-mode, but it is NOT forwarded to .Call() -## (TA_MAMA's C signature takes no period). -if [[ "$maType" != "-1" && $HAS_N -eq 0 ]]; then - _n_default=${N_DEFAULT:-30} - ## prepend so 'n' is the first spec field and first forwarding arg, - ## matching the ordering used by the n-bearing MAs. - SPEC_FIELDS_ARR=( "n = if (missing(n)) ${_n_default}L else as.integer(n)" "${SPEC_FIELDS_ARR[@]}" ) - PARGS_ARR=( ",n=n" "${PARGS_ARR[@]}" ) - ARGS_ARRAY=( "n=${_n_default}" "${ARGS_ARRAY[@]}" ) - ## NOTE: deliberately NOT adding to CARGS_ARR / CARGS_TYPED_ARR - - ## the C wrapper for MAMA has no period parameter. -fi - -## 2.2) construct arguments -## a la paste + collapse -PARGS=$(printf '%s ' "${PARGS_ARR[@]}"); PARGS=${PARGS%, } -if [[ "$ROLLING" != "1" ]]; then - if [[ -n ${PARGS} ]]; then PARGS+=','; fi -fi - -printf -v ARGS '%s, ' "${ARGS_ARRAY[@]}"; ARGS=${ARGS%, } -if [[ "$ROLLING" != "1" ]]; then - if [[ -n ${ARGS} ]]; then ARGS+=','; fi -fi -## NOTE: this is passed down to -## the {plotly} template -PPARGS=$(printf '%s ' "${PARGS_ARR[@]}"); -CARGS=$(printf '%s ' "${CARGS_ARR[@]}"); -CARGS_TYPED=$(printf '%s ' "${CARGS_TYPED_ARR[@]}"); - -## 2.3) spec-mode list fields for the moving_average template. -## Each signature argument becomes a round-tripped entry in -## the list returned when the MA is called without 'x'. -## Joined with ',' + newline + indent so 'air' can reformat. -SPEC_FIELDS="" -for ((_i=0; _i<${#SPEC_FIELDS_ARR[@]}; _i++)); do - if [[ $_i -eq 0 ]]; then - SPEC_FIELDS="${SPEC_FIELDS_ARR[$_i]}" - else - SPEC_FIELDS="${SPEC_FIELDS},"$'\n\t\t\t\t'"${SPEC_FIELDS_ARR[$_i]}" - fi -done - -## 3) export environment variables -## to replace in templates -REPLACE='' -export FUN; REPLACE+='${FUN}' -export TITLE; REPLACE+='${TITLE}' -export TA_FUN; REPLACE+='${TA_FUN}' -export ALIAS; REPLACE+='${ALIAS}' -export FAMILY; REPLACE+='${FAMILY}' -export FORMULA; REPLACE+='${FORMULA}' -export ARGS; REPLACE+='${ARGS}' -export PARGS; REPLACE+='${PARGS}' -export CARGS; REPLACE+='${CARGS}' -export CARGS_TYPED; REPLACE+='${CARGS_TYPED}' -export PPARGS; REPLACE+='${PPARGS}' -export AGNOSTIC; REPLACE+='${AGNOSTIC}' -export maType; REPLACE+='${maType}' -export N_DEFAULT; REPLACE+='${N_DEFAULT}' -export SPEC_FIELDS; REPLACE+='${SPEC_FIELDS}' - -## 4) construct R files -## in temporary locations -## to avoid breaking existing code -tmp_render="$(mktemp)"; tmp_plotly="$(mktemp)"; tmp_numeric="$(mktemp)"; tmp_ggplot="$(mktemp)"; tmp_splice="$(mktemp)" -trap 'rm -f "$tmp_render" "$tmp_plotly" "$tmp_numeric" "$tmp_ggplot" "$tmp_splice"' EXIT - -## 4.1) main template -envsubst "$REPLACE" < "$TEMPLATE_MAIN" > "$tmp_render" - -## 4.2) optional templates -## pre-appended with double linebreak -## to avoid broken code -if [[ $NUMERIC -eq 1 && $ROLLING -ne 1 ]]; then - envsubst "$REPLACE" < "$TEMPLATE_NUMERIC" > "$tmp_numeric" - printf '\n\n' >> "$tmp_render" - cat "$tmp_numeric" >> "$tmp_render" -fi - -if [[ $PLOTLY -eq 1 ]]; then - if [[ $SUBCHART -eq 1 ]]; then - TEMPLATE_PLOTLY=${TEMPLATE_PLOTLY:-codegen/templates/plotly_subchart_template.R.in} - envsubst "$REPLACE" < "$TEMPLATE_PLOTLY" > "$tmp_plotly" - printf '\n\n' >> "$tmp_render" - cat "$tmp_plotly" >> "$tmp_render" - else - TEMPLATE_PLOTLY=${TEMPLATE_PLOTLY:-codegen/templates/plotly_main_template.R.in} - envsubst "$REPLACE" < "$TEMPLATE_PLOTLY" > "$tmp_plotly" - printf '\n\n' >> "$tmp_render" - cat "$tmp_plotly" >> "$tmp_render" - fi -fi - -## 4.4) ggplot2 templates -## for candlestick and moving average templates -## the ggplot method is appended separately since -## their plotly methods are baked into the main template -if [[ $CANDLESTICK -eq 1 ]]; then - envsubst "$REPLACE" < "codegen/templates/candlestick_ggplot_template.R.in" > "$tmp_ggplot" - printf '\n\n' >> "$tmp_render" - cat "$tmp_ggplot" >> "$tmp_render" -elif [[ "$maType" != "-1" ]]; then - envsubst "$REPLACE" < "codegen/templates/moving_average_ggplot_template.R.in" > "$tmp_ggplot" - printf '\n\n' >> "$tmp_render" - cat "$tmp_ggplot" >> "$tmp_render" -elif [[ $PLOTLY -eq 1 ]]; then - if [[ $SUBCHART -eq 1 ]]; then - TEMPLATE_GGPLOT=${TEMPLATE_GGPLOT:-codegen/templates/ggplot_subchart_template.R.in} - envsubst "$REPLACE" < "$TEMPLATE_GGPLOT" > "$tmp_ggplot" - printf '\n\n' >> "$tmp_render" - cat "$tmp_ggplot" >> "$tmp_render" - else - TEMPLATE_GGPLOT=${TEMPLATE_GGPLOT:-codegen/templates/ggplot_main_template.R.in} - envsubst "$REPLACE" < "$TEMPLATE_GGPLOT" > "$tmp_ggplot" - printf '\n\n' >> "$tmp_render" - cat "$tmp_ggplot" >> "$tmp_render" - fi -fi - - -## 5) splice protected code regions -## (this is the old code, it works) -## NOTE: use -s (exists AND non-empty). If the file exists but is -## 0 bytes, awk's FNR==NR pass-1 trick misfires: no records from -## pass 1 means `tmp_render` gets consumed as pass 1 (harvest-only), -## pass 2 never runs, and the output is empty. -s routes 0-byte -## files through the `else` branch which copies the rendered template. -if [[ -s "$OUTPUTFILE" ]]; then - awk ' - function rtrim(s){ sub(/[[:space:]]+$/,"",s); return s } - function label_from(line, part, pos,rest,needle) { - needle = "splice:" - pos = index(line, needle) - if (!pos) return "" - rest = substr(line, pos + length(needle)) # LABEL:part - needle = ":" part - pos = index(rest, needle) - if (!pos) return "" - return rtrim(substr(rest, 1, pos-1)) - } - - ## pass 1: harvest preserved bodies from existing OUTPUTFILE - FNR==NR { - lbl = label_from($0, "start") - if (lbl != "") { cur = lbl; inside = 1; next } - if (inside) { - if (label_from($0, "end") == cur) { inside = 0; next } - blocks[cur] = blocks[cur] $0 ORS - next - } - next - } - - ## pass 2: write new file from staged template with preserved inserts - { - lbl = label_from($0, "start") - if (lbl != "") { - print # print the start marker - end_lbl = lbl - if (lbl in blocks) { - printf "%s", blocks[lbl] - preserve = 1 - } else { - preserve = 0 - } - while ( (getline line) > 0 ) { - if (label_from(line,"end") == end_lbl) { print line; break } - if (!preserve) print line - } - next - } - print - } - ' "$OUTPUTFILE" "$tmp_render" > "$tmp_splice" -else - cp "$tmp_render" "$tmp_splice" -fi - -## 6) commit the code -## to R/ -mv "$tmp_splice" "$OUTPUTFILE" diff --git a/codegen/generate_indicator_core.sh b/codegen/generate_indicator_core.sh deleted file mode 100755 index 56d2e5d8c..000000000 --- a/codegen/generate_indicator_core.sh +++ /dev/null @@ -1,419 +0,0 @@ -#!/usr/bin/env bash -# generate_indicator_core.sh -# usage: -# ./generate_indicator_core.sh MACD > impl_ta_MACD.c -# TEMPLATE=indicator_template.c.in ./generate_indicator_core.sh ACCBANDS -set -euo pipefail - -if [ "$#" -ne 1 ]; then - echo "usage: $0 " >&2 - exit 1 -fi -NAME="$1" - -# 1) find header (new layout first) -if [ -f "src/ta-lib/include/ta-lib/ta_func.h" ]; then - TA_H="src/ta-lib/include/ta-lib/ta_func.h" -elif [ -f "src/ta-lib/include/ta_func.h" ]; then - TA_H="src/ta-lib/include/ta_func.h" -else - echo "error: ta_func.h not found" >&2 - exit 1 -fi - -# 2) exact main prototype: must be TA_( and must NOT contain TA__ -proto_line=$(awk -v name="$NAME" ' - { gsub(/\/\*[^*]*\*\//, "", $0) } - index($0, "TA_" name "(") { - if (index($0, "TA_" name "_") != 0) next; - line = $0 - while (line !~ /\);/) { - getline nxt - gsub(/\/\*[^*]*\*\//, "", nxt) - line = line " " nxt - } - gsub(/[\r\n]+/, " ", line) - print line - exit - } -' "$TA_H") -[ -n "$proto_line" ] || { echo "error: TA_${NAME}(...) not found" >&2; exit 1; } - -param_list=${proto_line#*(} -param_list=${param_list%);} - -# 3) exact lookback prototype -lb_line=$(awk -v name="$NAME" ' - { gsub(/\/\*[^*]*\*\//, "", $0) } - index($0, "TA_" name "_Lookback(") { - line = $0 - while (line !~ /\);/) { - getline nxt - gsub(/\/\*[^*]*\*\//, "", nxt) - line = line " " nxt - } - gsub(/[\r\n]+/, " ", line) - print line - exit - } -' "$TA_H") -[ -n "$lb_line" ] || { echo "error: TA_${NAME}_Lookback(...) not found" >&2; exit 1; } - -lb_params=${lb_line#*(} -lb_params=${lb_params%);} - -# 4) classify params -declare -a in_arrays_type=() -declare -a in_arrays_name=() -declare -a in_scalars_type=() -declare -a in_scalars_name=() -declare -a out_arrays_type=() -declare -a out_arrays_name=() - -IFS=',' read -r -a params <<<"$param_list" -for raw in "${params[@]}"; do - p=$(echo "$raw" | sed 's:/\*[^*]*\*/::g; s/^[[:space:]]*//; s/[[:space:]]*$//') - - [[ "$p" =~ ^int[[:space:]]+startIdx$ ]] && continue - [[ "$p" =~ ^int[[:space:]]+endIdx$ ]] && continue - [[ "$p" =~ ^int[[:space:]]+\*outBegIdx$ ]] && continue - [[ "$p" =~ ^int[[:space:]]+\*outNBElement$ ]] && continue - - if [[ "$p" =~ ^double[[:space:]]+out([A-Za-z0-9_]+)\[\]$ ]]; then - out_arrays_type+=("double") - out_arrays_name+=("${BASH_REMATCH[1]}") - continue - fi - if [[ "$p" =~ ^int[[:space:]]+out([A-Za-z0-9_]+)\[\]$ ]]; then - out_arrays_type+=("int") - out_arrays_name+=("${BASH_REMATCH[1]}") - continue - fi - - if [[ "$p" =~ ^const[[:space:]]+double[[:space:]]+([A-Za-z0-9_]+)\[\]$ ]]; then - in_arrays_type+=("double") - in_arrays_name+=("${BASH_REMATCH[1]}") - continue - fi - if [[ "$p" =~ ^const[[:space:]]+int[[:space:]]+([A-Za-z0-9_]+)\[\]$ ]]; then - in_arrays_type+=("int") - in_arrays_name+=("${BASH_REMATCH[1]}") - continue - fi - - if [[ "$p" =~ ^TA_MAType[[:space:]]+([A-Za-z0-9_]+)$ ]]; then - in_scalars_type+=("MAType") - in_scalars_name+=("${BASH_REMATCH[1]}") - continue - fi - if [[ "$p" =~ ^double[[:space:]]+([A-Za-z0-9_]+)$ ]]; then - in_scalars_type+=("double") - in_scalars_name+=("${BASH_REMATCH[1]}") - continue - fi - if [[ "$p" =~ ^int[[:space:]]+([A-Za-z0-9_]+)$ ]]; then - in_scalars_type+=("int") - in_scalars_name+=("${BASH_REMATCH[1]}") - continue - fi -done - -[ "${#in_arrays_name[@]}" -gt 0 ] || { echo "error: no array inputs" >&2; exit 1; } -[ "${#out_arrays_name[@]}" -gt 0 ] || { echo "error: no array outputs" >&2; exit 1; } - -## 5) R signature -## -## // clang-format off -## SEXP impl_ta_${NAME}($R_SIGNATURE) -## // clang-format on -## -## example output: -## -## // clang-format off -## SEXP impl_ta_AROONOSC( -## SEXP inHigh, -## SEXP inLow, -## SEXP optInTimePeriod -## ) -## // clang-format on -## -R_SIGNATURE=$'\n' -for i in "${!in_arrays_name[@]}"; do - R_SIGNATURE+=$'\tSEXP '"${in_arrays_name[$i]}"$',\n' -done -for i in "${!in_scalars_name[@]}"; do - R_SIGNATURE+=$'\tSEXP '"${in_scalars_name[$i]}"$',\n' -done -R_SIGNATURE=${R_SIGNATURE%$'\n'} - -## 6) PARAM_DOC -## -## // Parameters -## // $PARAM_DOC -## // Returns -## -## example output: -## -## // Parameters -## // double inHigh -## // double inLow -## // integer optInTimePeriod -## // -## -PARAM_DOC=$'' -for i in "${!in_arrays_name[@]}"; do - n=${in_arrays_name[$i]} - t=${in_arrays_type[$i]} - if [ "$t" = "double" ]; then - PARAM_DOC+=$'\t\tdouble '"$n"$'\n// ' - else - PARAM_DOC+=$'\t\tinteger '"$n"$'\n' - fi -done -for i in "${!in_scalars_name[@]}"; do - n=${in_scalars_name[$i]} - t=${in_scalars_type[$i]} - case "$t" in - int) PARAM_DOC+=$'\t\tinteger '"$n"$'\n//' ;; - double) PARAM_DOC+=$'\t\tdouble '"$n"$'\n//' ;; - MAType) PARAM_DOC+=$'\t\tinteger '"$n"$' (MAType)\n//' ;; - esac -done - -## 7) VALUES -## -## // pointers to input -## $VALUES -## -## -## 7.1) length of the input array -## -## example output: -## -## // get length of 'inHigh' (assumes equal length across input) -## const int n = LENGTH(inHigh); -VALUES=$'' -first_arr_name=${in_arrays_name[0]} -first_arr_type=${in_arrays_type[0]} -VALUES+=$'// get length of \''"${first_arr_name}"$'\' (assumes equal length across input)\n' -VALUES+=$'int n = LENGTH('"${first_arr_name}"$');\n\n' - -## 7.2) extract the input array(s) -## -## example output: -## -## // pointers to input arrays -## const double *restrict inHigh_ptr = REAL(inHigh); -## const double *restrict inLow_ptr = REAL(inLow); -if [ "$first_arr_type" = "double" ]; then - VALUES+=$'// pointers to input arrays\n' - VALUES+=$'const double *'"${first_arr_name}"$'_ptr = REAL('"${first_arr_name}"$');\n' -else - VALUES+=$'const int *'"${first_arr_name}"$'_ptr = INTEGER('"${first_arr_name}"$');\n' -fi -for i in "${!in_arrays_name[@]}"; do - [ "$i" -eq 0 ] && continue - n=${in_arrays_name[$i]} - t=${in_arrays_type[$i]} - if [ "$t" = "double" ]; then - VALUES+=$'const double *'"$n"$'_ptr = REAL('"$n"$');\n' - else - VALUES+=$'const int *'"$n"$'_ptr = INTEGER('"$n"$');\n' - fi -done - -## 7.3) extract the input argumetns(s) -## -## example output: -## -## // extract input values -## const int optInTimePeriod_ptr = INTEGER(optInTimePeriod)[0]; -if [ "${#in_scalars_name[@]}" -gt 0 ]; then - VALUES+=$'\n// extract input values\n' -fi -for i in "${!in_scalars_name[@]}"; do - n=${in_scalars_name[$i]} - t=${in_scalars_type[$i]} - case "$t" in - int) VALUES+=$'const int '"$n"$'_value = INTEGER('"$n"$')[0];\n' ;; - double) VALUES+=$'const double '"$n"$'_value = REAL('"$n"$')[0];\n' ;; - MAType) VALUES+=$'const TA_MAType '"$n"$'_value = as_MAType('"$n"$');\n' ;; - esac -done - -## 8) Lookback args -## -## // calculate look back and exit -## // the function function early if -## // there is a mismatch -## const int lookback = TA_${NAME}_Lookback( -## $LOOKBACK_ARGS -## ); -## -LOOKBACK_ARGS="" -IFS=',' read -r -a lbps <<<"$lb_params" -for raw in "${lbps[@]}"; do - # strip /* ... */ and trim - p=$(echo "$raw" | sed 's:/\*[^*]*\*/::g; s/^[[:space:]]*//; s/[[:space:]]*$//') - [ -z "$p" ] && continue - - # split into words - read -r -a toks <<<"$p" - - name="" - for ((idx=${#toks[@]}-1; idx>=0; idx--)); do - tok=${toks[$idx]} - tok=${tok%,} - tok=${tok%);} - tok=${tok%)} - tok=${tok%;} - [ -z "$tok" ] && continue - if [ "$tok" = "void" ]; then - name="" - break - fi - name="$tok" - break - done - [ -z "$name" ] && continue - LOOKBACK_ARGS+="${name}_value, " -done - -LOOKBACK_ARGS=${LOOKBACK_ARGS%, } - -if [ -n "$LOOKBACK_ARGS" ]; then - LOOKBACK_ARGS=$''"$LOOKBACK_ARGS"$'\n' -fi - -## 9) Value pointers -## -## TA_RetCode return_code = TA_${NAME}( -## 0, -## n - 1, -## $VALUE_POINTERS, -## &start_idx, -## &end_idx, -## $OUTPUT_POINTERS -## ); -## -## NOTE: It doesnt quite work as expected -## but clang-format handles the rest -VALUE_POINTERS=$'' -for i in "${!in_arrays_name[@]}"; do - VALUE_POINTERS+=$'\t\t'"${in_arrays_name[$i]}_ptr"$',' -done -for i in "${!in_scalars_name[@]}"; do - VALUE_POINTERS+=$'\t\t'"${in_scalars_name[$i]}_value"$',' -done -VALUE_POINTERS=${VALUE_POINTERS%$''} - -## 10) Outputs -## -## 10.1) constructs all output -## values -OUT_COLS=${#out_arrays_name[@]} -first_out_type=${out_arrays_type[0]} - -OUTPUT_COLS=$'' -OUTPUT_POINTERS=$'' -SHIFT_ARRAYS=$'' -COLNAMES=() - -for i in "${!out_arrays_name[@]}"; do - on=${out_arrays_name[$i]} - cbase=${on#out} - clower=$(echo "$cbase" | tr '[:upper:]' '[:lower:]') - if [ "$i" -eq 0 ]; then - OUTPUT_COLS+=$''"${first_out_type}"$' *'"${clower}"$' = output_ptr;\n' - else - OUTPUT_COLS+=$''"${first_out_type}"$' *'"${clower}"$' = output_ptr + '"${i}"$' * n;\n' - fi - OUTPUT_POINTERS+=$''"${clower}"$',\n' - SHIFT_ARRAYS+=$'shift_array('"${clower}"$', n, start_idx);\n' - - cname=${on#out} - if [[ "$cname" == Real* ]]; then - cname=${cname#Real} - fi - COLNAMES+=("$cname") -done -OUTPUT_POINTERS=${OUTPUT_POINTERS%,$'\n'} - -## 10.2) column names -## -## // set the column names of the output -## // see names.h for more details -## $SET_COLUMN_NAMES -## -## example output: -## -## // set the column names of the output -## // see names.h for more details -## set_colnames(output, "AROONOSC"); -if [ "$OUT_COLS" -eq 1 ]; then - SET_COLUMN_NAMES="set_colnames(output, \"$NAME\");" - RETURN_COLS="\"$NAME\"" -else - cn_join="" - for c in "${COLNAMES[@]}"; do - cn_join+="\"$c\", " - done - cn_join=${cn_join%, } - SET_COLUMN_NAMES="set_colnames(output, $cn_join);" - RETURN_COLS="$cn_join" -fi - -## 10.3) output type -OUTPUT_TYPE=${out_arrays_type[0]} - -## 11) NA handling code generation -## -## 11.1) build_na_mask call with all double input arrays -NA_MASK_PTRS="" -NA_N_ARRAYS=0 -for i in "${!in_arrays_name[@]}"; do - t=${in_arrays_type[$i]} - if [ "$t" = "double" ]; then - NA_MASK_PTRS+="${in_arrays_name[$i]}_ptr, " - ((NA_N_ARRAYS++)) || true - fi -done -NA_MASK_PTRS=${NA_MASK_PTRS%, } - -NA_MASK_BUILD=$'' -NA_MASK_BUILD+="const double *na_arrays[] = {${NA_MASK_PTRS}};"$'\n' -NA_MASK_BUILD+=" n = build_na_mask(na_mask, n, ${NA_N_ARRAYS}, na_arrays);" - -## 11.2) compact_arrays call + pointer reassignment -NA_COMPACT=$'' -NA_COMPACT+="compact_arrays(na_arrays, ${NA_N_ARRAYS}, na_mask, n_original, n);"$'\n' -ci=0 -for i in "${!in_arrays_name[@]}"; do - t=${in_arrays_type[$i]} - nm=${in_arrays_name[$i]} - if [ "$t" = "double" ]; then - NA_COMPACT+=" ${nm}_ptr = na_arrays[${ci}];"$'\n' - ((ci++)) || true - fi -done - -# 12) export and run envsubst -export NAME -export R_SIGNATURE -export PARAM_DOC -export VALUES -export LOOKBACK_ARGS -export OUT_COLS -export OUTPUT_COLS -export VALUE_POINTERS -export END_IDX="&end_idx," -export OUTPUT_POINTERS -export SHIFT_ARRAYS -export SET_COLUMN_NAMES -export RETURN_COLS -export OUTPUT_TYPE -export NA_MASK_BUILD -export NA_COMPACT - -TEMPLATE_FILE=${TEMPLATE:-codegen/templates/indicator_template.c.in} -envsubst < "$TEMPLATE_FILE" diff --git a/codegen/parity/test_parity_template.R b/codegen/parity/test_parity_template.R index c275a39d8..51d8f70f3 100644 --- a/codegen/parity/test_parity_template.R +++ b/codegen/parity/test_parity_template.R @@ -72,7 +72,11 @@ R_CALL_OVERRIDES <- list( STDDEV = function(btc, snap) talib::STDDEV(btc$close), MAX = function(btc, snap) talib::MAX(btc$close), MIN = function(btc, snap) talib::MIN(btc$close), - SUM = function(btc, snap) talib::SUM(btc$close) + SUM = function(btc, snap) talib::SUM(btc$close), + ## MAVP takes a required 'periods' vector; parity_gen.c wires the + ## upstream inPeriods slot to close (the non-price Real fallback), + ## so mirror that here. + MAVP = function(btc, snap) talib::MAVP(btc, periods = btc$close) ) ## Invoke the R wrapper for an indicator. Returns a list: @@ -210,7 +214,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/src/c_header.rs b/codegen/src/c_header.rs new file mode 100644 index 000000000..3c5e3c0d1 --- /dev/null +++ b/codegen/src/c_header.rs @@ -0,0 +1,344 @@ +//! src/TA-Lib.h generation +//! +//! Each TA-Lib function is defined in 'src/ta-lib/include/ta_func.h' +//! on the following form: +//! +//! ```c +//! TA_LIB_API TA_RetCode TA_ACCBANDS( +//! int startIdx, +//! int endIdx, +//! const double inHigh[], +//! const double inLow[], +//! const double inClose[], +//! int optInTimePeriod, /* From 2 to 100000 */ +//! int *outBegIdx, +//! int *outNBElement, +//! double outRealUpperBand[], +//! double outRealMiddleBand[], +//! double outRealLowerBand[] +//! ); +//! ``` +//! +//! so every prototype can be mined directly and rewritten as one +//! variadic X-macro line per indicator (plus one for its +//! TA__Lookback() companion). The hand-written src/init.c +//! #includes the generated header several times, expanding those +//! lines via the macro helpers of src/wrapper.h into wrapper +//! definitions and the .Call() registration table, keeping the C +//! binding logic in exactly one place. + +/// One TA-Lib function mined from ta_func.h, reduced to what the +/// X-macro lines need +#[allow(non_camel_case_types)] +#[derive(Debug, Default, PartialEq)] +pub struct TA_Lib { + pub indicator: String, + pub argument_type: &'static str, + pub input: Vec, + pub optional_input: Vec, + pub output_indicators: Vec, + pub output_names: Vec, +} + +/// The full src/TA-Lib.h: one TA_INDICATOR line per function, +/// then one TA_LOOKBACK line per function +pub fn render_header(names: &[String], header: &str) -> String { + let header = purge_comments(header); + let funcs: Vec = names + .iter() + .map(|n| extract_signature(n, &header)) + .collect(); + + let mut out = String::from(concat!( + "// TA-Lib.h - Autogenerated via codegen/\n", + "// Description:\n", + "//\n", + "// \t\tTA_INDICATOR: TA-Lib indicator.\n", + "// \t\tTA_INPUT: Indicator input.\n", + "// \t\tTA_OPTIONS: Indicator input.\n", + "// \t\tTA_OUTPUT: Indicator input.\n", + "// \t\tTA_OUTPUT_NAMES: Indicator input.\n", + "// \t\tTA_LOOKBACK: Indicator lookback (name + optional inputs).\n", + "//\n", + "// clang-format off\n", + )); + + for f in &funcs { + out.push_str(&indicator_macro(f)); + out.push('\n'); + } + + out.push('\n'); + out.push_str("// Lookback\n"); + for f in &funcs { + out.push_str(&lookback_macro(f)); + out.push('\n'); + } + + out.push_str("// clang-format on\n"); + out +} + +/// TA_INDICATOR: The indicator function of TA-Lib, e.g. TA_SMA() and its type +/// TA_INPUT: The input to the TA-Lib indicator, e.g. inReal +/// TA_OPTIONS: The optional input in the TA-Lib indicator, e.g. optInWindow +/// TA_OUTPUT: The output from the TA-Lib indicator, e.g. outReal +/// TA_OUTPUT_NAME: The output names from the TA-Lib indicator, e.g. outReal, outRealMiddleBand etc. +fn indicator_macro(function: &TA_Lib) -> String { + format!( + "TA_INDICATOR({}, {}, TA_INPUT({}), TA_OPTIONS({}), TA_OUTPUT({}), TA_OUTPUT_NAME({}), {})", + function.indicator, + function.argument_type, + function.input.join(", "), + function.optional_input.join(", "), + function.output_indicators.join(", "), + function.output_names.join(", "), + if function.indicator.starts_with("CDL") { + "CANDLESTICK" + } else { + "NOT_CANDLESTICK" + } + ) +} + +/// The TA__Lookback() companion of each indicator takes +/// exactly the indicator's optional inputs, so its macro only needs +/// the name and TA_OPTIONS. Void lookbacks (e.g. TA_ACOS_Lookback) +/// yield an empty TA_OPTIONS() +fn lookback_macro(function: &TA_Lib) -> String { + format!( + "TA_LOOKBACK({}, TA_OPTIONS({}))", + function.indicator, + function.optional_input.join(", "), + ) +} + +/// Drop every '/* ... */' block comment (each replaced by a single +/// space) so prototype mining never matches commented-out code +fn purge_comments(header: &str) -> String { + let mut out = String::with_capacity(header.len()); + let mut rest = header; + + while let Some(start) = rest.find("/*") { + out.push_str(&rest[..start]); + out.push(' '); + rest = match rest[start + 2..].find("*/") { + Some(end) => &rest[start + 2 + end + 2..], + None => "", + }; + } + + out.push_str(rest); + out +} + +/// The identifier of a parameter: drop `[]`/`*` and take the last token. +fn parameter_identifier(param: &str) -> String { + param + .replace("[]", " ") + .replace('*', " ") + .split_whitespace() + .last() + .unwrap_or("") + .to_string() +} + +/// Mine the TA_() prototype from the (comment-purged) +/// header; panics if the prototype is not found +fn extract_signature(indicator: &str, header: &str) -> TA_Lib { + let needle = format!("TA_RetCode TA_{indicator}("); + + let start = header + .find(&needle) + .unwrap_or_else(|| panic!("prototype not found: {indicator}")); + + let after = &header[start + needle.len()..]; + + let end = after + .find(')') + .unwrap_or_else(|| panic!("no closing paren for {indicator}")); + + let params: Vec<&str> = after[..end] + .split(',') + .map(str::trim) + .filter(|s| !s.is_empty()) + .collect(); + + let mut f = TA_Lib { + indicator: indicator.to_string(), + argument_type: "TA_DOUBLE", + ..Default::default() + }; + + for p in ¶ms { + // skip TA_INDICATOR(int startIdx, int endIdx, ...) + if p.contains("startIdx") || p.contains("endIdx") { + continue; + } + // skip TA_INDICATOR(..., int *outBegIdx, int *outNBElement, ...) + if p.contains("outBegIdx") || p.contains("outNBElement") { + continue; + } + + // The TA_INDICATOR contains two types + // of arrays - immutable input arrays, and mutable + // output arrays. Input arrays are *always* doubles + // while output can be integer arrays (candlestick patterns) + if p.contains("[]") { + let nm = parameter_identifier(p); + + if p.contains("const") { + f.input.push(nm); + } else { + f.argument_type = if p.contains("double") { + "TA_DOUBLE" + } else { + "TA_INTEGER" + }; + f.output_indicators.push(nm); + } + } else { + // the remainder of the TA_INDICATOR(..., int optInTimePeriod, ...) + // can either be a double, integer or MAType + let nm = parameter_identifier(p); + + f.optional_input.push(if p.contains("TA_MAType") { + format!("OPTIONAL_MATYPE({nm})") + } else if p.contains("double") { + format!("OPTIONAL_DOUBLE({nm})") + } else { + format!("OPTIONAL_INTEGER({nm})") + }); + } + } + + // The output names are given as outReal, outRealUpperBand + // which needs to be stripped so it ouputs UpperBand and + // for univariate output where outReal is not identifiable + // from the outputs the indicator name is replaced so + // outReal becomes SMA for TA_SMA() + for output in &f.output_indicators { + let bare = output.strip_prefix("out").unwrap_or(output); + let bare = bare.strip_prefix("Real").unwrap_or(bare); + let bare = bare.strip_prefix("Integer").unwrap_or(bare); + + f.output_names.push(if bare.is_empty() { + f.indicator.clone() + } else { + bare.to_string() + }); + } + f +} + +#[cfg(test)] +mod tests { + use super::*; + + const SAMPLE: &str = " + TA_LIB_API TA_RetCode TA_RSI( + int startIdx, + int endIdx, + const double inReal[], + int optInTimePeriod, + int *outBegIdx, + int *outNBElement, + double outReal[] + ); + + TA_LIB_API TA_RetCode TA_BBANDS( + int startIdx, int endIdx, + const double inReal[], + int optInTimePeriod, + double optInNbDevUp, + double optInNbDevDn, + TA_MAType optInMAType, + int *outBegIdx, + int *outNBElement, + double outRealUpperBand[], + double outRealMiddleBand[], + double outRealLowerBand[] + ); + + TA_LIB_API TA_RetCode TA_CDLDOJI( + int startIdx, + int endIdx, + const double inOpen[], + const double inHigh[], + const double inLow[], + const double inClose[], + int *outBegIdx, + int *outNBElement, + int outInteger[] + ); + "; + + #[test] + fn parses_single_real() { + let f = extract_signature("RSI", SAMPLE); + assert_eq!(f.argument_type, "TA_DOUBLE"); + assert_eq!(f.input, ["inReal"]); + assert_eq!(f.optional_input, ["OPTIONAL_INTEGER(optInTimePeriod)"]); + assert_eq!(f.output_indicators, ["outReal"]); + assert_eq!(f.output_names, ["RSI"]); + } + + #[test] + fn parses_multi_out_and_matypes() { + let f = extract_signature("BBANDS", SAMPLE); + assert_eq!(f.input, ["inReal"]); + assert_eq!( + f.optional_input, + [ + "OPTIONAL_INTEGER(optInTimePeriod)", + "OPTIONAL_DOUBLE(optInNbDevUp)", + "OPTIONAL_DOUBLE(optInNbDevDn)", + "OPTIONAL_MATYPE(optInMAType)" + ] + ); + assert_eq!( + f.output_indicators, + ["outRealUpperBand", "outRealMiddleBand", "outRealLowerBand"] + ); + assert_eq!(f.output_names, ["UpperBand", "MiddleBand", "LowerBand"]); + } + + #[test] + fn parses_int_output_and_ohlc() { + let f = extract_signature("CDLDOJI", SAMPLE); + assert_eq!(f.argument_type, "TA_INTEGER"); + assert_eq!(f.input, ["inOpen", "inHigh", "inLow", "inClose"]); + assert!(f.optional_input.is_empty()); + assert_eq!(f.output_indicators, ["outInteger"]); + assert_eq!(f.output_names, ["CDLDOJI"]); + } + + #[test] + fn renders_macro_lines() { + let purged = purge_comments(SAMPLE); + + assert_eq!( + indicator_macro(&extract_signature("RSI", &purged)), + "TA_INDICATOR(RSI, TA_DOUBLE, TA_INPUT(inReal), \ + TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod)), TA_OUTPUT(outReal), \ + TA_OUTPUT_NAME(RSI), NOT_CANDLESTICK)" + ); + assert_eq!( + lookback_macro(&extract_signature("RSI", &purged)), + "TA_LOOKBACK(RSI, TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod)))" + ); + + // candlesticks carry the CANDLESTICK kind (normalization flag) + // and an empty TA_OPTIONS() + assert_eq!( + indicator_macro(&extract_signature("CDLDOJI", &purged)), + "TA_INDICATOR(CDLDOJI, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), \ + TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDLDOJI), CANDLESTICK)" + ); + } + + #[test] + fn strips_comments() { + assert_eq!(purge_comments("a /* x */ b"), "a b"); + } +} diff --git a/codegen/src/main.rs b/codegen/src/main.rs new file mode 100644 index 000000000..d249f3b1a --- /dev/null +++ b/codegen/src/main.rs @@ -0,0 +1,63 @@ +//! Driver +//! +//! One `cargo run` regenerates everything the codegen owns: +//! +//! 1. `src/TA-Lib.h` — the C X-macro lines (see c_header.rs) +//! 2. `R/ta_.R` — the R wrappers (see render.rs), with +//! hand-edited splice regions of the existing files preserved +//! 3. `tests/testthat/test-ta_.R` — the unit tests +//! (see testthat.rs), overwritten on every run + +mod c_header; +mod metadata; +mod render; +mod tables; +mod testthat; + +use std::fs; + +fn main() { + let list = fs::read_to_string("src/ta-lib/ta_func_list.txt").expect("read ta_func_list.txt"); + let header = fs::read_to_string("src/ta-lib/include/ta_func.h").expect("read ta_func.h"); + let xml = fs::read_to_string("src/ta-lib/ta_func_api.xml").expect("read ta_func_api.xml"); + + // excluded by name or GroupId; applies to both + // the C and R generation below + let excluded = tables::excluded_indicators(&xml); + + let names: Vec = list + .lines() + .filter_map(|l| l.split_whitespace().next()) + .filter(|n| !excluded.iter().any(|e| e == n)) + .map(str::to_string) + .collect(); + + fs::write("src/TA-Lib.h", c_header::render_header(&names, &header)) + .expect("write src/TA-Lib.h"); + + let templates = render::Templates::load("codegen/templates"); + + for f in metadata::parse_api(&xml) { + let path = format!("R/ta_{}.R", f.indicator); + let mut rendered = render::render_indicator(&f, &templates); + + // protected regions: hand-edited splice content in the + // existing wrapper survives regeneration. Only a missing + // file (first generation) may skip the splice — any other + // read error must not silently overwrite the hand edits + // with template defaults + match fs::read_to_string(&path) { + Ok(existing) => rendered = render::preserve_regions(&rendered, &existing), + Err(e) if e.kind() == std::io::ErrorKind::NotFound => {} + Err(e) => panic!("read {path}: {e}"), + } + + fs::write(path, rendered).expect("write R wrapper"); + + fs::write( + format!("tests/testthat/test-ta_{}.R", f.indicator), + testthat::render_test(&f), + ) + .expect("write unit test"); + } +} diff --git a/codegen/src/metadata.rs b/codegen/src/metadata.rs new file mode 100644 index 000000000..4a1c80e6d --- /dev/null +++ b/codegen/src/metadata.rs @@ -0,0 +1,377 @@ +//! ta_func_api.xml mining +//! +//! The metadata driving the R side is mined from +//! 'src/ta-lib/ta_func_api.xml' where each indicator is described +//! as a block: +//! +//! ```xml +//! +//! BBANDS +//! Bollinger Bands +//! Overlap Studies +//! ... +//! ... +//! ... +//! +//! ``` +//! +//! The XML is attribute-free and machine-generated, so the +//! hand-rolled tag_blocks()/tag_text() mining below is sufficient +//! and keeps the crate dependency-free. + +use crate::tables::{EXCLUDED_GROUPS, is_excluded}; + +/// A reduced to what the R generation needs +#[derive(Debug, Default, PartialEq)] +pub struct MetaData { + pub title: String, + pub indicator: String, + pub family: String, + pub input: Vec, + /// Required inputs that are not price series (MAVP: inPeriods). + /// Rendered as required formals passed straight to .Call() + /// instead of being routed through the column formula + pub passthrough: Vec, + pub optional_input: Vec, +} + +impl MetaData { + /// Default column formula, deduplicated in input order, + /// e.g. [high, low, close] -> ~high + low + close + pub fn default_formula(&self) -> String { + let mut cols: Vec<&str> = Vec::new(); + for col in &self.input { + if !cols.contains(&col.as_str()) { + cols.push(col); + } + } + format!("~{}", cols.join(" + ")) + } +} + +/// An reduced to what the +/// R signature needs: an argument name, its type +/// (for the .Call() coercion), its default value and +/// its one-line description (for the @param docs) +#[derive(Clone, Debug, PartialEq)] +pub struct OptionalArg { + pub name: String, + pub kind: OptionalType, + pub default: String, + pub description: String, +} + +#[derive(Clone, Debug, PartialEq)] +pub enum OptionalType { + Integer, + Double, + MAType, +} + +/// All ... contents in document order +pub(crate) fn tag_blocks<'a>(xml: &'a str, tag: &str) -> Vec<&'a str> { + let open = format!("<{tag}>"); + let close = format!(""); + + let mut blocks = Vec::new(); + let mut rest = xml; + + while let Some(start) = rest.find(&open) { + let after = &rest[start + open.len()..]; + let end = after + .find(&close) + .unwrap_or_else(|| panic!("unclosed <{tag}>")); + + blocks.push(after[..end].trim()); + rest = &after[end + close.len()..]; + } + + blocks +} + +/// First ... content, if any +pub(crate) fn tag_text<'a>(xml: &'a str, tag: &str) -> Option<&'a str> { + let open = format!("<{tag}>"); + let close = format!(""); + + let start = xml.find(&open)?; + let after = &xml[start + open.len()..]; + let end = after.find(&close)?; + + Some(after[..end].trim()) +} + +/// 'Fast-K Period' -> fastKPeriod, 'Bollinger Bands' -> bollingerBands +pub fn camel_case(s: &str) -> String { + let mut out = String::new(); + let mut boundary = false; + + for c in s.chars() { + if c.is_ascii_alphanumeric() { + if boundary && !out.is_empty() { + out.push(c.to_ascii_uppercase()); + } else { + out.push(c.to_ascii_lowercase()); + } + boundary = false; + } else { + boundary = true; + } + } + + out +} + +/// Parse 'src/ta-lib/ta_func_api.xml' into one MetaData +/// per , skipping the exclusions +pub fn parse_api(xml: &str) -> Vec { + tag_blocks(xml, "FinancialFunction") + .iter() + .map(|block| { + let mut f = MetaData { + indicator: tag_text(block, "Abbreviation") + .expect("Abbreviation") + .to_string(), + title: tag_text(block, "ShortDescription") + .expect("ShortDescription") + .to_string(), + family: tag_text(block, "GroupId").expect("GroupId").to_string(), + ..Default::default() + }; + + // Required inputs become R column names; price series + // map to their OHLCV column while plain double arrays + // (inReal) default to the 'close' column. Anything else + // (MAVP: inPeriods -> periods) is no price series and + // becomes a passthrough formal passed straight to + // .Call() instead of a formula column + for arg in tag_blocks(block, "RequiredInputArgument") { + let input_type = tag_text(arg, "Name").expect("input Type"); + + f.input.push(match input_type { + "Open" | "High" | "Low" | "Close" | "Volume" => { + input_type.to_lowercase().replace("in", "") + } + "inReal" => "close".to_string(), + // inReal0: x and inReal1: y + // is affiliated with Price Transforms, Statistics Functions and Math Transforms + "inReal0" => "x".to_string(), + "inReal1" => "y".to_string(), + other => { + let name = other.strip_prefix("in").unwrap_or(other); + let mut chars = name.chars(); + let name = match chars.next() { + Some(c) => c.to_ascii_lowercase().to_string() + chars.as_str(), + None => panic!("empty required input name"), + }; + + f.passthrough.push(name); + continue; + } + }); + } + + // Optional inputs; the DefaultValue of doubles is stored + // in scientific notation (2.000000e-2) and is reformatted + // as a plain R literal (0.02) + for arg in tag_blocks(block, "OptionalInputArgument") { + let name = camel_case(tag_text(arg, "Name").expect("optional Name")); + let default = tag_text(arg, "DefaultValue").expect("DefaultValue"); + + // the ShortDescription becomes the @param text; the + // XML is entity-escaped and carries a few wording + // slips ('fro', 'Nb of') worth fixing at the source + let description = tag_text(arg, "ShortDescription") + .expect("optional ShortDescription") + .replace(">", ">") + .replace("<", "<") + .replace("&", "&") + .replace(" fro ", " for ") + .replace("Nb of", "Number of") + .trim_end_matches('.') + .to_string(); + + let (kind, default) = match tag_text(arg, "Type").expect("optional Type") { + "Integer" => (OptionalType::Integer, default.to_string()), + "MA Type" => (OptionalType::MAType, default.to_string()), + "Double" => ( + OptionalType::Double, + format!("{}", default.parse::().expect("double default")), + ), + unknown => panic!("unknown optional type: {unknown}"), + }; + + f.optional_input.push(OptionalArg { + name, + kind, + default, + description, + }); + } + + f + }) + .filter(|f| !EXCLUDED_GROUPS.contains(&f.family.as_str())) + .filter(|f| !is_excluded(&f.indicator)) + .collect() +} + +#[cfg(test)] +pub(crate) const SAMPLE: &str = r#" + + + BBANDS + Bbands + Bollinger Bands + Overlap Studies + + + Double Array + inReal + + + + + Time Period + Number of period + Integer + + 2 + 100000 + + 5 + + + Deviations up + Deviation multiplier for upper band + Double + 2.000000e+0 + + + MA Type + Type of Moving Average + MA Type + 0 + + + + + Double Array + outRealUpperBand + + + Double Array + outRealLowerBand + + + + + CDLDOJI + Doji + Pattern Recognition + + + Open + Open + + + High + High + + + Low + Low + + + Close + Close + + + + + Integer Array + outInteger + + + + + "#; + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn parses_optional_inputs() { + let f = &parse_api(SAMPLE)[0]; + + assert_eq!(f.indicator, "BBANDS"); + assert_eq!(f.title, "Bollinger Bands"); + assert_eq!(f.family, "Overlap Studies"); + assert_eq!(f.input, ["close"]); + assert_eq!(f.default_formula(), "~close"); + assert_eq!( + f.optional_input, + [ + OptionalArg { + name: "timePeriod".to_string(), + kind: OptionalType::Integer, + default: "5".to_string(), + description: "Number of period".to_string() + }, + OptionalArg { + name: "deviationsUp".to_string(), + kind: OptionalType::Double, + default: "2".to_string(), + description: "Deviation multiplier for upper band".to_string() + }, + OptionalArg { + name: "maType".to_string(), + kind: OptionalType::MAType, + default: "0".to_string(), + description: "Type of Moving Average".to_string() + } + ] + ); + } + + #[test] + fn parses_ohlc_inputs() { + let f = &parse_api(SAMPLE)[1]; + + assert_eq!(f.input, ["open", "high", "low", "close"]); + assert_eq!(f.default_formula(), "~open + high + low + close"); + assert!(f.optional_input.is_empty()); + } + + #[test] + fn parses_full_api() { + let xml = std::fs::read_to_string(concat!( + env!("CARGO_MANIFEST_DIR"), + "/../src/ta-lib/ta_func_api.xml" + )) + .expect("read ta_func_api.xml"); + + // 161 functions minus the 15 Math Transforms and the + // 18 EXCLUDED_INDICATORS + let funcs = parse_api(&xml); + assert_eq!(funcs.len(), 128); + assert!(funcs.iter().all(|f| f.family != "Math Transform")); + assert!(!funcs.iter().any(|f| f.indicator == "ACOS")); + assert!(!funcs.iter().any(|f| f.indicator == "MA")); + + // MAVP: inPeriods is a passthrough formal, not a + // formula column + let mavp = funcs.iter().find(|f| f.indicator == "MAVP").expect("MAVP"); + assert_eq!(mavp.input, ["close"]); + assert_eq!(mavp.passthrough, ["periods"]); + assert_eq!(mavp.default_formula(), "~close"); + + // every other indicator has no passthrough inputs + assert!( + funcs + .iter() + .all(|f| f.indicator == "MAVP" || f.passthrough.is_empty()) + ); + } +} diff --git a/codegen/src/render.rs b/codegen/src/render.rs new file mode 100644 index 000000000..761db2116 --- /dev/null +++ b/codegen/src/render.rs @@ -0,0 +1,904 @@ +//! R wrapper rendering +//! +//! Templates are plain R files with ${...} placeholders filled by +//! simple string replacement (see the README for the placeholder +//! table). The chart-method templates are *dual-backend*: one file +//! describes both the .plotly and the .ggplot method, and +//! render_backend() renders it once per backend by +//! +//! - keeping '#plotly#'/'#ggplot#'-prefixed lines only for their +//! backend (prefix stripped), and +//! - filling ${METHOD} (plotly|ggplot), ${PKG} (plotly|ggplot2) +//! and ${SUFFIX} (ly|gg) +//! +//! The camelCase alias block is marker-conditional the same way: +//! render_camel() keeps '#camel#'-prefixed lines (prefix stripped) +//! only when the camelCase name differs from the snake_case name. +//! +//! After rendering, hand-edited splice regions of the existing file +//! on disk are preserved by preserve_regions() (see main.rs). + +use crate::metadata::{MetaData, OptionalArg, OptionalType}; +use crate::tables::{ + ChartType, MOVING_AVERAGES, agnostic, camel_case_name, chart_type, function_name, + is_candlestick, ma_type, +}; + +/// The template files rendered by render_indicator(), +/// loaded once from 'codegen/templates/' +pub struct Templates { + pub indicator: String, + pub numeric: String, + pub rolling: String, + pub moving_average: String, + pub candlestick: String, + pub chart_main: String, + pub chart_subchart: String, + pub chart_moving_average: String, + pub chart_candlestick: String, +} + +impl Templates { + pub fn load(dir: &str) -> Templates { + let read = |name: &str| { + std::fs::read_to_string(format!("{dir}/{name}")) + .unwrap_or_else(|e| panic!("read {dir}/{name}: {e}")) + }; + + Templates { + indicator: read("indicator_template.R"), + numeric: read("numeric_template.R"), + rolling: read("rolling_template.R"), + moving_average: read("moving_average_template.R"), + candlestick: read("candlestick_template.R"), + chart_main: read("chart_main_template.R"), + chart_subchart: read("chart_subchart_template.R"), + chart_moving_average: read("chart_moving_average_template.R"), + chart_candlestick: read("chart_candlestick_template.R"), + } + } +} + +/// One chart backend of a dual-backend template +struct Backend { + /// ${METHOD}: the S3 class, and by convention also the builder + /// (build_plotly), the init helper (plotly_init), the local + /// object (plotly_object) and the splice-region names + /// (optional-plotly, plotly-assembly) + method: &'static str, + /// ${PKG}: the package name in comments ({ggplot2}-object) + pkg: &'static str, + /// ${SUFFIX}: the chart-helper suffix (add_last_value_ly, + /// pattern_gg) + suffix: &'static str, +} + +const PLOTLY: Backend = Backend { + method: "plotly", + pkg: "plotly", + suffix: "ly", +}; + +const GGPLOT: Backend = Backend { + method: "ggplot", + pkg: "ggplot2", + suffix: "gg", +}; + +/// Render a dual-backend chart template for one backend: keep +/// '#plotly#'/'#ggplot#'-prefixed lines only for their backend +/// (prefix stripped), then fill the backend placeholders +fn render_backend(template: &str, backend: &Backend) -> String { + let own = format!("#{}#", backend.method); + + let mut out = template + .lines() + .filter_map(|line| { + if let Some(rest) = line.strip_prefix(&own) { + Some(rest) + } else if line.starts_with("#plotly#") || line.starts_with("#ggplot#") { + None + } else { + Some(line) + } + }) + .collect::>() + .join("\n"); + + if template.ends_with('\n') { + out.push('\n'); + } + + // a marker-shaped line ('#word#...') surviving the filter is a + // typo'd or unknown backend prefix; left alone it would ship as + // a plain R comment, silently disabling the line in both + // backends + for line in out.lines() { + if let Some(rest) = line.trim_start().strip_prefix('#') { + if let Some(end) = rest.find('#') { + if end > 0 && rest[..end].chars().all(|c| c.is_ascii_alphanumeric()) { + panic!("unknown backend prefix in template line: {line}"); + } + } + } + } + + out.replace("${METHOD}", backend.method) + .replace("${PKG}", backend.pkg) + .replace("${SUFFIX}", backend.suffix) +} + +/// Keep '#camel#'-prefixed lines (prefix stripped) only when the +/// indicator has a distinct camelCase alias; for single-word names +/// (doji, aroon) the block would alias the function to itself +pub fn render_camel(template: &str, keep: bool) -> String { + let mut out = template + .lines() + .filter_map(|line| match line.strip_prefix("#camel#") { + Some(rest) => keep.then_some(rest), + None => Some(line), + }) + .collect::>() + .join("\n"); + + if template.ends_with('\n') { + out.push('\n'); + } + + out +} + +/// Render the R wrapper of an indicator from its family's main +/// template plus the conditional methods: +/// +/// - candlestick patterns (CDL*): 'candlestick_template.R' with +/// the chart methods from 'chart_candlestick_template.R' +/// - moving averages (see MOVING_AVERAGES): the spec-mode +/// 'moving_average_template.R' (.numeric baked in) with the +/// chart methods from 'chart_moving_average_template.R' +/// - rolling statistics (GroupId 'Statistic Functions'): +/// 'rolling_template.R', not plotable, .numeric baked in +/// - everything else: 'indicator_template.R'; univariate +/// indicators (a single input series) get the appended +/// .numeric method, chartable indicators (see CHART_TYPES) +/// the methods from 'chart_main_template.R' or +/// 'chart_subchart_template.R' +/// +/// Multi-entry placeholders (ARGS, PARGS) carry their own trailing +/// comma per entry so that indicators without optional inputs +/// render an empty line instead of a dangling comma +pub fn render_indicator(f: &MetaData, t: &Templates) -> String { + // the R function name, e.g. BBANDS -> bollinger_bands + let fun = function_name(&f.indicator); + + // the TA_MAType index literal, Some for the nine + // moving averages rendered in spec-mode + let ma_index = ma_type(&f.indicator); + + // default column formula, e.g. ~high + low + close + let formula = f.default_formula(); + + // the generic's formal arguments: the XML optional inputs, + // plus a spec-only timePeriod injected for moving averages + // whose C signature has no period (MAMA) so that every MA + // spec carries one for its downstream consumers. The injected + // formal is deliberately absent from the .Call() coercions + let mut formals = f.optional_input.clone(); + if ma_index.is_some() && !formals.iter().any(|a| a.name == "timePeriod") { + formals.insert( + 0, + OptionalArg { + name: "timePeriod".to_string(), + kind: OptionalType::Integer, + default: "30".to_string(), + description: "Number of period".to_string(), + }, + ); + } + + // the ${PARAM_DOCS} roxygen lines of the generic, one @param + // per optional input with its type, XML description and default, + // e.g. #' @param fastPeriod ([integer]). Number of period for + // the fast MA. Defaults to `12`. MAType formals additionally + // carry the index legend with the default's moving average + // spelled out inline. + // + // timePeriod and penetration are skipped: they are documented + // by the man-roxygen templates ('description.R' and + // 'rolling_description.R'). An empty result renders a blank + // roxygen line so the block stays contiguous + let param_docs = { + let docs = f + .passthrough + .iter() + .map(|p| { + format!( + "#' @param {p} ([numeric]). Vector of periods, one per observation of the input series." + ) + }) + .chain(formals + .iter() + .filter(|a| a.name != "timePeriod" && a.name != "penetration") + .map(|a| match a.kind { + OptionalType::MAType => { + let default_ma = MOVING_AVERAGES + .iter() + .find(|(_, index)| index.trim_end_matches('L') == a.default) + .map(|(ma, _)| *ma) + .unwrap_or_else(|| panic!("no moving average for TA_MAType {}", a.default)); + + format!( + "#' @param {} ([integer]). {}. Defaults to `{}` ([{}]). Can also be passed as talib::{}.", + a.name, a.description, a.default, default_ma, default_ma + ) + } + _ => format!( + "#' @param {} ([{}]). {}. Defaults to `{}`.", + a.name, + match a.kind { + OptionalType::Double => "double", + _ => "integer", + }, + a.description, + a.default + ), + })) + .collect::>() + .join("\n"); + + if docs.is_empty() { + "#'".to_string() + } else { + docs + } + }; + + // formals and pass-through arguments, + // e.g. 'timePeriod = 14,' and 'timePeriod = timePeriod,'. + // Passthrough inputs (MAVP: periods) lead as required formals + // without a default + let args = f + .passthrough + .iter() + .map(|p| format!("{p},")) + .chain( + formals + .iter() + .map(|a| format!("{} = {},", a.name, a.default)), + ) + .collect::>() + .join("\n\t"); + + let pargs = f + .passthrough + .iter() + .chain(formals.iter().map(|a| &a.name)) + .map(|name| format!("{name} = {name},")) + .collect::>() + .join("\n\t\t\t"); + + // the spec-mode list fields of the moving_average template: + // each formal round-trips as 'name = if (missing(name)) + // else as.(name)' in the list returned without 'x' + let spec_fields = formals + .iter() + .map(|a| match a.kind { + OptionalType::Double => format!( + "{name} = if (missing({name})) {} else as.double({name})", + a.default, + name = a.name + ), + _ => format!( + "{name} = if (missing({name})) {}L else as.integer({name})", + a.default, + name = a.name + ), + }) + .collect::>() + .join(",\n\t\t\t\t"); + + // the bare argument names of the chart label(), + // each with a leading comma: label("SMA", timePeriod) + let cargs = f + .optional_input + .iter() + .map(|a| format!(", {}", a.name)) + .collect::(); + + // the coerced optional inputs of the .Call() arguments + let coercions: Vec = f + .optional_input + .iter() + .map(|a| match a.kind { + OptionalType::Double => format!("as.double({})", a.name), + OptionalType::MAType => format!("as.maType({})", a.name), + _ => format!("as.integer({})", a.name), + }) + .collect(); + + // the coerced passthrough formals: required inputs are always + // double arrays in TA-Lib, so as.double() guards the type on + // the R side (the C side additionally length-checks against + // the first input series) + let passthrough: Vec = f + .passthrough + .iter() + .map(|p| format!("as.double({p})")) + .collect(); + + // the .Call() arguments: one constructed_series column per + // required input (the raw vector for the numeric method), + // then the coerced passthrough formals, followed by the + // coerced optional inputs + let c_signature = (1..=f.input.len()) + .map(|i| format!("constructed_series[[{i}]]")) + .chain(passthrough.iter().cloned()) + .chain(coercions.iter().cloned()) + .collect::>() + .join(",\n\t\t"); + + // the raw-vector series of the numeric/rolling path: the + // bivariate rolling statistics (BETA, CORREL: inReal0/inReal1, + // mined as x/y) take a pair of vectors, everything else a + // single 'x'. ${SERIES}/${PSERIES} render the formals and the + // forwarded arguments, one per line with a trailing comma + let series: &[&str] = if f.input == ["x", "y"] { + &["x", "y"] + } else { + &["x"] + }; + + let series_args = series + .iter() + .map(|s| format!("{s},")) + .collect::>() + .join("\n\t"); + + let pseries = series + .iter() + .map(|s| format!("{s} = {s},")) + .collect::>() + .join("\n\t\t"); + + let c_numeric = series + .iter() + .map(|s| format!("as.double({s})")) + .chain(passthrough.iter().cloned()) + .chain(coercions.iter().cloned()) + .collect::>() + .join(",\n\t\t"); + + // the .Call() arguments of the lookback wrapper: only the + // coerced optional inputs (see TA_LB_WRAPPER in src/wrapper.h). + // Each entry carries a *leading* comma so that indicators + // without optional inputs render .Call(C_impl_ta_X_lookback) + // without a dangling empty argument + let c_lookback = coercions + .iter() + .map(|c| format!(",\n\t\t{c}")) + .collect::(); + + // the camelCase alias; single-word indicator names camelCase + // to themselves, dropping the '#camel#' alias block instead + let camel = camel_case_name(&f.indicator); + let has_camel = camel != fun; + + // the camelCase link of the chained lookback assignment + // (BBANDS_lookback <- bollingerBands_lookback <- ...) + let camel_lookback = if has_camel { + format!("{camel}_lookback <- ") + } else { + String::new() + }; + + let fill = |template: &str| { + render_camel(template, has_camel) + .replace("${FUN}", fun) + .replace("${ALIAS}", &f.indicator) + .replace("${CAMEL_LOOKBACK}", &camel_lookback) + .replace("${CAMEL}", &camel) + .replace("${TITLE}", &f.title) + .replace( + "${FAMILY}", + &f.family + .replace("Math Operators", "Rolling Statistics") + .replace("Statistic Functions", "Rolling Statistics"), + ) + .replace("${FORMULA}", &formula) + .replace("${PARAM_DOCS}", ¶m_docs) + .replace("${ARGS}", &args) + .replace("${PARGS}", &pargs) + .replace("${C_SIGNATURE_LOOKBACK}", &c_lookback) + .replace("${C_SIGNATURE}", &c_signature) + .replace("${C_NUMERIC}", &c_numeric) + .replace("${SERIES}", &series_args) + .replace("${PSERIES}", &pseries) + .replace("${SPEC_FIELDS}", &spec_fields) + .replace("${MA_TYPE}", ma_index.unwrap_or("-1L")) + .replace("${CARGS}", &cargs) + .replace("${AGNOSTIC}", agnostic(&f.indicator)) + }; + + // both chart methods from one dual-backend template, + // .plotly before .ggplot, matching the existing wrappers + let chart = |template: &str| { + format!( + "{}\n{}", + fill(&render_backend(template, &PLOTLY)), + fill(&render_backend(template, &GGPLOT)) + ) + }; + + let out = if is_candlestick(&f.indicator) { + format!("{}\n{}", fill(&t.candlestick), chart(&t.chart_candlestick)) + } else if ma_index.is_some() { + format!( + "{}\n{}", + fill(&t.moving_average), + chart(&t.chart_moving_average) + ) + } else if f.family == "Statistic Functions" || f.family == "Math Operators" { + fill(&t.rolling) + } else { + let mut out = fill(&t.indicator); + + // univariate indicators (a single input series) + // carry a .numeric method + if f.input.len() == 1 { + out.push('\n'); + out.push_str(&fill(&t.numeric)); + } + + if let Some(kind) = chart_type(&f.indicator) { + out.push('\n'); + out.push_str(&chart(match kind { + ChartType::Main => &t.chart_main, + ChartType::Sub => &t.chart_subchart, + })); + } + + out + }; + + strip_blank_indentation(&out) +} + +/// Empty multi-entry placeholders (${ARGS}, ${PARGS}) leave their +/// line's bare indentation behind, e.g. a whitespace-only line +/// between 'cols,' and 'na.bridge = FALSE,' for indicators without +/// optional inputs, which air does not reformat away. Drop those +/// lines; truly empty lines (paragraph separators) are kept +fn strip_blank_indentation(rendered: &str) -> String { + let mut out: String = rendered + .lines() + .filter(|line| line.is_empty() || !line.trim().is_empty()) + .collect::>() + .join("\n"); + + if rendered.ends_with('\n') { + out.push('\n'); + } + + out +} + +/// Protected regions +/// +/// Content between '## splice::start' and '## splice::end' +/// marker lines survives regeneration: for every region present in +/// both the freshly rendered output and the previously generated +/// file, the rendered default is replaced by the existing content. +/// Regions absent from the existing file keep the rendered default +pub fn preserve_regions(rendered: &str, existing: &str) -> String { + let mut out = rendered.to_string(); + + // the regions of the rendered output, in order + let names: Vec = rendered + .lines() + .filter_map(|line| { + line.trim() + .strip_prefix("## splice:")? + .strip_suffix(":start") + .map(str::to_string) + }) + .collect(); + + // region_span() only ever matches the first occurrence of a + // name, so a duplicated name would silently lose the hand + // edits of every later occurrence + for (i, name) in names.iter().enumerate() { + if names[..i].contains(name) { + panic!("duplicate splice region '{name}' in rendered output"); + } + } + + // spans are recomputed per region since each + // replacement shifts the offsets after it + for name in names { + if let (Some((out_start, out_end)), Some((existing_start, existing_end))) = + (region_span(&out, &name), region_span(existing, &name)) + { + out.replace_range(out_start..out_end, &existing[existing_start..existing_end]); + } + } + + out +} + +/// The content span between a region's marker lines: starts on +/// the line after '## splice::start' and ends at the +/// beginning of the '## splice::end' line +fn region_span(text: &str, name: &str) -> Option<(usize, usize)> { + let start_marker = format!("## splice:{name}:start"); + let end_marker = format!("## splice:{name}:end"); + + let start = text.find(&start_marker)?; + let content_start = start + start_marker.len(); + let content_start = content_start + text[content_start..].find('\n')? + 1; + + let end = content_start + text[content_start..].find(&end_marker)?; + let content_end = text[..end].rfind('\n').map_or(0, |i| i + 1); + + Some((content_start, content_end)) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::metadata::{SAMPLE, parse_api}; + + #[test] + fn strips_blank_indentation() { + let rendered = "\ +stick_sandwich <- function( +\tx, +\tcols, +\t +\tna.bridge = FALSE, +\t...) { +} + +next_function\n"; + + // the whitespace-only argument line vanishes, + // the empty separator line stays + assert_eq!( + strip_blank_indentation(rendered), + "\ +stick_sandwich <- function( +\tx, +\tcols, +\tna.bridge = FALSE, +\t...) { +} + +next_function\n" + ); + } + + #[test] + fn renders_backend_variants() { + let template = "\ +${FUN}.${METHOD} <- function(x) { +#plotly#\tassert_plotly_object(x) +#ggplot#\tassert_ggplot2() +\t## construct {${PKG}}-object +\tadd_last_value_${SUFFIX}(x) +} +"; + + // each backend keeps its own conditional lines (prefix + // stripped) and fills the backend placeholders; the + // indicator placeholders are left for fill() + assert_eq!( + render_backend(template, &PLOTLY), + "\ +${FUN}.plotly <- function(x) { +\tassert_plotly_object(x) +\t## construct {plotly}-object +\tadd_last_value_ly(x) +} +" + ); + assert_eq!( + render_backend(template, &GGPLOT), + "\ +${FUN}.ggplot <- function(x) { +\tassert_ggplot2() +\t## construct {ggplot2}-object +\tadd_last_value_gg(x) +} +" + ); + } + + #[test] + fn preserves_protected_regions() { + let rendered = "\ +head +\t## splice:documentation:start +\tdefault docs +\t## splice:documentation:end +mid +\t## splice:plotly-assembly:start +\tdefault traces +\t## splice:plotly-assembly:end +tail +"; + let existing = "\ +old head +\t## splice:documentation:start +\tcustom docs +\tsecond line +\t## splice:documentation:end +old mid +\t## splice:plotly-assembly:start +\tcustom traces +\t## splice:plotly-assembly:end +old tail +"; + + // both regions carry over their existing content while + // everything outside the markers is regenerated + let preserved = preserve_regions(rendered, existing); + assert_eq!( + preserved, + "\ +head +\t## splice:documentation:start +\tcustom docs +\tsecond line +\t## splice:documentation:end +mid +\t## splice:plotly-assembly:start +\tcustom traces +\t## splice:plotly-assembly:end +tail +" + ); + + // no regions in the existing file: + // the rendered default is kept + assert_eq!(preserve_regions(rendered, "plain old file"), rendered); + + // emptied-out region in the existing + // file stays empty after regeneration + let emptied = "\ +\t## splice:documentation:start +\t## splice:documentation:end +"; + let preserved = preserve_regions(rendered, emptied); + assert!( + preserved.contains("\t## splice:documentation:start\n\t## splice:documentation:end") + ); + assert!(preserved.contains("default traces")); + } + + #[test] + fn renders_template() { + let funcs = parse_api(SAMPLE); + let templates = Templates::load(concat!(env!("CARGO_MANIFEST_DIR"), "/templates")); + + let rendered = render_indicator(&funcs[0], &templates); + + assert!(rendered.contains("bollinger_bands <- function(")); + assert!(rendered.contains("BBANDS <- bollinger_bands")); + assert!(rendered.contains("timePeriod = 5,")); + assert!(rendered.contains("deviationsUp = 2,")); + assert!(rendered.contains("default_formula = ~close,")); + assert!(rendered.contains("C_impl_ta_BBANDS,")); + assert!(rendered.contains("constructed_series[[1]]")); + assert!(rendered.contains("as.integer(timePeriod)")); + assert!(rendered.contains("as.double(deviationsUp)")); + assert!(!rendered.contains("${"), "unreplaced placeholder"); + + // the optional inputs are documented with type, description + // and default; timePeriod stays with the man-roxygen template + assert!(rendered.contains( + "#' @param deviationsUp ([double]). Deviation multiplier for upper band. Defaults to `2`." + )); + assert!(!rendered.contains("#' @param timePeriod")); + + // MAType formals carry the TA_MAType legend with the + // default's moving average spelled out inline + assert!(rendered.contains( + "#' @param maType ([integer]). Type of Moving Average. Defaults to `0` ([SMA]). Can also be passed as talib::SMA." + )); + + // univariate: the numeric method is appended + // after the matrix method with the raw vector + assert!(rendered.contains("bollinger_bands.numeric <- function(")); + assert!(rendered.contains("as.double(x)")); + + // the lookback wrapper passes only the + // coerced optional inputs to C + assert!(rendered.contains("bollinger_bands_lookback <- function(")); + assert!(rendered.contains( + "C_impl_ta_BBANDS_lookback,\n\t\tas.integer(timePeriod),\n\t\tas.double(deviationsUp),\n\t\tas.maType(maType)\n\t)" + )); + + // BBANDS is a Main chart indicator: the plotly and ggplot + // methods are rendered from the dual-backend template and + // draw onto the main chart state + assert!(rendered.contains("bollinger_bands.plotly <- function(")); + assert!(rendered.contains("bollinger_bands.ggplot <- function(")); + assert!(rendered.contains("## splice:optional-plotly:start")); + assert!(rendered.contains("## splice:ggplot-assembly:start")); + assert!(rendered.contains("state[[\"main\"]]")); + assert!(!rendered.contains("#plotly#"), "unstripped backend prefix"); + assert!(!rendered.contains("#ggplot#"), "unstripped backend prefix"); + + // CDL* renders from the candlestick template: normalized + // pattern codes, the named output column and the chart + // methods with pattern markers + let rendered = render_indicator(&funcs[1], &templates); + + assert!(rendered.contains("doji <- function(")); + assert!(rendered.contains("CDLDOJI <- doji")); + assert!(rendered.contains("candlestick_setting()")); + assert!(rendered.contains("default_formula = ~open + high + low + close,")); + assert!(rendered.contains("colnames(x) <- \"CDLDOJI\"")); + assert!(!rendered.contains(",,")); + assert!(!rendered.contains("${"), "unreplaced placeholder"); + + // CDLDOJI is OHLC order agnostic + assert!(rendered.contains("doji.plotly <- function(")); + assert!(rendered.contains("doji.ggplot <- function(")); + assert!(rendered.contains("pattern_ly(")); + assert!(rendered.contains("pattern_gg(")); + assert!(rendered.contains("agnostic = TRUE")); + + // the candlestick template carries + // no lookback and no numeric method + assert!(!rendered.contains("_lookback")); + assert!(!rendered.contains(".numeric")); + } + + #[test] + fn renders_camel_alias() { + let funcs = parse_api(SAMPLE); + let templates = Templates::load(concat!(env!("CARGO_MANIFEST_DIR"), "/templates")); + + // BBANDS carries a camelCase alias next to the uppercase + // one, and its lookback joins the chained assignment + let rendered = render_indicator(&funcs[0], &templates); + assert!(rendered.contains("bollingerBands <- bollinger_bands")); + assert!(rendered.contains( + "BBANDS_lookback <- bollingerBands_lookback <- bollinger_bands_lookback <- function(" + )); + assert!(!rendered.contains("#camel#"), "unstripped camel prefix"); + + // 'doji' camelCases to itself: the alias block is + // dropped and the lookback chain stays two-membered + let rendered = render_indicator(&funcs[1], &templates); + assert!(!rendered.contains("doji <- doji")); + assert!(rendered.contains("CDLDOJI_lookback <- doji_lookback <- function(")); + assert!(!rendered.contains("#camel#"), "unstripped camel prefix"); + } + + #[test] + fn renders_full_api() { + let xml = std::fs::read_to_string(concat!( + env!("CARGO_MANIFEST_DIR"), + "/../src/ta-lib/ta_func_api.xml" + )) + .expect("read ta_func_api.xml"); + let templates = Templates::load(concat!(env!("CARGO_MANIFEST_DIR"), "/templates")); + + let funcs = parse_api(&xml); + + for f in &funcs { + let rendered = render_indicator(f, &templates); + assert!( + !rendered.contains("${"), + "unreplaced placeholder in {}", + f.indicator + ); + assert!( + !rendered.contains("#plotly#") && !rendered.contains("#ggplot#"), + "unstripped backend prefix in {}", + f.indicator + ); + } + + let render = |abbreviation: &str| { + render_indicator( + funcs + .iter() + .find(|f| f.indicator == abbreviation) + .unwrap_or_else(|| panic!("{abbreviation} not parsed")), + &templates, + ) + }; + + // moving averages: spec-mode list with the TA_MAType + // index and the main-chart methods + let sma = render("SMA"); + assert!(sma.contains("simple_moving_average <- function(")); + assert!(sma.contains("maType = 0L")); + assert!( + sma.contains("timePeriod = if (missing(timePeriod)) 30L else as.integer(timePeriod)") + ); + assert!(sma.contains("legendgroup = \"MovingAverage\"")); + assert!(sma.contains("label(\"SMA\", timePeriod)")); + assert!(sma.contains("simple_moving_average.plotly <- function(")); + assert!(sma.contains("simple_moving_average.ggplot <- function(")); + + // MAMA: the injected spec-only timePeriod is a formal and + // a spec field but is absent from the .Call() arguments + let mama = render("MAMA"); + assert!( + mama.contains("timePeriod = if (missing(timePeriod)) 30L else as.integer(timePeriod)") + ); + assert!(mama.contains( + "constructed_series[[1]],\n\t\tas.double(fastLimit),\n\t\tas.double(slowLimit)" + )); + + // every optional input beyond timePeriod/penetration is + // documented with type, description and default + let macd = render("MACD"); + assert!(macd.contains( + "#' @param fastPeriod ([integer]). Number of period for the fast MA. Defaults to `12`." + )); + assert!(macd.contains( + "#' @param signalPeriod ([integer]). Smoothing for the signal line (nb of period). Defaults to `9`." + )); + + // MAVP: the passthrough 'periods' leads the formals as a + // required argument (no default) and is passed to .Call() + // coerced, between the series column and the coerced + // optional inputs + let mavp = render("MAVP"); + assert!(mavp.contains( + "variable_moving_average_period <- function(\n\tx,\n\tcols,\n\tperiods,\n\tminimumPeriod = 2," + )); + assert!(mavp.contains("default_formula = ~close,")); + assert!(mavp.contains( + "constructed_series[[1]],\n\t\tas.double(periods),\n\t\tas.integer(minimumPeriod)" + )); + assert!(mavp.contains("periods = periods,")); + assert!(mavp.contains( + "#' @param periods ([numeric]). Vector of periods, one per observation of the input series." + )); + + // MAVP is univariate by series count: the numeric method + // passes the raw vector plus the passthrough + assert!(mavp.contains("variable_moving_average_period.numeric <- function(")); + assert!(mavp.contains("as.double(x),\n\t\tas.double(periods),")); + + // the lookback wrapper keeps taking only the + // coerced optional inputs + assert!(mavp.contains( + "C_impl_ta_MAVP_lookback,\n\t\tas.integer(minimumPeriod),\n\t\tas.integer(maximumPeriod),\n\t\tas.maType(maType)\n\t)" + )); + + // rolling statistics: protected .Call() region, + // no chart methods + let stddev = render("STDDEV"); + assert!(stddev.contains("rolling_standard_deviation <- function(")); + assert!( + stddev.contains( + "#' @param deviations ([double]). Number of deviations. Defaults to `1`." + ) + ); + assert!(!stddev.contains("#' @param timePeriod")); + assert!(stddev.contains("@template rolling_returns")); + assert!(stddev.contains("## splice:call:start")); + assert!(stddev.contains("as.double(x),")); + assert!(!stddev.contains("as.double(y)")); + assert!(!stddev.contains(".plotly")); + assert!(!stddev.contains(".ggplot")); + + // the bivariate rolling statistics (inReal0/inReal1) take + // the pair x/y and pass both series to the C routine + let correl = render("CORREL"); + assert!(correl.contains("rolling_correlation <- function(\n\tx,\n\ty,")); + assert!(correl.contains("as.double(x),\n\t\tas.double(y),\n\t\tas.integer(timePeriod)")); + assert!(correl.contains("x = x,\n\t\ty = y,")); + + // candlesticks: the agnostic flag comes + // from AGNOSTIC_PATTERNS + assert!(render("CDLDOJI").contains("agnostic = TRUE")); + assert!(render("CDLHAMMER").contains("agnostic = FALSE")); + } +} diff --git a/codegen/src/tables.rs b/codegen/src/tables.rs new file mode 100644 index 000000000..a0b0376fa --- /dev/null +++ b/codegen/src/tables.rs @@ -0,0 +1,384 @@ +//! The hand-maintained lookup tables +//! +//! Everything else is mined from the TA-Lib sources; these tables +//! layer the per-indicator knowledge the sources cannot provide on +//! top: the R function name, the chart type, the family +//! classifications and the exclusions. This is the one file to +//! touch when customizing how an indicator is generated. + +use crate::metadata::{camel_case, tag_blocks, tag_text}; + +/// Maps to snake_case indicator names +/// and defaults to +pub const FUNCTION_NAMES: &[(&str, &str)] = &[ + ("ACCBANDS", "acceleration_bands"), + ("AD", "chaikin_accumulation_distribution_line"), + ("ADOSC", "chaikin_accumulation_distribution_oscillator"), + ("ADX", "average_directional_movement_index"), + ("ADXR", "average_directional_movement_index_rating"), + ("APO", "absolute_price_oscillator"), + ("AROON", "aroon"), + ("AROONOSC", "aroon_oscillator"), + ("ATR", "average_true_range"), + ("AVGPRICE", "average_price"), + ("AVGDEV", "average_deviation"), + ("BBANDS", "bollinger_bands"), + ("BETA", "rolling_beta"), + ("BOP", "balance_of_power"), + ("CCI", "commodity_channel_index"), + ("CDL2CROWS", "two_crows"), + ("CDL3BLACKCROWS", "three_black_crows"), + ("CDL3INSIDE", "three_inside"), + ("CDL3LINESTRIKE", "three_line_strike"), + ("CDL3OUTSIDE", "three_outside"), + ("CDL3STARSINSOUTH", "three_stars_in_the_south"), + ("CDL3WHITESOLDIERS", "three_white_soldiers"), + ("CDLABANDONEDBABY", "abandoned_baby"), + ("CDLADVANCEBLOCK", "advance_block"), + ("CDLBELTHOLD", "belt_hold"), + ("CDLBREAKAWAY", "break_away"), + ("CDLCLOSINGMARUBOZU", "closing_marubozu"), + ("CDLCONCEALBABYSWALL", "concealing_baby_swallow"), + ("CDLCOUNTERATTACK", "counter_attack"), + ("CDLDARKCLOUDCOVER", "dark_cloud_cover"), + ("CDLDOJI", "doji"), + ("CDLDOJISTAR", "doji_star"), + ("CDLDRAGONFLYDOJI", "dragonfly_doji"), + ("CDLENGULFING", "engulfing"), + ("CDLEVENINGDOJISTAR", "evening_doji_star"), + ("CDLEVENINGSTAR", "evening_star"), + ("CDLGAPSIDESIDEWHITE", "gaps_side_white"), + ("CDLGRAVESTONEDOJI", "gravestone_doji"), + ("CDLHAMMER", "hammer"), + ("CDLHANGINGMAN", "hanging_man"), + ("CDLHARAMI", "harami"), + ("CDLHARAMICROSS", "harami_cross"), + ("CDLHIGHWAVE", "high_wave"), + ("CDLHIKKAKE", "hikakke"), + ("CDLHIKKAKEMOD", "hikakke_mod"), + ("CDLHOMINGPIGEON", "homing_pigeon"), + ("CDLIDENTICAL3CROWS", "three_identical_crows"), + ("CDLINNECK", "in_neck"), + ("CDLINVERTEDHAMMER", "inverted_hammer"), + ("CDLKICKING", "kicking"), + ("CDLKICKINGBYLENGTH", "kicking_baby_length"), + ("CDLLADDERBOTTOM", "ladder_bottom"), + ("CDLLONGLEGGEDDOJI", "long_legged_doji"), + ("CDLLONGLINE", "long_line"), + ("CDLMARUBOZU", "marubozu"), + ("CDLMATCHINGLOW", "matching_low"), + ("CDLMATHOLD", "mat_hold"), + ("CDLMORNINGDOJISTAR", "morning_doji_star"), + ("CDLMORNINGSTAR", "morning_star"), + ("CDLONNECK", "on_neck"), + ("CDLPIERCING", "piercing"), + ("CDLRICKSHAWMAN", "rickshaw_man"), + ("CDLRISEFALL3METHODS", "rise_fall_3_methods"), + ("CDLSEPARATINGLINES", "separating_lines"), + ("CDLSHOOTINGSTAR", "shooting_star"), + ("CDLSHORTLINE", "short_line"), + ("CDLSPINNINGTOP", "spinning_top"), + ("CDLSTALLEDPATTERN", "stalled_pattern"), + ("CDLSTICKSANDWICH", "stick_sandwich"), + ("CDLTAKURI", "takuri"), + ("CDLTASUKIGAP", "tasuki_gap"), + ("CDLTHRUSTING", "thrusting"), + ("CDLTRISTAR", "tristar"), + ("CDLUNIQUE3RIVER", "unique_3_river"), + ("CDLUPSIDEGAP2CROWS", "upside_gap_2_crows"), + ("CDLXSIDEGAP3METHODS", "xside_gap_3_methods"), + ("CMO", "chande_momentum_oscillator"), + ("CORREL", "rolling_correlation"), + ("DEMA", "double_exponential_moving_average"), + ("DX", "directional_movement_index"), + ("EMA", "exponential_moving_average"), + ("HT_DCPERIOD", "dominant_cycle_period"), + ("HT_DCPHASE", "dominant_cycle_phase"), + ("HT_PHASOR", "phasor_components"), + ("HT_SINE", "sine_wave"), + ("HT_TRENDLINE", "trendline"), + ("HT_TRENDMODE", "trend_cycle_mode"), + ("IMI", "intraday_movement_index"), + ("KAMA", "kaufman_adaptive_moving_average"), + ("MAVP", "variable_moving_average_period"), + ("MACD", "moving_average_convergence_divergence"), + ("MACDEXT", "extended_moving_average_convergence_divergence"), + ("MACDFIX", "fixed_moving_average_convergence_divergence"), + ("MAMA", "mesa_adaptive_moving_average"), + ("MAX", "rolling_maximum"), + ("MEDPRICE", "median_price"), + ("MFI", "money_flow_index"), + ("MIDPRICE", "midpoint_price"), + ("MIDPOINT", "midpoint_period"), + ("MIN", "rolling_minimum"), + ("MINUS_DI", "minus_directional_indicator"), + ("MINUS_DM", "minus_directional_movement"), + ("MOM", "momentum"), + ("NATR", "normalized_average_true_range"), + ("OBV", "on_balance_volume"), + ("PLUS_DI", "plus_directional_indicator"), + ("PLUS_DM", "plus_directional_movement"), + ("PPO", "percentage_price_oscillator"), + ("ROC", "rate_of_change"), + ("ROCR", "ratio_of_change"), + ("RSI", "relative_strength_index"), + ("SAR", "parabolic_stop_and_reverse"), + ("SAREXT", "extended_parabolic_stop_and_reverse"), + ("SMA", "simple_moving_average"), + ("STDDEV", "rolling_standard_deviation"), + ("STOCH", "stochastic"), + ("STOCHF", "fast_stochastic"), + ("STOCHRSI", "stochastic_relative_strength_index"), + ("SUM", "rolling_sum"), + ("T3", "t3_exponential_moving_average"), + ("TEMA", "triple_exponential_moving_average"), + ("TRANGE", "true_range"), + ("TRIMA", "triangular_moving_average"), + ("TRIX", "triple_exponential_average"), + ("TYPPRICE", "typical_price"), + ("ULTOSC", "ultimate_oscillator"), + ("VAR", "rolling_variance"), + ("VOLUME", "trading_volume"), + ("WCLPRICE", "weighted_close_price"), + ("WILLR", "williams_oscillator"), + ("WMA", "weighted_moving_average"), +]; + +/// The snake_case R name of an indicator, +/// e.g. BBANDS -> bollinger_bands +pub fn function_name(abbreviation: &str) -> &str { + FUNCTION_NAMES + .iter() + .find(|(alias, _)| *alias == abbreviation) + .map(|(_, fun)| *fun) + .unwrap_or(abbreviation) +} + +/// The camelCase R name of an indicator, +/// e.g. BBANDS -> bollingerBands +pub fn camel_case_name(abbreviation: &str) -> String { + camel_case(function_name(abbreviation)) +} + +/// Main indicators overlay the candlestick chart itself while +/// Sub indicators get their own panel below it. Indicators absent +/// from CHART_TYPES are not chartable and get no chart methods +#[derive(Debug, PartialEq)] +pub enum ChartType { + Main, + Sub, +} + +pub const CHART_TYPES: &[(&str, ChartType)] = &[ + ("ACCBANDS", ChartType::Main), + ("AD", ChartType::Sub), + ("ADOSC", ChartType::Sub), + ("ADX", ChartType::Sub), + ("ADXR", ChartType::Sub), + ("APO", ChartType::Sub), + ("AROON", ChartType::Sub), + ("AROONOSC", ChartType::Sub), + ("ATR", ChartType::Sub), + ("BBANDS", ChartType::Main), + ("BOP", ChartType::Sub), + ("CCI", ChartType::Sub), + ("CMO", ChartType::Sub), + ("DX", ChartType::Sub), + ("HT_DCPERIOD", ChartType::Sub), + ("HT_DCPHASE", ChartType::Sub), + ("HT_PHASOR", ChartType::Sub), + ("HT_SINE", ChartType::Sub), + ("HT_TRENDLINE", ChartType::Main), + ("HT_TRENDMODE", ChartType::Sub), + ("IMI", ChartType::Sub), + ("MAVP", ChartType::Main), + ("MACD", ChartType::Sub), + ("MACDEXT", ChartType::Sub), + ("MACDFIX", ChartType::Sub), + ("MFI", ChartType::Sub), + ("MIDPOINT", ChartType::Main), + ("MIDPRICE", ChartType::Main), + ("MINUS_DI", ChartType::Sub), + ("MINUS_DM", ChartType::Sub), + ("MOM", ChartType::Sub), + ("NATR", ChartType::Sub), + ("OBV", ChartType::Sub), + ("PLUS_DI", ChartType::Sub), + ("PLUS_DM", ChartType::Sub), + ("PPO", ChartType::Sub), + ("ROC", ChartType::Sub), + ("ROCR", ChartType::Sub), + ("RSI", ChartType::Sub), + ("SAR", ChartType::Main), + ("SAREXT", ChartType::Main), + ("STOCH", ChartType::Sub), + ("STOCHF", ChartType::Sub), + ("STOCHRSI", ChartType::Sub), + ("TRANGE", ChartType::Sub), + ("TRIX", ChartType::Sub), + ("ULTOSC", ChartType::Sub), + ("VOLUME", ChartType::Sub), + ("WILLR", ChartType::Sub), +]; + +pub fn chart_type(abbreviation: &str) -> Option<&'static ChartType> { + CHART_TYPES + .iter() + .find(|(alias, _)| *alias == abbreviation) + .map(|(_, kind)| kind) +} + +/// The TA-Lib moving averages and their TA_MAType index, +/// rendered via 'codegen/templates/moving_average_template.R'. +/// The index fills ${MA_TYPE} in the spec-mode list returned +/// when the MA is called without 'x' (used by e.g. stochastic() +/// to construct its smoothing lines) +pub const MOVING_AVERAGES: &[(&str, &str)] = &[ + ("SMA", "0L"), + ("EMA", "1L"), + ("WMA", "2L"), + ("DEMA", "3L"), + ("TEMA", "4L"), + ("TRIMA", "5L"), + ("KAMA", "6L"), + ("MAMA", "7L"), + ("T3", "8L"), +]; + +/// The TA_MAType index literal of a moving average; +/// None for everything that is not a moving average +pub fn ma_type(indicator: &str) -> Option<&'static str> { + MOVING_AVERAGES + .iter() + .find(|(abbreviation, _)| *abbreviation == indicator) + .map(|(_, index)| *index) +} + +/// The candlestick patterns (Abbreviation starting with "CDL") +/// that are OHLC order agnostic; fills ${AGNOSTIC} with TRUE in +/// the pattern_ly()/pattern_gg() chart markers +pub const AGNOSTIC_PATTERNS: &[&str] = &[ + "CDLCLOSINGMARUBOZU", + "CDLDOJI", + "CDLHIGHWAVE", + "CDLKICKINGBYLENGTH", + "CDLLONGLEGGEDDOJI", + "CDLLONGLINE", + "CDLPIERCING", + "CDLSHOOTINGSTAR", + "CDLSHORTLINE", +]; + +/// Returns true if the indicator is +/// a candlestick pattern +pub fn is_candlestick(indicator: &str) -> bool { + indicator.starts_with("CDL") +} + +/// The R literal for the pattern's OHLC order agnosticism +pub fn agnostic(indicator: &str) -> &'static str { + if AGNOSTIC_PATTERNS.contains(&indicator) { + "TRUE" + } else { + "FALSE" + } +} + +/// Indicators excluded from porting altogether, by TA-Lib +/// abbreviation: filtered out of both the C wrapper generation +/// (src/TA-Lib.h) and the R wrapper generation (R/ta_*.R) +pub const EXCLUDED_INDICATORS: &[&str] = &[ + "MA", + "ROC", + "ROCP", + "ROCR100", + "LINEARREG", + "LINEARREG_ANGLE", + "LINEARREG_SLOPE", + "LINEARREG_INTERCEPT", + "TSF", + // Math operators + "ADD", + "DIV", + "MAXINDEX", + "MININDEX", + "MINMAX", + "MINMAXINDEX", + "MULT", + "SUB", +]; + +/// GroupIds excluded from generation altogether; +/// R already ships vectorized math (sqrt, log, sin, ...) +/// so the Math Transform indicators are redundant +pub const EXCLUDED_GROUPS: &[&str] = &["Math Transform"]; + +/// Returns true if the indicator should be +/// skipped by the generators +pub fn is_excluded(indicator: &str) -> bool { + EXCLUDED_INDICATORS.contains(&indicator) +} + +/// All excluded abbreviations, listed directly or via their GroupId; +/// mined from 'src/ta-lib/ta_func_api.xml' since the C generation +/// inputs (ta_func_list.txt, ta_func.h) carry no group information +pub fn excluded_indicators(xml: &str) -> Vec { + tag_blocks(xml, "FinancialFunction") + .iter() + .filter(|block| EXCLUDED_GROUPS.contains(&tag_text(block, "GroupId").expect("GroupId"))) + .map(|block| { + tag_text(block, "Abbreviation") + .expect("Abbreviation") + .to_string() + }) + .chain(EXCLUDED_INDICATORS.iter().map(|s| s.to_string())) + .collect() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn function_name_falls_back_to_abbreviation() { + assert_eq!(function_name("BBANDS"), "bollinger_bands"); + assert_eq!(function_name("NOT_A_REAL_FUNC"), "NOT_A_REAL_FUNC"); + } + + #[test] + fn camel_case_name_derives_from_snake_case() { + assert_eq!(camel_case_name("BBANDS"), "bollingerBands"); + assert_eq!(camel_case_name("RSI"), "relativeStrengthIndex"); + assert_eq!(camel_case_name("CDLRISEFALL3METHODS"), "riseFall3Methods"); + assert_eq!(camel_case_name("T3"), "t3ExponentialMovingAverage"); + } + + #[test] + fn excludes_by_group() { + let xml = "\ + + ACOS + Math Transform + + + ADD + Math Operators + + + BBANDS + Overlap Studies +"; + + let excluded = excluded_indicators(xml); + + // group-mined abbreviations are in, the rest are not + assert!(excluded.contains(&"ACOS".to_string())); + assert!(excluded.contains(&"ADD".to_string())); + assert!(!excluded.contains(&"BBANDS".to_string())); + + // the name-based list is chained in + for name in EXCLUDED_INDICATORS { + assert!(excluded.contains(&name.to_string())); + } + } +} diff --git a/codegen/src/testthat.rs b/codegen/src/testthat.rs new file mode 100644 index 000000000..0de023e74 --- /dev/null +++ b/codegen/src/testthat.rs @@ -0,0 +1,533 @@ +//! testthat file generation +//! +//! Renders one testthat file per indicator, written to +//! 'tests/testthat/test-ta_.R' by main() and overwritten on +//! every run (no protected regions). What a file contains follows +//! from the metadata: +//! +//! - rolling statistics (GroupId 'Statistic Functions'): a short +//! fast-track file (',y=SPY[,2]' appended for the bivariate +//! BETA/CORREL) +//! - chartable indicators: .plotly/.ggplot method tests, including +//! candlesticks and moving averages whose chart methods render +//! from their own templates +//! - univariate indicators (a single input series): a .numeric +//! method test + +use crate::metadata::MetaData; +use crate::render::render_camel; +use crate::tables::{camel_case_name, chart_type, function_name, is_candlestick, ma_type}; + +const HEADER: &str = "\ +## autogenerated unit-test +## from codegen/ +## the file will be overwritten in the next iteration +## +## author: Serkan Korkmaz +"; + +const ROLLING_TESTS: &str = r#" +## test that the function runs without +## any conditions +testthat::test_that(desc = 'Runs without *any* conditions', code = { + + output <- testthat::expect_no_condition( + { + ${FUN}( + x = SPY[,1]${ADDITIONAL} + ) + } + ) +}) + +## test that the length of the input +## matches the output +testthat::test_that(desc = 'Length in, length out', code = { + testthat::expect_equal( + object = length( + ${FUN}( + x = SPY[,1]${ADDITIONAL} + ) + ), + expected = length(SPY[,1]) + ) +}) + +## test that the output is a vector +testthat::test_that(desc = 'Output type', code = { + +output <- ${FUN}( + x = SPY[,1]${ADDITIONAL} + ) + +testthat::expect_true( + typeof(output) == "double" || typeof(output) == "integer" + ) + + testthat::expect_true( + 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]) + ) + +} +) +"#; + +const STANDARD_TESTS: &str = r#" +## alias and function similarity +## checks this ensures that +## ${FUN} and ${ALIAS} produces the same results +testthat::test_that(desc = 'Alias and function similarity', code = { + + ## 1) test that the alias and + ## function returns the same values + output <- ${FUN}(SPY${PASS_SPY}) + alias <- ${ALIAS}(SPY${PASS_SPY}) + + ## 1.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = alias + ) +#camel# +#camel# ## 2) test that the camelCase alias +#camel# ## returns the same values +#camel# camel <- ${CAMEL}(SPY${PASS_SPY}) +#camel# +#camel# ## 2.1) check if the values +#camel# ## are equal +#camel# testthat::expect_equal( +#camel# object = output, +#camel# expected = camel +#camel# ) + +}) + +## type-checks for data.frames and +## matrices +## +## object +testthat::test_that(desc = 'Class in, class out ()', code = { + ## 1) check that the output class + ## matches the input class + testthat::expect_true( + inherits(${FUN}(SPY${PASS_SPY}), class(SPY)) + ) + +}) + +## object +testthat::test_that(desc = 'Class in, class out ()', code = { + ## 1) check that the output class + ## matches the input class + testthat::expect_true( + inherits(${FUN}(BTC${PASS_BTC}), class(BTC)) + ) +}) + +## check that the default calls +## matches that of the constructed call +## with default values. +## +## NOTE: This test is more of a test of the internal +## series() function +testthat::test_that(desc = 'Default calls', code = { + testthat::expect_equal( + object = ${FUN}( + BTC${PASS_BTC} + ), + expected = ${FUN}( + BTC, + cols = ${FORMULA}${PASS_BTC} + ) + ) +}) + +## check that the length of the input +## matches the output length with na.bridge = TRUE +## +## object +testthat::test_that(desc = 'Equal length of input and output for with na.bridge = TRUE', code = { + testthat::expect_equal( + object = nrow(${FUN}( + ATOM${PASS_ATOM}, + na.bridge = TRUE + )), + expected = nrow(ATOM) + ) +}) + +## check that the rownames are being +## respected for with na.bridge = TRUE +testthat::test_that(desc = 'Row names are respected for , na.bridge = TRUE', code = { + ## extract row names + x_names <- row.names(ATOM) + + ## calculate indicator + indicator <- ${FUN}(ATOM${PASS_ATOM}, na.bridge = TRUE) + + testthat::expect_equal( + object = x_names, + expected = rownames(indicator) + ) +}) + +## check that the length of the input +## matches the output length +## +## object +testthat::test_that(desc = 'Equal length of input and output for ', code = { + testthat::expect_equal( + object = nrow(${FUN}( + BTC${PASS_BTC} + )), + expected = nrow(BTC) + ) +}) + +## check that the rownames are being +## respected for +testthat::test_that(desc = 'Row names are respected for ', code = { + ## extract row names + x_names <- row.names(BTC) + + ## calculate indicator + indicator <- ${FUN}(BTC${PASS_BTC}) + + testthat::expect_equal( + object = x_names, + expected = rownames(indicator) + ) +}) + +## object +testthat::test_that(desc = 'Equal length of input and output for ', code = { + testthat::expect_equal( + object = nrow(${FUN}( + SPY${PASS_SPY} + )), + expected = nrow(SPY) + ) +}) + +## check that the rownames are being +## respected for +testthat::test_that(desc = 'Row names are respected for ', code = { + ## extract row names + ## NOTE: by default the SPY has no + ## rownames + rownames(SPY) <- paste0("row",1:nrow(SPY)) + + ## calculate indicator + indicator <- ${FUN}(SPY${PASS_SPY}) + + testthat::expect_equal( + object = paste0("row",1:nrow(SPY)), + expected = rownames(indicator) + ) +}) + +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + +output <- attr( + ${FUN}(x = SPY${PASS_SPY}), + "lookback" +) + +testthat::expect_equal( + object = output, + expected = lookback(FUN = ${FUN}, x = SPY${PASS_SPY}) + ) +#camel# +#camel### the camelCase lookback alias +#camel### is the function itself +#camel#testthat::expect_identical( +#camel# object = ${CAMEL}_lookback, +#camel# expected = ${FUN}_lookback +#camel# ) + +} +) +"#; + +const PLOTLY_TESTS: &str = r#" +## -method checks for +## and +## +## checks +testthat::test_that(desc = '-methods for ', code = { + ## check that ${FUN} can + ## use without any issues + output <- testthat::expect_no_error( + { + chart(BTC) + indicator(${FUN}${PASS_BTC}) + } + ) + + ## check that the output + ## is a -object + testthat::expect_true( + inherits(output, "plotly") + ) +}) + +## checks +testthat::test_that(desc = '-methods for ', code = { + ## check that ${FUN} can + ## use without any issues + output <- testthat::expect_no_error( + { + chart(SPY) + indicator(${FUN}${PASS_SPY}) + } + ) + + ## check that the output + ## is a -object + testthat::expect_true( + inherits(output, "plotly") + ) +}) +"#; + +const GGPLOT_TESTS: &str = r#" +## -method checks for +## and +## +## checks +testthat::test_that(desc = '-methods for ', code = { + testthat::skip_if_not_installed("ggplot2") + + ## check that ${FUN} can + ## use without any issues + output <- testthat::expect_no_error( + { + options(talib.chart.backend = "ggplot2") + on.exit(options(talib.chart.backend = "plotly")) + chart(BTC) + indicator(${FUN}${PASS_BTC}) + } + ) + + ## check that the output + ## is a -object or + testthat::expect_true( + inherits(output, "gg") || inherits(output, "talib_chart") + ) +}) + +## checks +testthat::test_that(desc = '-methods for ', code = { + testthat::skip_if_not_installed("ggplot2") + + ## check that ${FUN} can + ## use without any issues + output <- testthat::expect_no_error( + { + options(talib.chart.backend = "ggplot2") + on.exit(options(talib.chart.backend = "plotly")) + chart(SPY) + indicator(${FUN}${PASS_SPY}) + } + ) + + ## check that the output + ## is a -object or + testthat::expect_true( + inherits(output, "gg") || inherits(output, "talib_chart") + ) +}) +"#; + +const NUMERIC_TESTS: &str = r#" +## check that methods runs without +## issues and returns proper lengths +testthat::test_that(desc = ' methods', code = { + ## check that the method + ## runs + x <- testthat::expect_no_condition( + ${FUN}(BTC[[1]]${PASS_BTC}) + ) + + target_length <- length(BTC[[1]]) + + 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(is.matrix(x)) + testthat::expect_equal(nrow(x), target_length) + } +}) +"#; + +/// Render the testthat file of an indicator +pub fn render_test(f: &MetaData) -> String { + let fun = function_name(&f.indicator); + + // rolling statistics fast-track: a short univariate file, + // with the second input series of BETA/CORREL passed as 'y' + if f.family == "Statistic Functions" || f.family == "Math Operators" { + let additional = if f.input.len() > 1 { ",y=SPY[,2]" } else { "" }; + + return format!( + "{HEADER}{}", + ROLLING_TESTS + .replace("${FUN}", fun) + .replace("${ADDITIONAL}", additional) + ); + } + + // passthrough inputs (MAVP: periods) are required formals, so + // every call site supplies a deterministic full-length vector + // matched to its dataset via the ${PASS_} placeholders + let pass = |data: &str| { + f.passthrough + .iter() + .map(|p| format!(", {p} = rep(5, nrow({data}))")) + .collect::() + }; + + // the camelCase alias; single-word indicator names camelCase + // to themselves, dropping the '#camel#' test lines instead + let camel = camel_case_name(&f.indicator); + let has_camel = camel != fun; + + let fill = |template: &str| { + render_camel(template, has_camel) + .replace("${FUN}", fun) + .replace("${ALIAS}", &f.indicator) + .replace("${CAMEL}", &camel) + .replace("${FORMULA}", &f.default_formula()) + .replace("${PASS_SPY}", &pass("SPY")) + .replace("${PASS_BTC}", &pass("BTC")) + .replace("${PASS_ATOM}", &pass("ATOM")) + }; + + let mut out = format!("{HEADER}{}", fill(STANDARD_TESTS)); + + // chartable indicators: candlesticks and moving averages carry + // their chart methods regardless of CHART_TYPES + let chartable = chart_type(&f.indicator).is_some() + || is_candlestick(&f.indicator) + || ma_type(&f.indicator).is_some(); + + if chartable { + out.push_str(&fill(PLOTLY_TESTS)); + out.push_str(&fill(GGPLOT_TESTS)); + } + + // univariate indicators carry a .numeric method + if f.input.len() == 1 { + out.push_str(&fill(NUMERIC_TESTS)); + } + + out +} + +#[cfg(test)] +mod tests { + use super::*; + + fn meta(indicator: &str, family: &str, input: &[&str]) -> MetaData { + MetaData { + indicator: indicator.to_string(), + family: family.to_string(), + input: input.iter().map(|s| s.to_string()).collect(), + ..Default::default() + } + } + + #[test] + fn renders_standard_chartable_test() { + let rendered = render_test(&meta("BBANDS", "Overlap Studies", &["close"])); + + assert!(rendered.contains("output <- bollinger_bands(SPY)")); + assert!(rendered.contains("alias <- BBANDS(SPY)")); + assert!(rendered.contains("camel <- bollingerBands(SPY)")); + assert!(rendered.contains("object = bollingerBands_lookback,")); + assert!(!rendered.contains("#camel#"), "unstripped camel prefix"); + assert!(rendered.contains("cols = ~close")); + assert!(rendered.contains("-methods for ")); + assert!(rendered.contains("-methods for ")); + assert!(rendered.contains(" methods")); + assert!(!rendered.contains("${"), "unreplaced placeholder"); + } + + #[test] + fn renders_candlestick_test_without_numeric() { + let rendered = render_test(&meta( + "CDLDOJI", + "Pattern Recognition", + &["open", "high", "low", "close"], + )); + + assert!(rendered.contains("cols = ~open + high + low + close")); + assert!(rendered.contains("-methods for ")); + assert!(!rendered.contains(" methods")); + + // 'doji' camelCases to itself: + // the camel test lines are dropped + assert!(!rendered.contains("camel <-")); + assert!(!rendered.contains("#camel#"), "unstripped camel prefix"); + } + + #[test] + fn renders_passthrough_args() { + let mut m = meta("MAVP", "Overlap Studies", &["close"]); + m.passthrough.push("periods".to_string()); + + let rendered = render_test(&m); + + // every call site supplies a full-length periods vector + // matched to its dataset + assert!( + rendered.contains("variable_moving_average_period(SPY, periods = rep(5, nrow(SPY)))") + ); + assert!(rendered.contains("cols = ~close, periods = rep(5, nrow(BTC))")); + assert!( + rendered + .contains("indicator(variable_moving_average_period, periods = rep(5, nrow(BTC)))") + ); + assert!( + rendered + .contains("variable_moving_average_period(BTC[[1]], periods = rep(5, nrow(BTC)))") + ); + assert!(!rendered.contains("${"), "unreplaced placeholder"); + } + + #[test] + fn renders_rolling_tests() { + let rendered = render_test(&meta("STDDEV", "Statistic Functions", &["close"])); + + assert!(rendered.contains("Runs without *any* conditions")); + assert!(rendered.contains("x = SPY[,1]\n")); + assert!(!rendered.contains("y=SPY[,2]")); + assert!(!rendered.contains("Alias and function similarity")); + + // the bivariate rolling statistics pass + // the second column as 'y' + let rendered = render_test(&meta("BETA", "Statistic Functions", &["close", "close"])); + assert!(rendered.contains("x = SPY[,1],y=SPY[,2]")); + } +} diff --git a/codegen/templates/candlestick_template.R b/codegen/templates/candlestick_template.R new file mode 100644 index 000000000..e0733a682 --- /dev/null +++ b/codegen/templates/candlestick_template.R @@ -0,0 +1,165 @@ +#' @export +#' @family ${FAMILY} +#' +#' @title ${TITLE} +#' @templateVar .title ${TITLE} +#' @templateVar .author Serkan Korkmaz +#' @templateVar .fun ${FUN} +#' @templateVar .family ${FAMILY} +#' @templateVar .formula ${FORMULA} +#' +#' @returns +#' An object of same [class] and [length] of `x`: +#' +#' \describe{ +#' \item{${ALIAS}}{[integer]} +#' } +#' +#' Pattern codes depend on `options(talib.normalize)`: +#' +#' * If `TRUE`: `1` = identified pattern; `-1` = identified bearish pattern. +#' * If `FALSE`: `100` = identified pattern; `-100` = identified bearish pattern. +#' * `0` = no pattern. +#' +#' @template description +#' @template candlestick +${FUN} <- function( + x, + cols, + ${ARGS} + na.bridge = FALSE, + ...) { + UseMethod("${FUN}") +} + +#' @export +#' @usage NULL +#' @rdname ${FUN} +#' +#' @aliases ${FUN} +${ALIAS} <- ${FUN} +#camel# +#camel##' @export +#camel##' @usage NULL +#camel##' @rdname ${FUN} +#camel##' +#camel##' @aliases ${FUN} +#camel#${CAMEL} <- ${FUN} + +#' @usage NULL +#' @aliases ${FUN} +#' +#' @export +${FUN}.default <- function( + x, + cols, + ${ARGS} + na.bridge = FALSE, + ...) { + + ## get candlestick pattern + ## options + ## + ## NOTE: this adds an overhead + ## of ~60% (from 50 microseconds to 80 microseconds) it needs to be set outside of the function without bloating the number of functions + candlestick_setting() + + ## get normalization option + normalize <- as.logical( + getOption("talib.normalize", TRUE) + ) + + ## 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, + ... + ) + + ## extract rownames + ## for later attachment + x_names <- rownames(constructed_series) + + ## calculate indicator and + ## return as data.frame + x <- as.matrix( + .Call( + C_impl_ta_${ALIAS}, + ${C_SIGNATURE}, + normalize, + as.logical(na.bridge) + ) + ) + + ## add column name + colnames(x) <- "${ALIAS}" + + ## readd rownames + set_rownames(x, x_names) + + ## return indicator + x +} + +#' @usage NULL +#' @aliases ${FUN} +#' +#' @export +${FUN}.data.frame <- function( + x, + cols, + ${ARGS} + na.bridge = FALSE, + ... +) { + map_dfr( + ${FUN}.default( + x = x, + cols = cols, + ${PARGS} + na.bridge = na.bridge, + ... + ) + ) + +} + +#' @usage NULL +#' @aliases ${FUN} +#' +#' @export +${FUN}.matrix <- function( + x, + cols, + ${ARGS} + na.bridge = FALSE, + ...) { + + ${FUN}.default( + x = x, + cols = cols , + ${PARGS} + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +${ALIAS}_lookback <- ${CAMEL_LOOKBACK}${FUN}_lookback <- function( + x, + cols,${ARGS} + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_${ALIAS}_lookback${C_SIGNATURE_LOOKBACK} + ) +} diff --git a/codegen/templates/candlestick_template.R.in b/codegen/templates/candlestick_template.R.in deleted file mode 100644 index a1d685cb1..000000000 --- a/codegen/templates/candlestick_template.R.in +++ /dev/null @@ -1,188 +0,0 @@ -#' @export -#' @family Pattern Recognition -#' -#' @title $TITLE -#' @templateVar .title $TITLE -#' @templateVar .author Serkan Korkmaz -#' @templateVar .fun $FUN -#' @templateVar .family ${FAMILY} -#' @templateVar .formula ${FORMULA} -#' -#' @returns -#' An object of same [class] and [length] of `x`: -#' -#' \describe{ -#' \item{$ALIAS}{[integer]} -#' } -#' -#' Pattern codes depend on `options(talib.normalize)`: -#' -#' * If `TRUE`: `1` = identified pattern; `-1` = identified bearish pattern. -#' * If `FALSE`: `100` = identified pattern; `-100` = identified bearish pattern. -#' * `0` = no pattern. -#' -#' @template description -#' @template candlestick -$FUN <- function( - x, - cols, ${ARGS} - na.bridge = FALSE, - ...) { - UseMethod("$FUN") -} - -#' @export -#' @usage NULL -#' @rdname $FUN -#' -#' @aliases $FUN -$ALIAS <- $FUN - -#' @usage NULL -#' @aliases $FUN -#' -#' @export -$FUN.default <- function( - x, - cols, ${ARGS} - na.bridge = FALSE, - ...) { - - ## get candlestick pattern - ## options - ## - ## NOTE: this adds an overhead - ## of ~60% (from 50 microseconds to 80 microseconds) it needs to be set outside of the function without bloating the number of functions - candlestick_setting() - - ## get normalization option - normalize <- as.logical( - getOption("talib.normalize", TRUE) - ) - - ## 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, - ... - ) - - ## extract rownames - ## for later attachment - x_names <- rownames(constructed_series) - - ## calculate indicator and - ## return as data.frame - x <- as.matrix( - .Call( - C_impl_ta_$ALIAS, - constructed_series[[1]], - constructed_series[[2]], - constructed_series[[3]], - constructed_series[[4]] ${CARGS}, - normalize, - as.logical(na.bridge) - ) - ) - - ## add column name - colnames(x) <- "$ALIAS" - - ## readd rownames - set_rownames(x, x_names) - - ## return indicator - x -} - -#' @usage NULL -#' @aliases $FUN -#' -#' @export -$FUN.data.frame <- function( - x, - cols, ${ARGS} - na.bridge = FALSE, - ...) { - - map_dfr( - NextMethod() - ) -} - -#' @usage NULL -#' @aliases $FUN -#' -#' @export -$FUN.matrix <- function( - x, - cols,${ARGS} - na.bridge = FALSE, - ...) { - NextMethod() -} - -#' @usage NULL -#' @aliases $FUN -#' -#' @export -$FUN.plotly <- function( - x, - cols, ${ARGS} - na.bridge = FALSE, - ...) { - - ## check that input value - ## 'x' is -object - assert_plotly_object(x) - - ## check that input value - ## 'cols' is a -objet - if (!missing(cols)) { - assert_formula(cols) - } - - ## construct series from - ## {plotly}-object - constructed_series <- series( - x = x, - formula = cols, - default_formula = ~open + high + low + close, - ... - ) - - ## construct indicator - ## from the series - constructed_indicator <- $FUN( - x = constructed_series, - cols = rebuild_formula( - names(constructed_series) - )${PPARGS} - ) - - ## add conditional idx - constructed_indicator[["idx"]] <- add_idx( - constructed_series - ) - - ## construct {plotly}-object - state <- .chart_state() - plotly_object <- pattern_ly( - p = state[["main"]], - x = constructed_indicator, - high = constructed_series[[2]], - low = constructed_series[[3]], - pattern_name = "$FUN", - agnostic = $AGNOSTIC ) - state[["main"]] <- plotly_object - - plotly_object - } diff --git a/codegen/templates/candlestick_template.c.in b/codegen/templates/candlestick_template.c.in deleted file mode 100644 index ac9564a02..000000000 --- a/codegen/templates/candlestick_template.c.in +++ /dev/null @@ -1,149 +0,0 @@ -// interface to ta_{{NAME}}.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose {{PEN_TEMP}} -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "{{NAME}}" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_{{NAME}}.c -// -#include "lib.h" -#include "attributes.h" -#include "Rinternals.h" -#include "container.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include "normalize.h" -#include - -// clang-format off -SEXP impl_ta_{{NAME}}( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose{{PEN_ARG}}, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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}} - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = {{LOOKBACK}} - - // 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 - const int proceed = output_container( - n, - lookback, - 1, - &output, - &output_ptr, - &protection_count - ); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_{{NAME}} returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_{{NAME}}( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr{{PEN_CALL}} - , - &start_idx, - &end_idx, - output_ptr - ); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "{{NAME}}"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix(output, output_ptr, na_mask, n_original, &protection_count); - } - - // ta_{{NAME}} returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real(output, 100.0, (na_mask != NULL), &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/codegen/templates/candlestick_ggplot_template.R.in b/codegen/templates/chart_candlestick_template.R similarity index 53% rename from codegen/templates/candlestick_ggplot_template.R.in rename to codegen/templates/chart_candlestick_template.R index b87c0ed64..7d05e32dc 100644 --- a/codegen/templates/candlestick_ggplot_template.R.in +++ b/codegen/templates/chart_candlestick_template.R @@ -1,15 +1,19 @@ #' @usage NULL -#' @aliases $FUN +#' @aliases ${FUN} #' #' @export -$FUN.ggplot <- function( +${FUN}.${METHOD} <- function( x, - cols, ${ARGS} + cols, + ${ARGS} na.bridge = FALSE, ...) { - ## check ggplot2 availability - assert_ggplot2() +#plotly# ## check that input value +#plotly# ## 'x' is -object +#plotly# assert_plotly_object(x) +#ggplot# ## check ggplot2 availability +#ggplot# assert_ggplot2() ## check that input value ## 'cols' is a -objet @@ -18,21 +22,23 @@ $FUN.ggplot <- function( } ## construct series from - ## {ggplot}-object + ## {${METHOD}}-object constructed_series <- series( x = x, formula = cols, - default_formula = ~open + high + low + close, + default_formula = ${FORMULA}, ... ) ## construct indicator ## from the series - constructed_indicator <- $FUN( + constructed_indicator <- ${FUN}( x = constructed_series, cols = rebuild_formula( names(constructed_series) - )${PPARGS} + ), + ${PARGS} + na.bridge = na.bridge ) ## add conditional idx @@ -40,16 +46,17 @@ $FUN.ggplot <- function( constructed_series ) - ## construct {ggplot2}-object + ## construct {${PKG}}-object state <- .chart_state() - ggplot_object <- pattern_gg( + ${METHOD}_object <- pattern_${SUFFIX}( p = state[["main"]], x = constructed_indicator, high = constructed_series[[2]], low = constructed_series[[3]], - pattern_name = "$FUN", - agnostic = $AGNOSTIC ) - state[["main"]] <- ggplot_object + pattern_name = "${FUN}", + agnostic = ${AGNOSTIC} + ) + state[["main"]] <- ${METHOD}_object - ggplot_object - } \ No newline at end of file + ${METHOD}_object +} diff --git a/codegen/templates/chart_main_template.R b/codegen/templates/chart_main_template.R new file mode 100644 index 000000000..3d1eda9b1 --- /dev/null +++ b/codegen/templates/chart_main_template.R @@ -0,0 +1,86 @@ +#' @usage NULL +#' @aliases ${FUN} +#' +#' @export +${FUN}.${METHOD} <- function( + x, + cols, + ${ARGS} + na.bridge = FALSE, + ## splice:optional-${METHOD}:start + ## splice:optional-${METHOD}:end + ...) { + +#plotly# ## check that input value +#plotly# ## 'x' is -object +#plotly# assert_plotly_object(x) +#ggplot# ## check ggplot2 availability +#ggplot# assert_ggplot2() + + ## check that input value + ## 'cols' is a -objet + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series from + ## {${METHOD}}-object + constructed_series <- series( + x = x, + formula = cols, + default_formula = ${FORMULA}, + ... + ) + + ## construct indicator + ## from the series + constructed_indicator <- ${FUN}( + x = constructed_series, + cols = rebuild_formula( + names(constructed_series) + ), + ${PARGS} + na.bridge = TRUE + ) + + ## add conditional idx + constructed_indicator[["idx"]] <- add_idx( + constructed_series + ) + + ## construct {${PKG}}-object + ## splice:${METHOD}-assembly:start +#plotly# traces <- lapply( +#plotly# setdiff(colnames(constructed_indicator), "idx"), +#plotly# function(col) { +#plotly# list( +#plotly# y = stats::as.formula( +#plotly# paste0("~", col) +#plotly# ), +#plotly# name = col +#plotly# ) +#plotly# } +#plotly# ) +#ggplot# layers <- lapply( +#ggplot# setdiff(colnames(constructed_indicator), "idx"), +#ggplot# function(col) list(y = col) +#ggplot# ) + name <- "${ALIAS}" + ## splice:${METHOD}-assembly:end + + state <- .chart_state() + ${METHOD}_object <- build_${METHOD}( + init = state[["main"]], +#plotly# traces = traces, +#ggplot# layers = layers, + decorators = list(), + name = get0( + x = "name", + ifnotfound = NULL + ), + data = constructed_indicator + ) + state[["main"]] <- ${METHOD}_object + + ${METHOD}_object +} diff --git a/codegen/templates/chart_moving_average_template.R b/codegen/templates/chart_moving_average_template.R new file mode 100644 index 000000000..977f9de4d --- /dev/null +++ b/codegen/templates/chart_moving_average_template.R @@ -0,0 +1,74 @@ +#' @usage NULL +#' @aliases ${FUN} +#' +#' @export +${FUN}.${METHOD} <- function( + x, + cols, + ${ARGS} + na.bridge = FALSE, + ...) { + +#plotly# ## check that input value +#plotly# ## 'x' is -object +#plotly# assert_plotly_object(x) +#ggplot# ## check ggplot2 availability +#ggplot# assert_ggplot2() + + ## check that input value + ## 'cols' is a -objet + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series from + ## {${METHOD}}-object + constructed_series <- series( + x = x, + formula = cols, + default_formula = ${FORMULA}, + ... + ) + + ## construct indicator + ## from the series + constructed_indicator <- ${FUN}( + x = constructed_series, + cols = rebuild_formula( + names(constructed_series) + ), + ${PARGS} + na.bridge = TRUE + ) + + ## add conditional idx + constructed_indicator[["idx"]] <- add_idx( + constructed_series + ) + + ## construct {${PKG}}-object + state <- .chart_state() + ${METHOD}_object <- build_${METHOD}( + init = state[["main"]], +#plotly# traces = list( +#plotly# list( +#plotly# y = ~constructed_indicator[["${ALIAS}"]][-(1:attr(constructed_indicator, "lookback", TRUE))], +#plotly# legendgroup = "MovingAverage", +#plotly# legendgrouptitle = list( +#plotly# text = "Moving Averages" +#plotly# ) +#plotly# ) +#plotly# ), +#ggplot# layers = list( +#ggplot# list( +#ggplot# y = "${ALIAS}" +#ggplot# ) +#ggplot# ), + name = label("${ALIAS}"${CARGS}), + decorators = list(), + data = constructed_indicator + ) + state[["main"]] <- ${METHOD}_object + + ${METHOD}_object +} diff --git a/codegen/templates/chart_subchart_template.R b/codegen/templates/chart_subchart_template.R new file mode 100644 index 000000000..1a43471e4 --- /dev/null +++ b/codegen/templates/chart_subchart_template.R @@ -0,0 +1,110 @@ +#' @usage NULL +#' @aliases ${FUN} +#' +#' @export +${FUN}.${METHOD} <- function( + x, + cols, + ${ARGS} + na.bridge = FALSE, +#plotly# ## splice:optional-${METHOD}:start +#plotly# ## splice:optional-${METHOD}:end +#plotly# title, +#ggplot# title, +#ggplot# ## splice:optional-${METHOD}:start +#ggplot# ## splice:optional-${METHOD}:end + ...) { + +#plotly# ## check that input value +#plotly# ## 'x' is -object +#plotly# assert_plotly_object(x) +#ggplot# ## check ggplot2 availability +#ggplot# assert_ggplot2() + + ## check that input value + ## 'cols' is a -objet + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series from + ## {${METHOD}}-object + constructed_series <- series( + x = x, + formula = cols, + default_formula = ${FORMULA}, + ... + ) + + ## construct indicator + ## from the series + constructed_indicator <- ${FUN}( + x = constructed_series, + cols = rebuild_formula( + names(constructed_series) + ), + ${PARGS} + na.bridge = TRUE + ) + + ## the constructed indicator +#plotly# ## always returns excpected +#ggplot# ## always returns expected + ## columns which can be passed +#plotly# ## down to add_last_values() +#ggplot# ## down to add_last_value_gg() + values_to_extract <- colnames(constructed_indicator) + + ## add conditional idx + constructed_indicator[["idx"]] <- add_idx( + constructed_series + ) + + ## construct {${PKG}}-object + ## splice:${METHOD}-assembly:start +#plotly# traces <- lapply( +#plotly# setdiff(colnames(constructed_indicator), "idx"), +#plotly# function(col) { +#plotly# list( +#plotly# y = stats::as.formula( +#plotly# paste0("~", col) +#plotly# ), +#plotly# name = col +#plotly# ) +#plotly# } +#plotly# ) +#ggplot# layers <- lapply( +#ggplot# setdiff(colnames(constructed_indicator), "idx"), +#ggplot# function(col) list(y = col) +#ggplot# ) + name <- "${ALIAS}" + ## splice:${METHOD}-assembly:end + + ${METHOD}_object <- add_last_value_${SUFFIX}( + build_${METHOD}( + init = ${METHOD}_init(), +#plotly# traces = traces, +#ggplot# layers = layers, + decorators = get0( + x = "decorators", + ifnotfound = list() + ), + name = get0( + x = "name", + ifnotfound = NULL + ), + data = constructed_indicator, + title = if (missing(title)) {"${TITLE}"} else {title} + ), + data = constructed_indicator[,values_to_extract, drop = FALSE], +#plotly# values_to_extract = values_to_extract, +#plotly# name = get0(x = "name", ifnotfound = NULL) +#ggplot# values_to_extract = values_to_extract, +#ggplot# name = get0(x = "name", ifnotfound = NULL) + ) + + state <- .chart_state() + state$sub <- c(state$sub, list(${METHOD}_object)) + + ${METHOD}_object +} diff --git a/codegen/templates/ggplot_main_template.R.in b/codegen/templates/ggplot_main_template.R.in deleted file mode 100644 index d93152ef4..000000000 --- a/codegen/templates/ggplot_main_template.R.in +++ /dev/null @@ -1,70 +0,0 @@ -#' @usage NULL -#' @aliases ${FUN} -#' -#' @export -${FUN}.ggplot <- function( - x, - cols,${ARGS} - na.bridge = FALSE, - ## splice:optional-ggplot:start - ## splice:optional-ggplot:end - ...) { - - ## check ggplot2 availability - assert_ggplot2() - - ## check that input value - ## 'cols' is a -objet - if (!missing(cols)) { - assert_formula(cols) - } - - ## construct series from - ## {ggplot}-object - constructed_series <- series( - x = x, - formula = cols, - default_formula = ${FORMULA}, - ... - ) - - ## construct indicator - ## from the series - constructed_indicator <- ${FUN}( - x = constructed_series, - cols = rebuild_formula( - names(constructed_series) - ) - ${PPARGS}, - na.bridge = TRUE - ) - - ## add conditional idx - constructed_indicator[["idx"]] <- add_idx( - constructed_series - ) - - ## construct {ggplot2}-object - ## splice:ggplot-assembly:start - layers <- lapply( - setdiff(colnames(constructed_indicator), "idx"), - function(col) list(y = col) - ) - name <- "${ALIAS}" - ## splice:ggplot-assembly:end - - state <- .chart_state() - ggplot_object <- build_ggplot( - init = state[["main"]], - layers = layers, - decorators = list(), - name = get0( - x = "name", - ifnotfound = NULL - ), - data = constructed_indicator - ) - state[["main"]] <- ggplot_object - - ggplot_object - } \ No newline at end of file diff --git a/codegen/templates/ggplot_subchart_template.R.in b/codegen/templates/ggplot_subchart_template.R.in deleted file mode 100644 index f9197df0d..000000000 --- a/codegen/templates/ggplot_subchart_template.R.in +++ /dev/null @@ -1,87 +0,0 @@ -#' @usage NULL -#' @aliases ${FUN} -#' -#' @export -${FUN}.ggplot <- function( - x, - cols,${ARGS} - na.bridge = FALSE, - ## splice:optional-ggplot:start - ## splice:optional-ggplot:end - title, - ...) { - - ## check ggplot2 availability - assert_ggplot2() - - ## check that input value - ## 'cols' is a -objet - if (!missing(cols)) { - assert_formula(cols) - } - - ## construct series from - ## {ggplot}-object - constructed_series <- series( - x = x, - formula = cols, - default_formula = ${FORMULA}, - ... - ) - - ## construct indicator - ## from the series - constructed_indicator <- ${FUN}( - x = constructed_series, - cols = rebuild_formula( - names(constructed_series) - ) - ${PPARGS}, - na.bridge = TRUE - ) - - ## the constructed indicator - ## always returns expected - ## columns which can be passed - ## down to add_last_value_gg() - values_to_extract <- colnames(constructed_indicator) - - ## add conditional idx - constructed_indicator[["idx"]] <- add_idx( - constructed_series - ) - - ## construct {ggplot2}-object - ## splice:ggplot-assembly:start - layers <- lapply( - setdiff(colnames(constructed_indicator), "idx"), - function(col) list(y = col) - ) - name <- "${ALIAS}" - ## splice:ggplot-assembly:end - - ggplot_object <- add_last_value_gg( - build_ggplot( - init = ggplot_init(), - layers = layers, - decorators = get0( - x = "decorators", - ifnotfound = list() - ), - name = get0( - x = "name", - ifnotfound = NULL - ), - data = constructed_indicator, - title = if (missing(title)) {"${TITLE}"} else {title} - ), - data = constructed_indicator[,values_to_extract, drop = FALSE], - values_to_extract = values_to_extract, - name = get0(x = "name", ifnotfound = NULL) - ) - - state <- .chart_state() - state$sub <- c(state$sub, list(ggplot_object)) - - ggplot_object - } \ No newline at end of file diff --git a/codegen/templates/indicator_template.R.in b/codegen/templates/indicator_template.R similarity index 73% rename from codegen/templates/indicator_template.R.in rename to codegen/templates/indicator_template.R index 0abd895ba..f0b947dc9 100644 --- a/codegen/templates/indicator_template.R.in +++ b/codegen/templates/indicator_template.R @@ -12,10 +12,12 @@ ## splice:documentation:end #' #' @template description +${PARAM_DOCS} #' @template returns ${FUN} <- function( x, - cols,${ARGS} + cols, + ${ARGS} na.bridge = FALSE, ...) { UseMethod("${FUN}") @@ -27,6 +29,13 @@ ${FUN} <- function( #' #' @aliases ${FUN} ${ALIAS} <- ${FUN} +#camel# +#camel##' @export +#camel##' @usage NULL +#camel##' @rdname ${FUN} +#camel##' +#camel##' @aliases ${FUN} +#camel#${CAMEL} <- ${FUN} #' @usage NULL #' @aliases ${FUN} @@ -34,7 +43,8 @@ ${ALIAS} <- ${FUN} #' @export ${FUN}.default <- function( x, - cols,${ARGS} + cols, + ${ARGS} na.bridge = FALSE, ...) { @@ -60,9 +70,8 @@ ${FUN}.default <- function( ## calculate indicator and ## return as data.frame x <- .Call( - C_impl_ta_${TA_FUN}, - ## splice:call:start - ## splice:call:end + C_impl_ta_${ALIAS}, + ${C_SIGNATURE}, as.logical(na.bridge) ) @@ -79,13 +88,16 @@ ${FUN}.default <- function( #' @export ${FUN}.data.frame <- function( x, - cols,${ARGS} + cols, + ${ARGS} na.bridge = FALSE, - ...) { + ... +) { map_dfr( ${FUN}.default( x = x, - cols = cols ${PARGS} + cols = cols, + ${PARGS} na.bridge = na.bridge, ... ) @@ -99,14 +111,31 @@ ${FUN}.data.frame <- function( #' @export ${FUN}.matrix <- function( x, - cols,${ARGS} + cols, + ${ARGS} na.bridge = FALSE, ...) { ${FUN}.default( x = x, - cols = cols ${PARGS} + cols = cols , + ${PARGS} na.bridge = na.bridge, ... ) } + +#' @usage NULL +${ALIAS}_lookback <- ${CAMEL_LOOKBACK}${FUN}_lookback <- function( + x, + cols, + ${ARGS} + na.bridge = FALSE, + ... +) { + + .Call( + C_impl_ta_${ALIAS}_lookback${C_SIGNATURE_LOOKBACK} + ) + +} diff --git a/codegen/templates/indicator_template.c.in b/codegen/templates/indicator_template.c.in deleted file mode 100644 index c8ade4f0f..000000000 --- a/codegen/templates/indicator_template.c.in +++ /dev/null @@ -1,119 +0,0 @@ -// interface to ta_${NAME}.c -// -// Parameters -// $PARAM_DOC -// Returns -// matrix (n x $OUT_COLS) with colum: -// $RETURN_COLS -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_${NAME}.c -// -#include "MAType.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include "attributes.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_${NAME}($R_SIGNATURE - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - $VALUES - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - $NA_MASK_BUILD - if (n < n_original) { - $NA_COMPACT - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - $OUTPUT_TYPE *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_${NAME}_Lookback($LOOKBACK_ARGS); - - - // 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 - const int proceed = output_container( - n, - lookback, - $OUT_COLS, - &output, - &output_ptr, - &protection_count - ); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - $OUTPUT_COLS - - // TA_$NAME returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_${NAME}( - 0, - n - 1, - $VALUE_POINTERS - &start_idx, - &end_idx, - $OUTPUT_POINTERS - ); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - $SHIFT_ARRAYS - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - $SET_COLUMN_NAMES - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix(output, output_ptr, na_mask, n_original, &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/codegen/templates/moving_average_ggplot_template.R.in b/codegen/templates/moving_average_ggplot_template.R.in deleted file mode 100644 index 35aa587e5..000000000 --- a/codegen/templates/moving_average_ggplot_template.R.in +++ /dev/null @@ -1,59 +0,0 @@ -#' @usage NULL -#' @aliases $FUN -#' -#' @export -$FUN.ggplot <- function( - x, - cols,${ARGS} - na.bridge = FALSE, - ...) { - - ## check ggplot2 availability - assert_ggplot2() - - ## check that input value - ## 'cols' is a -objet - if (!missing(cols)) { - assert_formula(cols) - } - - ## construct series from - ## {ggplot}-object - constructed_series <- series( - x = x, - formula = cols, - default_formula = ~close, - ... - ) - - ## construct indicator - ## from the series - constructed_indicator <- $FUN( - x = constructed_series, - cols = rebuild_formula( - names(constructed_series) - ) ${PPARGS} - ) - - ## add conditional idx - constructed_indicator[["idx"]] <- add_idx( - constructed_series - ) - - ## construct {ggplot2}-object - state <- .chart_state() - ggplot_object <- build_ggplot( - init = state[["main"]], - layers = list( - list( - y = "$ALIAS" - ) - ), - name = label("$ALIAS" ${CARGS}), - decorators = list(), - data = constructed_indicator - ) - state[["main"]] <- ggplot_object - - ggplot_object - } diff --git a/codegen/templates/moving_average_template.R b/codegen/templates/moving_average_template.R new file mode 100644 index 000000000..19b9561f8 --- /dev/null +++ b/codegen/templates/moving_average_template.R @@ -0,0 +1,198 @@ +#' @export +#' @family ${FAMILY} +#' +#' @title ${TITLE} +#' @templateVar .title ${TITLE} +#' @templateVar .author Serkan Korkmaz +#' @templateVar .fun ${FUN} +#' @templateVar .family ${FAMILY} +#' @templateVar .formula ${FORMULA} +#' +## splice:documentation:start +## splice:documentation:end +#' +#' @details +#' When passed without 'x', [${FUN}] functions as an 'Moving Average'-specification which is used in, for example, [stochastic] when constructing the smoothing lines. +#' +#' When called without 'x' it will return a named list which is used for the +#' indicators that supports various Moving Average specifications. +#' +#' @template description +${PARAM_DOCS} +#' @template returns +${FUN} <- function( + x, + cols, + ${ARGS} + na.bridge = FALSE, + ...) { + + ## if 'x' is missing ${FUN} functions + ## as a Moving Average Specification + if (missing(x)) { + ## construct Moving Average specification + ## from call + x <- structure( + list( + ${SPEC_FIELDS}, + maType = ${MA_TYPE} + ), + class = "maType" + ) + + return(x) + } + + UseMethod("${FUN}") +} + +#' @export +#' @usage NULL +#' @rdname ${FUN} +#' +#' @aliases ${FUN} +${ALIAS} <- ${FUN} +#camel# +#camel##' @export +#camel##' @usage NULL +#camel##' @rdname ${FUN} +#camel##' +#camel##' @aliases ${FUN} +#camel#${CAMEL} <- ${FUN} + +#' @usage NULL +#' @aliases ${FUN} +#' +#' @export +${FUN}.default <- function( + x, + cols, + ${ARGS} + na.bridge = FALSE, + ...) { + + ## 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, + ... + ) + + ## extract rownames + ## for later attachment + x_names <- rownames(constructed_series) + + ## calculate indicator and + ## return as data.frame + x <- .Call( + C_impl_ta_${ALIAS}, + ${C_SIGNATURE}, + as.logical(na.bridge) + ) + + ## readd rownames + set_rownames(x, x_names) + + ## return indicator + x +} + +#' @usage NULL +#' @aliases ${FUN} +#' +#' @export +${FUN}.data.frame <- function( + x, + cols, + ${ARGS} + na.bridge = FALSE, + ... +) { + map_dfr( + ${FUN}.default( + x = x, + cols = cols, + ${PARGS} + na.bridge = na.bridge, + ... + ) + ) + +} + +#' @usage NULL +#' @aliases ${FUN} +#' +#' @export +${FUN}.matrix <- function( + x, + cols, + ${ARGS} + na.bridge = FALSE, + ...) { + + ${FUN}.default( + x = x, + cols = cols , + ${PARGS} + na.bridge = na.bridge, + ... + ) +} + +#' @usage NULL +#' @aliases ${FUN} +#' +#' @export +${FUN}.numeric <- function( + x, + cols, + ${ARGS} + na.bridge = FALSE, + ...) { + + ## warn if 'cols' have been + ## passed just to make sure + ## the user knows its not possible + ## or relevant + if (!missing(cols)) { + warning("'cols' is passed but is unused for vectors.") + } + + ## pass to 'C' directly + ## with the input vector + x <- .Call( + C_impl_ta_${ALIAS}, + ${C_NUMERIC}, + as.logical(na.bridge) + ) + + if (dim(x)[2] == 1L) { + dim(x) <- NULL + } + + x +} + +#' @usage NULL +${ALIAS}_lookback <- ${CAMEL_LOOKBACK}${FUN}_lookback <- function( + x, + cols, + ${ARGS} + na.bridge = FALSE, + ... +) { + + .Call( + C_impl_ta_${ALIAS}_lookback${C_SIGNATURE_LOOKBACK} + ) +} + diff --git a/codegen/templates/moving_average_template.R.in b/codegen/templates/moving_average_template.R.in deleted file mode 100644 index a7fbec5ca..000000000 --- a/codegen/templates/moving_average_template.R.in +++ /dev/null @@ -1,235 +0,0 @@ -#' @export -#' @family $FAMILY -#' -#' @title $TITLE -#' @templateVar .title $TITLE -#' @templateVar .author Serkan Korkmaz -#' @templateVar .fun $FUN -#' @templateVar .family ${FAMILY} -#' @templateVar .formula ${FORMULA} -#' -## splice:documentation:start -## splice:documentation:end -#' -#' @details -#' When passed without 'x', [$FUN] functions as an 'Moving Average'-specification which is used in, for example, [stochastic] when constructing the smoothing lines. -#' -#' When called without 'x' it will return a named list which is used for the -#' indicators that supports various Moving Average specifications. -#' -#' @template description -#' @template returns -$FUN <- function( - x, - cols,${ARGS} - na.bridge = FALSE, - ...) { - - ## if 'x' is missing $FUN functions - ## as a Moving Average Specification - if (missing(x)) { - ## construct Moving Average specification - ## from call - x <- structure( - list( - ${SPEC_FIELDS}, - maType = ${maType} - ) - ) - - return(x) - } - UseMethod("$FUN") -} - -#' @export -#' @usage NULL -#' @rdname $FUN -#' -#' @aliases $FUN -$ALIAS <- $FUN - -#' @usage NULL -#' @aliases $FUN -#' -#' @export -$FUN.default <- function( - x, - cols,${ARGS} - na.bridge = FALSE, - ...) { - - ## 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, - ... - ) - - ## extract rownames - ## for later attachment - x_names <- rownames(constructed_series) - - ## calculate indicator and - ## return as data.frame - x <- .Call( - C_impl_ta_${TA_FUN}, - as.double(constructed_series[[1]])${CARGS_TYPED}, - as.logical(na.bridge) - ) - - ## readd rownames - set_rownames(x, x_names) - - ## return indicator - x -} - -#' @usage NULL -#' @aliases $FUN -#' -#' @export -$FUN.data.frame <- function( - x, - cols,${ARGS} - na.bridge = FALSE, - ...) { - - map_dfr( - NextMethod() - ) -} - -#' @usage NULL -#' @aliases $FUN -#' -#' @export -$FUN.matrix <- function( - x, - cols,${ARGS} - na.bridge = FALSE, - ...) { - - ## pass directly to - ## $FUN.default to avoid - ## shenanigans with NextMethod() - $FUN.default( - x = x, - cols = cols ${PARGS} - na.bridge = na.bridge, - ... - ) -} - -#' @usage NULL -#' @aliases $FUN -#' -#' @export -$FUN.numeric <- function( - x, - cols,${ARGS} - na.bridge = FALSE, - ...) { - - ## warn if 'cols' have been - ## passed just to make sure - ## the user knows its not possible - ## or relevant - if (!missing(cols)) { - warning("'cols' is passed but is unused for vectors.") - } - - ## pass to 'C' directly - ## with the input vector - x <- .Call( - C_impl_ta_${TA_FUN}, - as.double(x)${CARGS_TYPED}, - 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) - } - - x - -} - -#' @usage NULL -#' @aliases $FUN -#' -#' @export -$FUN.plotly <- function( - x, - cols,${ARGS} - na.bridge = FALSE, - ...) { - - ## check that input value - ## 'x' is -object - assert_plotly_object(x) - - ## check that input value - ## 'cols' is a -objet - if (!missing(cols)) { - assert_formula(cols) - } - - ## construct series from - ## {plotly}-object - constructed_series <- series( - x = x, - formula = cols, - default_formula = ~close, - ... - ) - - ## construct indicator - ## from the series - constructed_indicator <- $FUN( - x = constructed_series, - cols = rebuild_formula( - names(constructed_series) - ) ${PPARGS} - ) - - ## add conditional idx - constructed_indicator[["idx"]] <- add_idx( - constructed_series - ) - - ## construct {plotly}-object - state <- .chart_state() - plotly_object <- build_plotly( - init = state[["main"]], - traces = list( - list(y = ~constructed_indicator[["$ALIAS"]][-(1:attr(constructed_indicator, "lookback", TRUE))], - legendgroup = "MovingAverage", - legendgrouptitle = list( - text = "Moving Averages" - ) - ) - ), - name = label("$ALIAS" ${CARGS}), - decorators = list() - ) - state[["main"]] <- plotly_object - - plotly_object - } diff --git a/codegen/templates/numeric_template.R b/codegen/templates/numeric_template.R new file mode 100644 index 000000000..f96709b0d --- /dev/null +++ b/codegen/templates/numeric_template.R @@ -0,0 +1,33 @@ +#' @usage NULL +#' @aliases ${FUN} +#' +#' @export +${FUN}.numeric <- function( + x, + cols, + ${ARGS} + na.bridge = FALSE, + ...) { + + ## warn if 'cols' have been + ## passed just to make sure + ## the user knows its not possible + ## or relevant + if (!missing(cols)) { + warning("'cols' is passed but is unused for vectors.") + } + + ## pass the argument directly + ## to 'C' + x <- .Call( + C_impl_ta_${ALIAS}, + ${C_NUMERIC}, + as.logical(na.bridge) + ) + + if (dim(x)[2] == 1L) { + dim(x) <- NULL + } + + x +} diff --git a/codegen/templates/numeric_template.R.in b/codegen/templates/numeric_template.R.in deleted file mode 100644 index adc86c376..000000000 --- a/codegen/templates/numeric_template.R.in +++ /dev/null @@ -1,42 +0,0 @@ -#' @usage NULL -#' @aliases ${FUN} -#' -#' @export -${FUN}.numeric <- function( - x, - cols,${ARGS} - na.bridge = FALSE, - ...) { - - ## warn if 'cols' have been - ## passed just to make sure - ## the user knows its not possible - ## or relevant - if (!missing(cols)) { - warning("'cols' is passed but is unused for vectors.") - } - - ## pass the argument directly - ## to 'C' - x <- .Call( - C_impl_ta_${TA_FUN}, - ## splice:numeric:start - ${CARGS} - ## splice:numeric:end - 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) - } - - x -} diff --git a/codegen/templates/plotly_main_template.R.in b/codegen/templates/plotly_main_template.R.in deleted file mode 100644 index 92056163a..000000000 --- a/codegen/templates/plotly_main_template.R.in +++ /dev/null @@ -1,67 +0,0 @@ -#' @usage NULL -#' @aliases ${FUN} -#' -#' @export -${FUN}.plotly <- function( - x, - cols,${ARGS} - na.bridge = FALSE, - ## splice:optional-plotly:start - ## splice:optional-plotly:end - ...) { - - ## check that input value - ## 'x' is -object - assert_plotly_object(x) - - ## check that input value - ## 'cols' is a -objet - if (!missing(cols)) { - assert_formula(cols) - } - - ## construct series from - ## {plotly}-object - constructed_series <- series( - x = x, - formula = cols, - default_formula = ${FORMULA}, - ... - ) - - ## construct indicator - ## from the series - constructed_indicator <- ${FUN}( - x = constructed_series, - cols = rebuild_formula( - names(constructed_series) - ) - ${PPARGS}, - na.bridge = TRUE - ) - - ## add conditional idx - constructed_indicator[["idx"]] <- add_idx( - constructed_series - ) - - ## construct {plotly}-object - ## splice:plotly-assembly:start - ## initial scaffold - ## splice:plotly-assembly:end - - state <- .chart_state() - plotly_object <- build_plotly( - init = state[["main"]], - traces = traces, - decorators = list(), - name = get0( - x = "name", - ifnotfound = NULL - ), - data = constructed_indicator - ) - state[["main"]] <- plotly_object - - plotly_object - } \ No newline at end of file diff --git a/codegen/templates/plotly_subchart_template.R.in b/codegen/templates/plotly_subchart_template.R.in deleted file mode 100644 index 7b0b142c5..000000000 --- a/codegen/templates/plotly_subchart_template.R.in +++ /dev/null @@ -1,83 +0,0 @@ -#' @usage NULL -#' @aliases ${FUN} -#' -#' @export -${FUN}.plotly <- function( - x, - cols,${ARGS} - na.bridge = FALSE, - ## splice:optional-plotly:start - ## splice:optional-plotly:end - title, - ...) { - - ## check that input value - ## 'x' is -object - assert_plotly_object(x) - - ## check that input value - ## 'cols' is a -objet - if (!missing(cols)) { - assert_formula(cols) - } - - ## construct series from - ## {plotly}-object - constructed_series <- series( - x = x, - formula = cols, - default_formula = ${FORMULA}, - ... - ) - - ## construct indicator - ## from the series - constructed_indicator <- ${FUN}( - x = constructed_series, - cols = rebuild_formula( - names(constructed_series) - ) - ${PPARGS}, - na.bridge = TRUE - ) - - ## the constructed indicator - ## always returns excpected - ## columns which can be passed - ## down to add_last_values() - values_to_extract <- colnames(constructed_indicator) - - ## add conditional idx - constructed_indicator[["idx"]] <- add_idx( - constructed_series - ) - - ## construct {plotly}-object - ## splice:plotly-assembly:start - ## initial scaffold - ## splice:plotly-assembly:end - - plotly_object <- add_last_value_ly( - build_plotly( - init = plotly_init(), - traces = traces, - decorators = get0( - x = "decorators", - ifnotfound = list() - ), - name = get0( - x = "name", - ifnotfound = NULL - ), - data = constructed_indicator, - title = if (missing(title)) {"${TITLE}"} else {title} - ), - data = constructed_indicator[,values_to_extract, drop = FALSE], - values_to_extract = values_to_extract - ) - - state <- .chart_state() - state$sub <- c(state$sub, list(plotly_object)) - - plotly_object - } \ No newline at end of file diff --git a/codegen/templates/rolling_template.R.in b/codegen/templates/rolling_template.R similarity index 52% rename from codegen/templates/rolling_template.R.in rename to codegen/templates/rolling_template.R index 5a8a965eb..3ba503292 100644 --- a/codegen/templates/rolling_template.R.in +++ b/codegen/templates/rolling_template.R @@ -10,12 +10,12 @@ ## splice:documentation:end #' #' @template rolling_description +${PARAM_DOCS} #' @template rolling_returns ${FUN} <- function( - x, - ${ARGS}, - na.bridge = FALSE - ) { + ${SERIES} + ${ARGS} + na.bridge = FALSE, ...) { UseMethod("${FUN}") } @@ -25,28 +25,40 @@ ${FUN} <- function( #' #' @aliases ${FUN} ${ALIAS} <- ${FUN} +#camel# +#camel##' @export +#camel##' @usage NULL +#camel##' @rdname ${FUN} +#camel##' +#camel##' @aliases ${FUN} +#camel#${CAMEL} <- ${FUN} #' @usage NULL #' @aliases ${FUN} #' #' @export ${FUN}.default <- function( - x, - ${ARGS}, - na.bridge = FALSE - ) { + ${SERIES} + ${ARGS} + na.bridge = FALSE, ...) { ## calculate indicator and ## return as data.frame x <- .Call( - C_impl_ta_${TA_FUN}, - ## splice:call:start + C_impl_ta_${ALIAS}, + ## splice:call:start + ${C_NUMERIC},,, ## splice:call:end as.logical(na.bridge) ) + ## strip dimensions + ## while preserving + ## attributes + dim(x) <- NULL + ## return indicator - as.double(x) + x } #' @usage NULL @@ -54,19 +66,35 @@ ${FUN}.default <- function( #' #' @export ${FUN}.numeric <- function( - x, - ${ARGS}, - na.bridge = FALSE - ) { + ${SERIES} + ${ARGS} + na.bridge = FALSE, ...) { ## calculate indicator and ## return as data.frame x <- ${FUN}.default( - x = x ${PARGS}, - na.bridge = na.bridge - + ${PSERIES} + ${PARGS} + na.bridge = na.bridge ) + ## strip dimensions + ## while preserving + ## attributes + dim(x) <- NULL + ## return indicator - as.double(x) + x } + +#' @usage NULL +${ALIAS}_lookback <- ${CAMEL_LOOKBACK}${FUN}_lookback <- function( + x,${ARGS} + na.bridge = FALSE, + ... +) { + .Call( + C_impl_ta_${ALIAS}_lookback${C_SIGNATURE_LOOKBACK} + ) + +} \ No newline at end of file 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..ce73cb185 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 talib website [![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,185 +34,210 @@ 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 +Install the development version from GitHub: -{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). +```{r install-dev, echo = TRUE, eval = FALSE} +pak::pak("serkor1/ta-lib-R") +``` + +## Quick start + +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 patterns, echo = TRUE} -## detect Engulfing patterns: -## 1 = bullish, -1 = bearish, 0 = none +```{r quick-start, echo=TRUE} +## calculate the +## relative strength index +relative_strength_index <- talib::RSI( + talib::BTC +) + +## display results tail( - talib::engulfing(BTC) + relative_strength_index ) ``` -## Charts +Indicator outputs preserve input length, which keeps results aligned with the +original OHLCV rows. -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 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 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) -} +tail(features) ``` -Multiple indicators can share a sub-panel by passing them as calls: +## 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: -```{r combined, fig.align = 'center', fig.height = 7, echo = TRUE} +```{r charting-example, echo=TRUE} +## 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" + ) + + ## add Bollinger Bands to + ## the existing chart + talib::indicator( + talib::BBANDS + ) - ## pass multiple calls to combine - ## them on a single sub-panel + ## add Simple Moving Averages (SMA) + ## to the chart in a loop + for (timePeriod in seq(5, 15, by = 3)) { + talib::indicator( + talib::SMA, + timePeriod = timePeriod + ) + } + + ## similar subchart indicators + ## like the Relative Strength Index + ## can be grouped to avoid repeated + ## subpanels + talib::indicator( + talib::RSI(timePeriod = 10), + talib::RSI(timePeriod = 14), + talib::RSI(timePeriod = 21) + ) + + ## identify Doji patterns + ## and add them to the chart talib::indicator( - talib::RSI(n = 10), - talib::RSI(n = 14), - talib::RSI(n = 21) + talib::doji ) } ``` -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: +## Implementation: {talib} vs upstream (TA-Lib Core) -```{r ggplot2-setup, include = FALSE} -options(talib.chart.backend = "ggplot2") -talib::set_theme("hawks_and_doves") -``` +Functions use descriptive snake_case names; each is aliased to its [TA-Lib](https://github.com/TA-Lib/ta-lib) shorthand for compatibility with the broader ecosystem, and to a camelCase name for consistency across R's finance ecosystem: -```{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) -} -``` +
-```{r ggplot2-teardown, include = FALSE} -options(talib.chart.backend = "plotly") -talib::set_theme("default") -``` +| Category | TA-Lib (C) | {talib} | {talib} alias | {talib} camelCase alias | +|:----------------------|:---------------------|:----------------------------|:--------------------|:----------------------------| +| Overlap Studies | `TA_BBANDS()` | `bollinger_bands()` | `BBANDS()` | `bollingerBands()` | +| Momentum Indicators | `TA_CCI()` | `commodity_channel_index()` | `CCI()` | `commodityChannelIndex()` | +| Volume Indicators | `TA_OBV()` | `on_balance_volume()` | `OBV()` | `onBalanceVolume()` | +| Volatility Indicators | `TA_ATR()` | `average_true_range()` | `ATR()` | `averageTrueRange()` | +| Price Transform | `TA_AVGPRICE()` | `average_price()` | `AVGPRICE()` | `averagePrice()` | +| Cycle Indicators | `TA_HT_SINE()` | `sine_wave()` | `HT_SINE()` | `sineWave()` | +| Pattern Recognition | `TA_CDLHANGINGMAN()` | `hanging_man()` | `CDLHANGINGMAN()` | `hangingMan()` | -## Column selection +
-Indicators use the columns they need automatically. When your data has non-standard column names, remap them with formula syntax: +### Interface: R vs Python -```{r cols, echo = TRUE, eval = FALSE} -## remap 'price' to the close column -talib::RSI(x, cols = ~price) +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. -## remap hi, lo, last to high, low, close -talib::stochastic(x, cols = ~ hi + lo + last) -``` +In Python, each series is passed independently: -## Naming +```python +import numpy as np +import talib -Functions use descriptive snake_case names, but every function is aliased to its TA-Lib shorthand for compatibility with the broader ecosystem: +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) -
+print( + talib.CDLDOJI(o, h, l, c) +) +``` -| Category | TA-Lib (C) | {talib} | {talib} alias | -|:----------------------|:---------------------|:----------------------------|:--------------------| -| Overlap Studies | `TA_BBANDS()` | `bollinger_bands()` | `BBANDS()` | -| Momentum Indicators | `TA_CCI()` | `commodity_channel_index()` | `CCI()` | -| Volume Indicators | `TA_OBV()` | `on_balance_volume()` | `OBV()` | -| Volatility Indicators | `TA_ATR()` | `average_true_range()` | `ATR()` | -| Price Transform | `TA_AVGPRICE()` | `average_price()` | `AVGPRICE()` | -| Cycle Indicators | `TA_HT_SINE()` | `sine_wave()` | `HT_SINE()` | -| Pattern Recognition | `TA_CDLHANGINGMAN()` | `hanging_man()` | `CDLHANGINGMAN()` | +In R the series are passed as a tabular container: -
+```{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 alias, echo = TRUE} -## snake_case and TA-Lib aliases -## are identical -all.equal( - target = talib::bollinger_bands(BTC), - current = talib::BBANDS(BTC) +talib::CDLDOJI( + ohlc ) ``` -## Installation[^1] +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. -Install the release version from CRAN: +## Contributing and cloning -```{r install-cran, echo = TRUE, eval = FALSE} -install.packages("talib") -``` +Contributions are welcome. For non-trivial changes, please open an issue first to discuss the proposed design, API impact, and testing approach. -Install the development version from GitHub: +This repository vendors [TA-Lib](https://github.com/TA-Lib/ta-lib) as a Git submodule. Clone the repository with submodules enabled: -```{r install-dev, echo = TRUE, eval = FALSE} -pak::pak("serkor1/ta-lib-R") +```sh +git clone --recurse-submodules https://github.com/serkor1/ta-lib-R.git +cd ta-lib-R ``` -### 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: +If you already cloned the repository without submodules, initialize them with: -```{r install-native, echo = TRUE, eval = FALSE} -install.packages( - "talib", - type = "source", - configure.args = "-O3 -march=native" -) +```sh +git submodule update --init --recursive ``` -Or from a local clone: +Most indicator wrappers, helper functions, documentation fragments, and unit tests are generated from the scripts in `codegen/`. The charting interface is maintained separately. -```shell -git clone --recursive https://github.com/serkor1/ta-lib-R.git -cd ta-lib-R -R CMD INSTALL . --configure-args="-O3 -march=native" +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/dev/favicons.R b/dev/favicons.R new file mode 100644 index 000000000..d6e6332c7 --- /dev/null +++ b/dev/favicons.R @@ -0,0 +1,21 @@ +## script: favicons +## author: Serkan Korkmaz +## objective: Generate favicons from the SVG logo into +## pkgdown/favicon so pkgdown::init_site() skips the +## realfavicongenerator.net API (it rejects SVG logos with HTTP 500). +## +## called by the pkgdown Makefile target and .github/workflows/pkgdown.yaml +svg <- "man/figures/logo.svg" +dir.create("pkgdown/favicon", recursive = TRUE, showWarnings = FALSE) + +file.copy(svg, "pkgdown/favicon/favicon.svg", overwrite = TRUE) +rsvg::rsvg_png(svg, "pkgdown/favicon/favicon-96x96.png", width = 96) +rsvg::rsvg_png(svg, "pkgdown/favicon/apple-touch-icon.png", width = 180) + +tmp <- tempfile(fileext = ".png") +rsvg::rsvg_png(svg, tmp, width = 48) +magick::image_write( + magick::image_read(tmp), + "pkgdown/favicon/favicon.ico", + format = "ico" +) diff --git a/dev/hexSticker.R b/dev/hexSticker.R index 6e25915ce..002e2faf4 100644 --- a/dev/hexSticker.R +++ b/dev/hexSticker.R @@ -6,14 +6,11 @@ ## set clean to TRUE for deleting auxillary files ## run this code in the terminal to replace ## the log: -## -## Rscript -e "usethis::use_logo('talib-hex.png')" clean <- TRUE ## file destinations -raw_file <- "talib-hex-raw.png" -final_file <- "talib-hex.png" -mask_file <- "talib-hex-mask.png" +raw_file <- "talib-hex-raw.svg" +final_file <- "talib-hex.svg" ## common colors and fonts ## across the sticker @@ -23,8 +20,11 @@ up <- "#65a479" down <- "#d5695d" ink <- "#D8DEE3" +## render text at the same dpi the sticker is saved at +dpi <- 1200 sysfonts::font_add_google("JetBrains Mono", "jbmono") showtext::showtext_auto() +showtext::showtext_opts(dpi = dpi) ## construct OHLC ## series @@ -127,11 +127,12 @@ p_candles <- ggplot2::ggplot(OHLC, ggplot2::aes(x = x)) + ## store locally hexSticker::sticker( p_candles, - package = "", + package = "{talib}", p_family = "jbmono", - p_size = 33, - p_color = ink, - p_y = 1.44, + p_size = 3, + p_color = grid_minor_col, + p_x = 0.503, + p_y = 1.313, s_x = 1, s_y = 1, s_width = 2, @@ -139,57 +140,72 @@ hexSticker::sticker( h_fill = bg, h_color = accent, h_size = 1, - url = "{talib}", - u_color = accent, - u_size = 33, + url = "", + u_color = grid_major_col, + u_size = 3.5, u_x = 0.4, - u_y = 1.5, + u_y = 1.6, u_angle = 30, filename = raw_file, - dpi = 600, - device = ragg::agg_png, + dpi = dpi, + # device = ragg::agg_png, bg = "transparent", white_around_sticker = FALSE ) -## construct an additional -## hexsticker to crop figures outside -## the hex -p_blank <- ggplot2::ggplot() + - ggplot2::theme_void() + - hexSticker::theme_transparent() +## crop everything outside the hex by clipping the SVG to a +## hexagon-shaped . +svg <- readLines(raw_file, warn = FALSE) -hexSticker::sticker( - p_blank, - package = "", - p_size = 1, - p_color = "white", - s_x = 1, - s_y = 1, - s_width = 1, - s_height = 1, - h_fill = "white", - h_color = "white", - h_size = 0.001, # solid white hex - url = "", - filename = mask_file, - dpi = 600, - device = ragg::agg_png, - bg = "black", # black corners outside hex - white_around_sticker = FALSE +poly_line <- grep(" found in ", raw_file, " -- cannot locate the hexagon") +} +hex_pts <- trimws(sub(".*points='([^']*)'.*", "\\1", svg[poly_line])) + +clip_def <- sprintf( + "", + hex_pts ) -## apply the mask -## and crop it -img <- magick::image_read(raw_file) -mask <- magick::image_read(mask_file) +## inject the clip definition next to the tag and clip the +## svglite drawing group to the hexagon +svg_line <- grep("", + "", + svg, + fixed = TRUE +) -out <- magick::image_composite(img, mask, operator = "CopyOpacity") -magick::image_write(out, final_file) +writeLines(svg, final_file) +usethis::use_logo(final_file, geometry = "1980x1200") if (clean) { - base::unlink(c(mask_file, raw_file)) + base::unlink(raw_file, force = TRUE) + base::unlink(final_file, force = TRUE) } diff --git a/dev/socialPreview.R b/dev/socialPreview.R new file mode 100644 index 000000000..ac9efb52c --- /dev/null +++ b/dev/socialPreview.R @@ -0,0 +1,160 @@ +## script: social-preview +## author: Serkan Korkmaz +## objective: Generate the GitHub social preview (1280x640) +## using the same color palette, synthetic data, and ggplot +## scaffolding as dev/hexSticker.R so the preview shares the +## hex sticker's brand identity. +## +## Output: man/figures/social-preview.png +## man/figures/social-preview.svg +## +## Usage: +## Rscript dev/social-preview.R + +out_file <- "man/figures/social-preview.png" +out_file_svg <- "man/figures/social-preview.svg" + +## ---- colors (mirroring dev/hexSticker.R) ---- +bg <- "#101A24" +accent <- "#6FBFBF" +up <- "#65a479" +down <- "#d5695d" +ink <- "#D8DEE3" + +ma_short_col <- accent +ma_long_col <- "#00BFA6" +wick_col <- "#B3C2D1" + +grid_major_col <- "#1A2A38" +grid_minor_col <- "#14222D" + +## ---- synthetic OHLC series ---- +## same seed and generator as dev/hexSticker.R +set.seed(1903) +n <- 18 +x <- seq_len(n) +open <- cumsum(rnorm(n, 0, 1)) + 100 +close <- open + rnorm(n, 0, 1) +high <- pmax(open, close) + runif(n, 0.4, 1.1) +low <- pmin(open, close) - runif(n, 0.4, 1.1) +OHLC <- data.frame(x, open, close, high, low, up = close >= open) + +## ---- moving averages (long / short) ---- +ma_short <- stats::filter(close, rep(1 / 3, 3), sides = 1) +ma_long <- stats::filter(close, rep(1 / 6, 6), sides = 1) + +## ---- gridlines ---- +y_rng <- range(OHLC$low, OHLC$high) +y_major <- pretty(y_rng, n = 5) +y_minor <- setdiff(pretty(y_rng, n = 11), y_major) + +x_major <- pretty(range(OHLC$x), n = 6) +x_minor <- setdiff(pretty(range(OHLC$x), n = 13), x_major) + +## ---- plot ---- +w <- 0.34 + +p <- ggplot2::ggplot(OHLC, ggplot2::aes(x = x)) + + ggplot2::geom_hline( + yintercept = y_major, + color = grid_major_col, + linewidth = 0.28, + alpha = 0.55 + ) + + ggplot2::geom_hline( + yintercept = y_minor, + color = grid_minor_col, + linewidth = 0.22, + alpha = 0.35 + ) + + ggplot2::geom_vline( + xintercept = x_major, + color = grid_major_col, + linewidth = 0.26, + alpha = 0.55 + ) + + ggplot2::geom_vline( + xintercept = x_minor, + color = grid_minor_col, + linewidth = 0.20, + alpha = 0.35 + ) + + ## candle wicks + ggplot2::geom_segment( + ggplot2::aes(xend = x, y = low, yend = high), + linewidth = 0.45, + color = wick_col + ) + + ## candle bodies + ggplot2::geom_rect( + ggplot2::aes( + xmin = x - w, + xmax = x + w, + ymin = pmin(open, close), + ymax = pmax(open, close), + fill = up, + color = up + ), + linewidth = 0.25 + ) + + ## moving averages + ggplot2::geom_line( + ggplot2::aes(y = ma_long), + color = ma_long_col, + linewidth = 0.8, + na.rm = TRUE + ) + + ggplot2::geom_line( + ggplot2::aes(y = ma_short), + color = ma_short_col, + linewidth = 1.0, + na.rm = TRUE + ) + + ggplot2::scale_fill_manual(values = c(`TRUE` = up, `FALSE` = down)) + + ggplot2::scale_color_manual(values = c(`TRUE` = up, `FALSE` = down)) + + ## symmetric horizontal padding so the first and last candle bodies + ## (which extend +/- w around their x position) are fully visible + ggplot2::coord_cartesian( + xlim = c(1 - w - 0.15, n + w + 0.15), + expand = FALSE + ) + + ggplot2::theme_void() + + ggplot2::theme( + legend.position = "none", + plot.background = ggplot2::element_rect(fill = bg, color = NA), + panel.background = ggplot2::element_rect(fill = bg, color = NA) + ) + +## ---- save (1280 x 640) ---- +ggplot2::ggsave( + filename = out_file, + plot = p, + width = 1280, + height = 640, + units = "px", + dpi = 132, + device = ragg::agg_png, + bg = bg +) + +ggplot2::ggsave( + filename = out_file_svg, + plot = p, + width = 1280, + height = 640, + units = "px", + dpi = 132, + device = svglite::svglite, + bg = bg +) + +## svglite declares the canvas in physical pt; rewrite it to +## 1280x640 (CSS px) so the SVG reports the same dimensions as +## the PNG -- the viewBox is kept, so the drawing is unchanged +svg <- readLines(out_file_svg, warn = FALSE) +svg <- sub( + "width='[^']*' height='[^']*' (viewBox=)", + "width='1280' height='640' \\1", + svg +) +writeLines(svg, out_file_svg) diff --git a/man-roxygen/description.R b/man-roxygen/description.R index 7b7426fb6..06f0babbc 100644 --- a/man-roxygen/description.R +++ b/man-roxygen/description.R @@ -62,12 +62,12 @@ <% } %> #' <% fun_args <- names(formals(.fun)) %> -<% if ("n" %in% fun_args) { %> -#' @param n ([integer]). Lookback period (window size). A positive [integer] +<% if ("timePeriod" %in% fun_args) { %> +#' @param timePeriod ([integer]). Lookback period (window size). A positive [integer] #' of [length] 1. <% } %> -<% if ("eps" %in% fun_args) { %> -#' @param eps ([double]). Penetration threshold for candlestick pattern +<% if ("penetration" %in% fun_args) { %> +#' @param penetration ([double]). Penetration threshold for candlestick pattern #' recognition, expressed as a fraction of the candle body. A [double] of #' [length] 1. <% } %> @@ -92,6 +92,7 @@ #' @concept trading #' @concept algorithmic trading #' +<% if (!exists(".custom_example")) { %> <% if (grepl(pattern = "Price Transform", x = .family)) { %> #' @examples #' ## load Bitcoin (BTC) @@ -136,3 +137,4 @@ #' } <% } %> +<% } %> diff --git a/man-roxygen/returns.R b/man-roxygen/returns.R index 603b7d9d2..443b8c050 100644 --- a/man-roxygen/returns.R +++ b/man-roxygen/returns.R @@ -2,4 +2,4 @@ #' #' An object of same [class] and [length] of `x`: #' -#' `r generate_returns_section(<%= tolower(.fun) %>(talib::BTC))` +#' `r BTC <- talib::BTC; generate_returns_section(<%= tolower(.fun) %>(BTC<%= if (.fun == "variable_moving_average_period") ", periods = runif(nrow(BTC), 10, 20)" else "" %>))` diff --git a/man-roxygen/rolling_description.R b/man-roxygen/rolling_description.R index a9dda6307..5143c256e 100644 --- a/man-roxygen/rolling_description.R +++ b/man-roxygen/rolling_description.R @@ -30,8 +30,8 @@ #' <% } %> <% fun_args <- names(formals(.fun)) %> -<% if ("n" %in% fun_args) { %> -#' @param n ([integer]). Lookback period (window size). A positive [integer] +<% if ("timePeriod" %in% fun_args) { %> +#' @param timePeriod ([integer]). Lookback period (window size). A positive [integer] #' of [length] 1. <% } %> <% if ("na.bridge" %in% fun_args) { %> diff --git a/man/examples/MAVP-example.R b/man/examples/MAVP-example.R new file mode 100644 index 000000000..2f523e7cf --- /dev/null +++ b/man/examples/MAVP-example.R @@ -0,0 +1,39 @@ +## load Bitcoin (BTC) +## series +data(BTC, package = "talib") + +## define a random series +## of periods to evaluate +## each candle +periods <- runif( + n = nrow(BTC), + min = 5, + max = 10 +) + +## calculate the indicator +## for Bitcoin (BTC) +utils::tail( + talib::variable_moving_average_period( + BTC, + periods = periods + ) +) + +## visualize the indicator +## with talib::chart() +## +## see ?talib::chart or ?talib::indicator +## for more details +{ + ## chart OHLC-V + ## series with talib::chart() + talib::chart(BTC) + + ## chart indicator + ## with default values + talib::indicator( + talib::variable_moving_average_period, + periods = periods + ) +} 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..a06e9518a 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/man/figures/logo.png b/man/figures/logo.png deleted file mode 100644 index 75c24715e..000000000 Binary files a/man/figures/logo.png and /dev/null differ diff --git a/man/figures/logo.svg b/man/figures/logo.svg new file mode 100644 index 000000000..97ace00dc --- /dev/null +++ b/man/figures/logo.svg @@ -0,0 +1,234 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/man/figures/social-preview.png b/man/figures/social-preview.png new file mode 100644 index 000000000..90b3c7cf6 Binary files /dev/null and b/man/figures/social-preview.png differ diff --git a/man/figures/social-preview.svg b/man/figures/social-preview.svg new file mode 100644 index 000000000..3b95eb5e0 --- /dev/null +++ b/man/figures/social-preview.svg @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/MAType.h b/src/MAType.h deleted file mode 100644 index ce2910b2c..000000000 --- a/src/MAType.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef _MATYPE_H -#define _MATYPE_H -// as_MAType -// -// Parameters: -// x: SEXP -// Description -// Syntactic sugar for mapping SEXP -// to TA_MAType -#include "Rinternals.h" -#include "ta_defs.h" - -static inline TA_MAType as_MAType(SEXP x) { - int x_ = INTEGER(x)[0]; - return (TA_MAType)x_; -} - -// clang-format off -static inline const char *_MAType_(TA_MAType t) { - static const char *const k[] = { - "SMA", - "EMA", - "WMA", - "DEMA", - "TEMA", - "TRIMA", - "KAMA", - "MAMA", - "T3" - }; - unsigned u = (unsigned)t; - return u < (sizeof k / sizeof k[0]) ? k[u] : "INVALID"; -} -// clang-format on - -#endif // _MATYPE_H diff --git a/src/NA-handling.c b/src/NA-handling.c new file mode 100644 index 000000000..87880eb50 --- /dev/null +++ b/src/NA-handling.c @@ -0,0 +1,144 @@ +// -handling +// +// Description +// TA-Lib does handle -values if passed into the +// TA_()-function—it returns all if a +// single is passed via in*-arrays. +// +// This C-routine strips all while recording their positional +// index, and then reinserts them once the indicator is returned, +// if (bool) na.bridge is passed as TRUE from the R-side. +// +#include "NA-handling.h" +#include +#include +#include + +// clang-format off +#define TA_BIT_GET(bitmask, bit_index) \ + ((bitmask)[(R_xlen_t)(bit_index) >> 3] & (unsigned char) (1u << ((bit_index) & 7))) +#define TA_BIT_SET(bitmask, bit_index) \ + ((bitmask)[(R_xlen_t)(bit_index) >> 3] |= (unsigned char) (1u << ((bit_index) & 7))) +// clang-format on + +// clang-format off +R_xlen_t build_presence_mask( + const double *const *input_columns, + int k_columns, + R_xlen_t n_rows, + unsigned char **presence_mask +) +// clang-format on +{ + // one bit per row, rounded up to whole bytes + size_t nbytes = (size_t)((n_rows + 7) / 8); + + unsigned char *mask = (unsigned char *)R_alloc(nbytes, 1); + memset(mask, 0, nbytes); + + R_xlen_t num_present = 0; + for (R_xlen_t row = 0; row < n_rows; row++) { + int present = 1; + for (int col = 0; col < k_columns; col++) { + if (ISNAN(input_columns[col][row])) { + present = 0; + break; + } + } + if (present) { + TA_BIT_SET(mask, row); + num_present++; + } + } + + *presence_mask = mask; + return num_present; +} + +// clang-format off +double *dense_array( + R_xlen_t num_present_rows, + int k_columns +) +// clang-format on +{ + return (double *)R_alloc( + (size_t)num_present_rows * (size_t)k_columns, + sizeof(double)); +} + +// clang-format off +double *compact_array( + double *dense_column, + const double *full_column, + const unsigned char *presence_mask, + R_xlen_t n_rows +) +// clang-format on +{ + R_xlen_t dense = 0; + for (R_xlen_t row = 0; row < n_rows; row++) { + if (TA_BIT_GET(presence_mask, row)) { + dense_column[dense++] = full_column[row]; + } + } + return dense_column; +} + +// clang-format off +void scatter_double_array( + double *column, + R_xlen_t n_rows, + const unsigned char *presence_mask, + R_xlen_t num_present_rows, + int begIdx, + int nbElement +) +// clang-format on +{ + R_xlen_t dense = num_present_rows - 1; + R_xlen_t raw = (R_xlen_t)nbElement - 1; + for (R_xlen_t row = n_rows - 1; row >= 0; row--) { + if (dense >= 0 && TA_BIT_GET(presence_mask, row)) { + if (dense >= (R_xlen_t)begIdx && raw >= 0) { + column[row] = column[raw]; + raw--; + } else { + column[row] = NA_REAL; + } + dense--; + } else { + column[row] = NA_REAL; + } + } +} + +// clang-format off +void scatter_integer_array( + int *column, + R_xlen_t n_rows, + const unsigned char *presence_mask, + R_xlen_t num_present_rows, + int begIdx, + int nbElement +) +// clang-format on +{ + R_xlen_t dense = num_present_rows - 1; + R_xlen_t raw = (R_xlen_t)nbElement - 1; + for (R_xlen_t row = n_rows - 1; row >= 0; row--) { + if (dense >= 0 && TA_BIT_GET(presence_mask, row)) { + if (dense >= (R_xlen_t)begIdx && raw >= 0) { + column[row] = column[raw]; + raw--; + } else { + column[row] = NA_INTEGER; + } + dense--; + } else { + column[row] = NA_INTEGER; + } + } +} +#undef TA_BIT_GET +#undef TA_BIT_SET diff --git a/src/NA-handling.h b/src/NA-handling.h new file mode 100644 index 000000000..89506956f --- /dev/null +++ b/src/NA-handling.h @@ -0,0 +1,58 @@ +// NA-handling.h +// +// Description +// Public interface for the `na.bridge` path: drop rows where any input +// is NA/NaN, compute the indicator on the dense (gap-free) series, then +// scatter the results back to their original row positions. Kept in one +// place so all generated wrappers share a single, memory-lean routine. +// +#ifndef NA_HANDLING_H +#define NA_HANDLING_H + +#include + +R_xlen_t build_presence_mask( + const double *const *input_columns, + int k_columns, + R_xlen_t n_rows, + unsigned char **presence_mask); + +double *dense_array(R_xlen_t num_present_rows, int k_columns); + +double *compact_array( + double *dense_column, + const double *full_column, + const unsigned char *presence_mask, + R_xlen_t n_rows); + +void scatter_double_array( + double *column, + R_xlen_t n_rows, + const unsigned char *presence_mask, + R_xlen_t num_present_rows, + int begIdx, + int nbElement); + +void scatter_integer_array( + int *column, + R_xlen_t n_rows, + const unsigned char *presence_mask, + R_xlen_t num_present_rows, + int begIdx, + int nbElement); + +// clang-format off +// Generic scatter_array +// +// Description +// Works similar to S3 functions in R +// _Generic( (x), type: dispatch ) ( signature ) +#define scatter_array(column, n_rows, presence_mask, num_present_rows, begIdx, nbElement) \ + _Generic((column), \ + double *: scatter_double_array, \ + int *: scatter_integer_array \ + )((column), (n_rows), (presence_mask), (num_present_rows), (begIdx), (nbElement)) +// clang-format on +// scatter array end + +#endif /* NA_HANDLING_H */ diff --git a/src/lib.c b/src/TA-Lib.c similarity index 67% rename from src/lib.c rename to src/TA-Lib.c index 1d908e2e2..b8b7f7eff 100644 --- a/src/lib.c +++ b/src/TA-Lib.c @@ -1,54 +1,6 @@ -// TA-Lib specific options -#include "lib.h" -#include "R_ext/Error.h" -#include "api.h" -#include "shift.h" -#include "ta_defs.h" -#include "ta_func.h" -#include +#include "ta_libc.h" +#include "utils.h" #include -#include - -// initialize TA-Lib -SEXP initialize_ta_lib(void) { - TA_RetCode return_code = TA_Initialize(); - - if (return_code != TA_SUCCESS) { - Rf_error("TA_Initialize failed (code %d)", return_code); - } - - return ScalarLogical(1); -} - -// shutdown TA-Lib -SEXP shutdown_ta_lib(void) { - TA_RetCode return_code = TA_Shutdown(); - - if (return_code != TA_SUCCESS) { - Rf_error("TA_Shutdown failed (code %d)", return_code); - } - - return ScalarLogical(1); -} - -// candlestick options -// -SEXP reset_candle_setting(void) { - - // reset all candle settings - // clang-format off - TA_RetCode return_code = TA_RestoreCandleDefaultSettings( TA_AllCandleSettings - ); - // clang-format on - - // send a warning instead of error - // to allow the interface some slack - if (return_code != TA_SUCCESS) { - Rf_warning("Candle settings failed (Code %d)", return_code); - } - - return Rf_ScalarLogical(1); -} // Candle Settings // @@ -79,26 +31,19 @@ SEXP reset_candle_setting(void) { // // clang-format off SEXP set_candle_setting( - SEXP s_settingType, - SEXP s_rangeType, - SEXP s_avgPeriod, - SEXP s_factor + SEXP settingType, + SEXP rangeType, + SEXP avgPeriod, + SEXP factor ) { // clang-format on - // extract values to be passed - // onto settings - const TA_CandleSettingType settingType = INTEGER(s_settingType)[0]; - const TA_RangeType rangeType = INTEGER(s_rangeType)[0]; - const int avgPeriod = INTEGER(s_avgPeriod)[0]; - const double factor = REAL(s_factor)[0]; - // clang-format off TA_RetCode return_code = TA_SetCandleSettings( - settingType, - rangeType, - avgPeriod, - factor + (TA_CandleSettingType) Rf_asInteger(settingType), + (TA_RangeType) Rf_asInteger(rangeType), + (int) Rf_asInteger(avgPeriod), + (double) Rf_asReal(factor) ); // clang-format on @@ -108,5 +53,65 @@ SEXP set_candle_setting( Rf_warning("Candle settings failed (Code %d)", return_code); } + return Rf_ScalarLogical(1); +} + +SEXP reset_candle_setting(void) { + + // reset all candle settings + // clang-format off + TA_RetCode return_code = TA_RestoreCandleDefaultSettings( + TA_AllCandleSettings + ); + // clang-format on + + // send a warning instead of error + // to allow the interface some slack + if (return_code != TA_SUCCESS) { + Rf_warning("Candle settings failed (Code %d)", return_code); + } + + return Rf_ScalarLogical(1); +} +// Candle settings end + +SEXP ta_set_unstable_period(SEXP s_id, SEXP s_period) { + ta_check( + TA_SetUnstablePeriod( + (TA_FuncUnstId)Rf_asInteger(s_id), + (unsigned int)Rf_asInteger(s_period)), + "TA_SetUnstablePeriod"); + return R_NilValue; +} + +SEXP ta_set_compatibility(SEXP s_value) { + ta_check( + TA_SetCompatibility((TA_Compatibility)Rf_asInteger(s_value)), + "TA_SetCompatibility"); + return R_NilValue; +} + +// initialize TA-Lib +// +// NOTE: Only kept for backwards compatibility +// will be deleted after merge +SEXP initialize_ta_lib(void) { + TA_RetCode return_code = TA_Initialize(); + + if (return_code != TA_SUCCESS) { + Rf_error("TA_Initialize failed (code %d)", return_code); + } + + return Rf_ScalarLogical(1); +} + +// shutdown TA-Lib +SEXP shutdown_ta_lib(void) { + TA_RetCode return_code = TA_Shutdown(); + + if (return_code != TA_SUCCESS) { + Rf_error("TA_Shutdown failed (code %d)", return_code); + } + return Rf_ScalarLogical(1); } \ No newline at end of file diff --git a/src/TA-Lib.h b/src/TA-Lib.h new file mode 100644 index 000000000..5bbab5249 --- /dev/null +++ b/src/TA-Lib.h @@ -0,0 +1,272 @@ +// TA-Lib.h - Autogenerated via codegen/ +// Description: +// +// TA_INDICATOR: TA-Lib indicator. +// TA_INPUT: Indicator input. +// TA_OPTIONS: Indicator input. +// TA_OUTPUT: Indicator input. +// TA_OUTPUT_NAMES: Indicator input. +// TA_LOOKBACK: Indicator lookback (name + optional inputs). +// +// clang-format off +TA_INDICATOR(ACCBANDS, TA_DOUBLE, TA_INPUT(inHigh, inLow, inClose), TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod)), TA_OUTPUT(outRealUpperBand, outRealMiddleBand, outRealLowerBand), TA_OUTPUT_NAME(UpperBand, MiddleBand, LowerBand), NOT_CANDLESTICK) +TA_INDICATOR(AD, TA_DOUBLE, TA_INPUT(inHigh, inLow, inClose, inVolume), TA_OPTIONS(), TA_OUTPUT(outReal), TA_OUTPUT_NAME(AD), NOT_CANDLESTICK) +TA_INDICATOR(ADOSC, TA_DOUBLE, TA_INPUT(inHigh, inLow, inClose, inVolume), TA_OPTIONS(OPTIONAL_INTEGER(optInFastPeriod), OPTIONAL_INTEGER(optInSlowPeriod)), TA_OUTPUT(outReal), TA_OUTPUT_NAME(ADOSC), NOT_CANDLESTICK) +TA_INDICATOR(ADX, TA_DOUBLE, TA_INPUT(inHigh, inLow, inClose), TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod)), TA_OUTPUT(outReal), TA_OUTPUT_NAME(ADX), NOT_CANDLESTICK) +TA_INDICATOR(ADXR, TA_DOUBLE, TA_INPUT(inHigh, inLow, inClose), TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod)), TA_OUTPUT(outReal), TA_OUTPUT_NAME(ADXR), NOT_CANDLESTICK) +TA_INDICATOR(APO, TA_DOUBLE, TA_INPUT(inReal), TA_OPTIONS(OPTIONAL_INTEGER(optInFastPeriod), OPTIONAL_INTEGER(optInSlowPeriod), OPTIONAL_MATYPE(optInMAType)), TA_OUTPUT(outReal), TA_OUTPUT_NAME(APO), NOT_CANDLESTICK) +TA_INDICATOR(AROON, TA_DOUBLE, TA_INPUT(inHigh, inLow), TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod)), TA_OUTPUT(outAroonDown, outAroonUp), TA_OUTPUT_NAME(AroonDown, AroonUp), NOT_CANDLESTICK) +TA_INDICATOR(AROONOSC, TA_DOUBLE, TA_INPUT(inHigh, inLow), TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod)), TA_OUTPUT(outReal), TA_OUTPUT_NAME(AROONOSC), NOT_CANDLESTICK) +TA_INDICATOR(ATR, TA_DOUBLE, TA_INPUT(inHigh, inLow, inClose), TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod)), TA_OUTPUT(outReal), TA_OUTPUT_NAME(ATR), NOT_CANDLESTICK) +TA_INDICATOR(AVGDEV, TA_DOUBLE, TA_INPUT(inReal), TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod)), TA_OUTPUT(outReal), TA_OUTPUT_NAME(AVGDEV), NOT_CANDLESTICK) +TA_INDICATOR(AVGPRICE, TA_DOUBLE, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outReal), TA_OUTPUT_NAME(AVGPRICE), NOT_CANDLESTICK) +TA_INDICATOR(BBANDS, TA_DOUBLE, TA_INPUT(inReal), TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod), OPTIONAL_DOUBLE(optInNbDevUp), OPTIONAL_DOUBLE(optInNbDevDn), OPTIONAL_MATYPE(optInMAType)), TA_OUTPUT(outRealUpperBand, outRealMiddleBand, outRealLowerBand), TA_OUTPUT_NAME(UpperBand, MiddleBand, LowerBand), NOT_CANDLESTICK) +TA_INDICATOR(BETA, TA_DOUBLE, TA_INPUT(inReal0, inReal1), TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod)), TA_OUTPUT(outReal), TA_OUTPUT_NAME(BETA), NOT_CANDLESTICK) +TA_INDICATOR(BOP, TA_DOUBLE, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outReal), TA_OUTPUT_NAME(BOP), NOT_CANDLESTICK) +TA_INDICATOR(CCI, TA_DOUBLE, TA_INPUT(inHigh, inLow, inClose), TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod)), TA_OUTPUT(outReal), TA_OUTPUT_NAME(CCI), NOT_CANDLESTICK) +TA_INDICATOR(CDL2CROWS, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDL2CROWS), CANDLESTICK) +TA_INDICATOR(CDL3BLACKCROWS, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDL3BLACKCROWS), CANDLESTICK) +TA_INDICATOR(CDL3INSIDE, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDL3INSIDE), CANDLESTICK) +TA_INDICATOR(CDL3LINESTRIKE, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDL3LINESTRIKE), CANDLESTICK) +TA_INDICATOR(CDL3OUTSIDE, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDL3OUTSIDE), CANDLESTICK) +TA_INDICATOR(CDL3STARSINSOUTH, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDL3STARSINSOUTH), CANDLESTICK) +TA_INDICATOR(CDL3WHITESOLDIERS, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDL3WHITESOLDIERS), CANDLESTICK) +TA_INDICATOR(CDLABANDONEDBABY, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(OPTIONAL_DOUBLE(optInPenetration)), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDLABANDONEDBABY), CANDLESTICK) +TA_INDICATOR(CDLADVANCEBLOCK, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDLADVANCEBLOCK), CANDLESTICK) +TA_INDICATOR(CDLBELTHOLD, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDLBELTHOLD), CANDLESTICK) +TA_INDICATOR(CDLBREAKAWAY, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDLBREAKAWAY), CANDLESTICK) +TA_INDICATOR(CDLCLOSINGMARUBOZU, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDLCLOSINGMARUBOZU), CANDLESTICK) +TA_INDICATOR(CDLCONCEALBABYSWALL, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDLCONCEALBABYSWALL), CANDLESTICK) +TA_INDICATOR(CDLCOUNTERATTACK, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDLCOUNTERATTACK), CANDLESTICK) +TA_INDICATOR(CDLDARKCLOUDCOVER, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(OPTIONAL_DOUBLE(optInPenetration)), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDLDARKCLOUDCOVER), CANDLESTICK) +TA_INDICATOR(CDLDOJI, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDLDOJI), CANDLESTICK) +TA_INDICATOR(CDLDOJISTAR, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDLDOJISTAR), CANDLESTICK) +TA_INDICATOR(CDLDRAGONFLYDOJI, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDLDRAGONFLYDOJI), CANDLESTICK) +TA_INDICATOR(CDLENGULFING, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDLENGULFING), CANDLESTICK) +TA_INDICATOR(CDLEVENINGDOJISTAR, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(OPTIONAL_DOUBLE(optInPenetration)), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDLEVENINGDOJISTAR), CANDLESTICK) +TA_INDICATOR(CDLEVENINGSTAR, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(OPTIONAL_DOUBLE(optInPenetration)), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDLEVENINGSTAR), CANDLESTICK) +TA_INDICATOR(CDLGAPSIDESIDEWHITE, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDLGAPSIDESIDEWHITE), CANDLESTICK) +TA_INDICATOR(CDLGRAVESTONEDOJI, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDLGRAVESTONEDOJI), CANDLESTICK) +TA_INDICATOR(CDLHAMMER, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDLHAMMER), CANDLESTICK) +TA_INDICATOR(CDLHANGINGMAN, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDLHANGINGMAN), CANDLESTICK) +TA_INDICATOR(CDLHARAMI, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDLHARAMI), CANDLESTICK) +TA_INDICATOR(CDLHARAMICROSS, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDLHARAMICROSS), CANDLESTICK) +TA_INDICATOR(CDLHIGHWAVE, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDLHIGHWAVE), CANDLESTICK) +TA_INDICATOR(CDLHIKKAKE, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDLHIKKAKE), CANDLESTICK) +TA_INDICATOR(CDLHIKKAKEMOD, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDLHIKKAKEMOD), CANDLESTICK) +TA_INDICATOR(CDLHOMINGPIGEON, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDLHOMINGPIGEON), CANDLESTICK) +TA_INDICATOR(CDLIDENTICAL3CROWS, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDLIDENTICAL3CROWS), CANDLESTICK) +TA_INDICATOR(CDLINNECK, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDLINNECK), CANDLESTICK) +TA_INDICATOR(CDLINVERTEDHAMMER, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDLINVERTEDHAMMER), CANDLESTICK) +TA_INDICATOR(CDLKICKING, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDLKICKING), CANDLESTICK) +TA_INDICATOR(CDLKICKINGBYLENGTH, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDLKICKINGBYLENGTH), CANDLESTICK) +TA_INDICATOR(CDLLADDERBOTTOM, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDLLADDERBOTTOM), CANDLESTICK) +TA_INDICATOR(CDLLONGLEGGEDDOJI, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDLLONGLEGGEDDOJI), CANDLESTICK) +TA_INDICATOR(CDLLONGLINE, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDLLONGLINE), CANDLESTICK) +TA_INDICATOR(CDLMARUBOZU, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDLMARUBOZU), CANDLESTICK) +TA_INDICATOR(CDLMATCHINGLOW, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDLMATCHINGLOW), CANDLESTICK) +TA_INDICATOR(CDLMATHOLD, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(OPTIONAL_DOUBLE(optInPenetration)), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDLMATHOLD), CANDLESTICK) +TA_INDICATOR(CDLMORNINGDOJISTAR, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(OPTIONAL_DOUBLE(optInPenetration)), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDLMORNINGDOJISTAR), CANDLESTICK) +TA_INDICATOR(CDLMORNINGSTAR, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(OPTIONAL_DOUBLE(optInPenetration)), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDLMORNINGSTAR), CANDLESTICK) +TA_INDICATOR(CDLONNECK, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDLONNECK), CANDLESTICK) +TA_INDICATOR(CDLPIERCING, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDLPIERCING), CANDLESTICK) +TA_INDICATOR(CDLRICKSHAWMAN, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDLRICKSHAWMAN), CANDLESTICK) +TA_INDICATOR(CDLRISEFALL3METHODS, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDLRISEFALL3METHODS), CANDLESTICK) +TA_INDICATOR(CDLSEPARATINGLINES, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDLSEPARATINGLINES), CANDLESTICK) +TA_INDICATOR(CDLSHOOTINGSTAR, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDLSHOOTINGSTAR), CANDLESTICK) +TA_INDICATOR(CDLSHORTLINE, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDLSHORTLINE), CANDLESTICK) +TA_INDICATOR(CDLSPINNINGTOP, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDLSPINNINGTOP), CANDLESTICK) +TA_INDICATOR(CDLSTALLEDPATTERN, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDLSTALLEDPATTERN), CANDLESTICK) +TA_INDICATOR(CDLSTICKSANDWICH, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDLSTICKSANDWICH), CANDLESTICK) +TA_INDICATOR(CDLTAKURI, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDLTAKURI), CANDLESTICK) +TA_INDICATOR(CDLTASUKIGAP, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDLTASUKIGAP), CANDLESTICK) +TA_INDICATOR(CDLTHRUSTING, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDLTHRUSTING), CANDLESTICK) +TA_INDICATOR(CDLTRISTAR, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDLTRISTAR), CANDLESTICK) +TA_INDICATOR(CDLUNIQUE3RIVER, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDLUNIQUE3RIVER), CANDLESTICK) +TA_INDICATOR(CDLUPSIDEGAP2CROWS, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDLUPSIDEGAP2CROWS), CANDLESTICK) +TA_INDICATOR(CDLXSIDEGAP3METHODS, TA_INTEGER, TA_INPUT(inOpen, inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(CDLXSIDEGAP3METHODS), CANDLESTICK) +TA_INDICATOR(CMO, TA_DOUBLE, TA_INPUT(inReal), TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod)), TA_OUTPUT(outReal), TA_OUTPUT_NAME(CMO), NOT_CANDLESTICK) +TA_INDICATOR(CORREL, TA_DOUBLE, TA_INPUT(inReal0, inReal1), TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod)), TA_OUTPUT(outReal), TA_OUTPUT_NAME(CORREL), NOT_CANDLESTICK) +TA_INDICATOR(DEMA, TA_DOUBLE, TA_INPUT(inReal), TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod)), TA_OUTPUT(outReal), TA_OUTPUT_NAME(DEMA), NOT_CANDLESTICK) +TA_INDICATOR(DX, TA_DOUBLE, TA_INPUT(inHigh, inLow, inClose), TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod)), TA_OUTPUT(outReal), TA_OUTPUT_NAME(DX), NOT_CANDLESTICK) +TA_INDICATOR(EMA, TA_DOUBLE, TA_INPUT(inReal), TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod)), TA_OUTPUT(outReal), TA_OUTPUT_NAME(EMA), NOT_CANDLESTICK) +TA_INDICATOR(HT_DCPERIOD, TA_DOUBLE, TA_INPUT(inReal), TA_OPTIONS(), TA_OUTPUT(outReal), TA_OUTPUT_NAME(HT_DCPERIOD), NOT_CANDLESTICK) +TA_INDICATOR(HT_DCPHASE, TA_DOUBLE, TA_INPUT(inReal), TA_OPTIONS(), TA_OUTPUT(outReal), TA_OUTPUT_NAME(HT_DCPHASE), NOT_CANDLESTICK) +TA_INDICATOR(HT_PHASOR, TA_DOUBLE, TA_INPUT(inReal), TA_OPTIONS(), TA_OUTPUT(outInPhase, outQuadrature), TA_OUTPUT_NAME(InPhase, Quadrature), NOT_CANDLESTICK) +TA_INDICATOR(HT_SINE, TA_DOUBLE, TA_INPUT(inReal), TA_OPTIONS(), TA_OUTPUT(outSine, outLeadSine), TA_OUTPUT_NAME(Sine, LeadSine), NOT_CANDLESTICK) +TA_INDICATOR(HT_TRENDLINE, TA_DOUBLE, TA_INPUT(inReal), TA_OPTIONS(), TA_OUTPUT(outReal), TA_OUTPUT_NAME(HT_TRENDLINE), NOT_CANDLESTICK) +TA_INDICATOR(HT_TRENDMODE, TA_INTEGER, TA_INPUT(inReal), TA_OPTIONS(), TA_OUTPUT(outInteger), TA_OUTPUT_NAME(HT_TRENDMODE), NOT_CANDLESTICK) +TA_INDICATOR(IMI, TA_DOUBLE, TA_INPUT(inOpen, inClose), TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod)), TA_OUTPUT(outReal), TA_OUTPUT_NAME(IMI), NOT_CANDLESTICK) +TA_INDICATOR(KAMA, TA_DOUBLE, TA_INPUT(inReal), TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod)), TA_OUTPUT(outReal), TA_OUTPUT_NAME(KAMA), NOT_CANDLESTICK) +TA_INDICATOR(MACD, TA_DOUBLE, TA_INPUT(inReal), TA_OPTIONS(OPTIONAL_INTEGER(optInFastPeriod), OPTIONAL_INTEGER(optInSlowPeriod), OPTIONAL_INTEGER(optInSignalPeriod)), TA_OUTPUT(outMACD, outMACDSignal, outMACDHist), TA_OUTPUT_NAME(MACD, MACDSignal, MACDHist), NOT_CANDLESTICK) +TA_INDICATOR(MACDEXT, TA_DOUBLE, TA_INPUT(inReal), TA_OPTIONS(OPTIONAL_INTEGER(optInFastPeriod), OPTIONAL_MATYPE(optInFastMAType), OPTIONAL_INTEGER(optInSlowPeriod), OPTIONAL_MATYPE(optInSlowMAType), OPTIONAL_INTEGER(optInSignalPeriod), OPTIONAL_MATYPE(optInSignalMAType)), TA_OUTPUT(outMACD, outMACDSignal, outMACDHist), TA_OUTPUT_NAME(MACD, MACDSignal, MACDHist), NOT_CANDLESTICK) +TA_INDICATOR(MACDFIX, TA_DOUBLE, TA_INPUT(inReal), TA_OPTIONS(OPTIONAL_INTEGER(optInSignalPeriod)), TA_OUTPUT(outMACD, outMACDSignal, outMACDHist), TA_OUTPUT_NAME(MACD, MACDSignal, MACDHist), NOT_CANDLESTICK) +TA_INDICATOR(MAMA, TA_DOUBLE, TA_INPUT(inReal), TA_OPTIONS(OPTIONAL_DOUBLE(optInFastLimit), OPTIONAL_DOUBLE(optInSlowLimit)), TA_OUTPUT(outMAMA, outFAMA), TA_OUTPUT_NAME(MAMA, FAMA), NOT_CANDLESTICK) +TA_INDICATOR(MAVP, TA_DOUBLE, TA_INPUT(inReal, inPeriods), TA_OPTIONS(OPTIONAL_INTEGER(optInMinPeriod), OPTIONAL_INTEGER(optInMaxPeriod), OPTIONAL_MATYPE(optInMAType)), TA_OUTPUT(outReal), TA_OUTPUT_NAME(MAVP), NOT_CANDLESTICK) +TA_INDICATOR(MAX, TA_DOUBLE, TA_INPUT(inReal), TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod)), TA_OUTPUT(outReal), TA_OUTPUT_NAME(MAX), NOT_CANDLESTICK) +TA_INDICATOR(MEDPRICE, TA_DOUBLE, TA_INPUT(inHigh, inLow), TA_OPTIONS(), TA_OUTPUT(outReal), TA_OUTPUT_NAME(MEDPRICE), NOT_CANDLESTICK) +TA_INDICATOR(MFI, TA_DOUBLE, TA_INPUT(inHigh, inLow, inClose, inVolume), TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod)), TA_OUTPUT(outReal), TA_OUTPUT_NAME(MFI), NOT_CANDLESTICK) +TA_INDICATOR(MIDPOINT, TA_DOUBLE, TA_INPUT(inReal), TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod)), TA_OUTPUT(outReal), TA_OUTPUT_NAME(MIDPOINT), NOT_CANDLESTICK) +TA_INDICATOR(MIDPRICE, TA_DOUBLE, TA_INPUT(inHigh, inLow), TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod)), TA_OUTPUT(outReal), TA_OUTPUT_NAME(MIDPRICE), NOT_CANDLESTICK) +TA_INDICATOR(MIN, TA_DOUBLE, TA_INPUT(inReal), TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod)), TA_OUTPUT(outReal), TA_OUTPUT_NAME(MIN), NOT_CANDLESTICK) +TA_INDICATOR(MINUS_DI, TA_DOUBLE, TA_INPUT(inHigh, inLow, inClose), TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod)), TA_OUTPUT(outReal), TA_OUTPUT_NAME(MINUS_DI), NOT_CANDLESTICK) +TA_INDICATOR(MINUS_DM, TA_DOUBLE, TA_INPUT(inHigh, inLow), TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod)), TA_OUTPUT(outReal), TA_OUTPUT_NAME(MINUS_DM), NOT_CANDLESTICK) +TA_INDICATOR(MOM, TA_DOUBLE, TA_INPUT(inReal), TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod)), TA_OUTPUT(outReal), TA_OUTPUT_NAME(MOM), NOT_CANDLESTICK) +TA_INDICATOR(NATR, TA_DOUBLE, TA_INPUT(inHigh, inLow, inClose), TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod)), TA_OUTPUT(outReal), TA_OUTPUT_NAME(NATR), NOT_CANDLESTICK) +TA_INDICATOR(OBV, TA_DOUBLE, TA_INPUT(inReal, inVolume), TA_OPTIONS(), TA_OUTPUT(outReal), TA_OUTPUT_NAME(OBV), NOT_CANDLESTICK) +TA_INDICATOR(PLUS_DI, TA_DOUBLE, TA_INPUT(inHigh, inLow, inClose), TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod)), TA_OUTPUT(outReal), TA_OUTPUT_NAME(PLUS_DI), NOT_CANDLESTICK) +TA_INDICATOR(PLUS_DM, TA_DOUBLE, TA_INPUT(inHigh, inLow), TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod)), TA_OUTPUT(outReal), TA_OUTPUT_NAME(PLUS_DM), NOT_CANDLESTICK) +TA_INDICATOR(PPO, TA_DOUBLE, TA_INPUT(inReal), TA_OPTIONS(OPTIONAL_INTEGER(optInFastPeriod), OPTIONAL_INTEGER(optInSlowPeriod), OPTIONAL_MATYPE(optInMAType)), TA_OUTPUT(outReal), TA_OUTPUT_NAME(PPO), NOT_CANDLESTICK) +TA_INDICATOR(ROCR, TA_DOUBLE, TA_INPUT(inReal), TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod)), TA_OUTPUT(outReal), TA_OUTPUT_NAME(ROCR), NOT_CANDLESTICK) +TA_INDICATOR(RSI, TA_DOUBLE, TA_INPUT(inReal), TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod)), TA_OUTPUT(outReal), TA_OUTPUT_NAME(RSI), NOT_CANDLESTICK) +TA_INDICATOR(SAR, TA_DOUBLE, TA_INPUT(inHigh, inLow), TA_OPTIONS(OPTIONAL_DOUBLE(optInAcceleration), OPTIONAL_DOUBLE(optInMaximum)), TA_OUTPUT(outReal), TA_OUTPUT_NAME(SAR), NOT_CANDLESTICK) +TA_INDICATOR(SAREXT, TA_DOUBLE, TA_INPUT(inHigh, inLow), TA_OPTIONS(OPTIONAL_DOUBLE(optInStartValue), OPTIONAL_DOUBLE(optInOffsetOnReverse), OPTIONAL_DOUBLE(optInAccelerationInitLong), OPTIONAL_DOUBLE(optInAccelerationLong), OPTIONAL_DOUBLE(optInAccelerationMaxLong), OPTIONAL_DOUBLE(optInAccelerationInitShort), OPTIONAL_DOUBLE(optInAccelerationShort), OPTIONAL_DOUBLE(optInAccelerationMaxShort)), TA_OUTPUT(outReal), TA_OUTPUT_NAME(SAREXT), NOT_CANDLESTICK) +TA_INDICATOR(SMA, TA_DOUBLE, TA_INPUT(inReal), TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod)), TA_OUTPUT(outReal), TA_OUTPUT_NAME(SMA), NOT_CANDLESTICK) +TA_INDICATOR(STDDEV, TA_DOUBLE, TA_INPUT(inReal), TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod), OPTIONAL_DOUBLE(optInNbDev)), TA_OUTPUT(outReal), TA_OUTPUT_NAME(STDDEV), NOT_CANDLESTICK) +TA_INDICATOR(STOCH, TA_DOUBLE, TA_INPUT(inHigh, inLow, inClose), TA_OPTIONS(OPTIONAL_INTEGER(optInFastK_Period), OPTIONAL_INTEGER(optInSlowK_Period), OPTIONAL_MATYPE(optInSlowK_MAType), OPTIONAL_INTEGER(optInSlowD_Period), OPTIONAL_MATYPE(optInSlowD_MAType)), TA_OUTPUT(outSlowK, outSlowD), TA_OUTPUT_NAME(SlowK, SlowD), NOT_CANDLESTICK) +TA_INDICATOR(STOCHF, TA_DOUBLE, TA_INPUT(inHigh, inLow, inClose), TA_OPTIONS(OPTIONAL_INTEGER(optInFastK_Period), OPTIONAL_INTEGER(optInFastD_Period), OPTIONAL_MATYPE(optInFastD_MAType)), TA_OUTPUT(outFastK, outFastD), TA_OUTPUT_NAME(FastK, FastD), NOT_CANDLESTICK) +TA_INDICATOR(STOCHRSI, TA_DOUBLE, TA_INPUT(inReal), TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod), OPTIONAL_INTEGER(optInFastK_Period), OPTIONAL_INTEGER(optInFastD_Period), OPTIONAL_MATYPE(optInFastD_MAType)), TA_OUTPUT(outFastK, outFastD), TA_OUTPUT_NAME(FastK, FastD), NOT_CANDLESTICK) +TA_INDICATOR(SUM, TA_DOUBLE, TA_INPUT(inReal), TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod)), TA_OUTPUT(outReal), TA_OUTPUT_NAME(SUM), NOT_CANDLESTICK) +TA_INDICATOR(T3, TA_DOUBLE, TA_INPUT(inReal), TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod), OPTIONAL_DOUBLE(optInVFactor)), TA_OUTPUT(outReal), TA_OUTPUT_NAME(T3), NOT_CANDLESTICK) +TA_INDICATOR(TEMA, TA_DOUBLE, TA_INPUT(inReal), TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod)), TA_OUTPUT(outReal), TA_OUTPUT_NAME(TEMA), NOT_CANDLESTICK) +TA_INDICATOR(TRANGE, TA_DOUBLE, TA_INPUT(inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outReal), TA_OUTPUT_NAME(TRANGE), NOT_CANDLESTICK) +TA_INDICATOR(TRIMA, TA_DOUBLE, TA_INPUT(inReal), TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod)), TA_OUTPUT(outReal), TA_OUTPUT_NAME(TRIMA), NOT_CANDLESTICK) +TA_INDICATOR(TRIX, TA_DOUBLE, TA_INPUT(inReal), TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod)), TA_OUTPUT(outReal), TA_OUTPUT_NAME(TRIX), NOT_CANDLESTICK) +TA_INDICATOR(TYPPRICE, TA_DOUBLE, TA_INPUT(inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outReal), TA_OUTPUT_NAME(TYPPRICE), NOT_CANDLESTICK) +TA_INDICATOR(ULTOSC, TA_DOUBLE, TA_INPUT(inHigh, inLow, inClose), TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod1), OPTIONAL_INTEGER(optInTimePeriod2), OPTIONAL_INTEGER(optInTimePeriod3)), TA_OUTPUT(outReal), TA_OUTPUT_NAME(ULTOSC), NOT_CANDLESTICK) +TA_INDICATOR(VAR, TA_DOUBLE, TA_INPUT(inReal), TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod), OPTIONAL_DOUBLE(optInNbDev)), TA_OUTPUT(outReal), TA_OUTPUT_NAME(VAR), NOT_CANDLESTICK) +TA_INDICATOR(WCLPRICE, TA_DOUBLE, TA_INPUT(inHigh, inLow, inClose), TA_OPTIONS(), TA_OUTPUT(outReal), TA_OUTPUT_NAME(WCLPRICE), NOT_CANDLESTICK) +TA_INDICATOR(WILLR, TA_DOUBLE, TA_INPUT(inHigh, inLow, inClose), TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod)), TA_OUTPUT(outReal), TA_OUTPUT_NAME(WILLR), NOT_CANDLESTICK) +TA_INDICATOR(WMA, TA_DOUBLE, TA_INPUT(inReal), TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod)), TA_OUTPUT(outReal), TA_OUTPUT_NAME(WMA), NOT_CANDLESTICK) + +// Lookback +TA_LOOKBACK(ACCBANDS, TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod))) +TA_LOOKBACK(AD, TA_OPTIONS()) +TA_LOOKBACK(ADOSC, TA_OPTIONS(OPTIONAL_INTEGER(optInFastPeriod), OPTIONAL_INTEGER(optInSlowPeriod))) +TA_LOOKBACK(ADX, TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod))) +TA_LOOKBACK(ADXR, TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod))) +TA_LOOKBACK(APO, TA_OPTIONS(OPTIONAL_INTEGER(optInFastPeriod), OPTIONAL_INTEGER(optInSlowPeriod), OPTIONAL_MATYPE(optInMAType))) +TA_LOOKBACK(AROON, TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod))) +TA_LOOKBACK(AROONOSC, TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod))) +TA_LOOKBACK(ATR, TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod))) +TA_LOOKBACK(AVGDEV, TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod))) +TA_LOOKBACK(AVGPRICE, TA_OPTIONS()) +TA_LOOKBACK(BBANDS, TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod), OPTIONAL_DOUBLE(optInNbDevUp), OPTIONAL_DOUBLE(optInNbDevDn), OPTIONAL_MATYPE(optInMAType))) +TA_LOOKBACK(BETA, TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod))) +TA_LOOKBACK(BOP, TA_OPTIONS()) +TA_LOOKBACK(CCI, TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod))) +TA_LOOKBACK(CDL2CROWS, TA_OPTIONS()) +TA_LOOKBACK(CDL3BLACKCROWS, TA_OPTIONS()) +TA_LOOKBACK(CDL3INSIDE, TA_OPTIONS()) +TA_LOOKBACK(CDL3LINESTRIKE, TA_OPTIONS()) +TA_LOOKBACK(CDL3OUTSIDE, TA_OPTIONS()) +TA_LOOKBACK(CDL3STARSINSOUTH, TA_OPTIONS()) +TA_LOOKBACK(CDL3WHITESOLDIERS, TA_OPTIONS()) +TA_LOOKBACK(CDLABANDONEDBABY, TA_OPTIONS(OPTIONAL_DOUBLE(optInPenetration))) +TA_LOOKBACK(CDLADVANCEBLOCK, TA_OPTIONS()) +TA_LOOKBACK(CDLBELTHOLD, TA_OPTIONS()) +TA_LOOKBACK(CDLBREAKAWAY, TA_OPTIONS()) +TA_LOOKBACK(CDLCLOSINGMARUBOZU, TA_OPTIONS()) +TA_LOOKBACK(CDLCONCEALBABYSWALL, TA_OPTIONS()) +TA_LOOKBACK(CDLCOUNTERATTACK, TA_OPTIONS()) +TA_LOOKBACK(CDLDARKCLOUDCOVER, TA_OPTIONS(OPTIONAL_DOUBLE(optInPenetration))) +TA_LOOKBACK(CDLDOJI, TA_OPTIONS()) +TA_LOOKBACK(CDLDOJISTAR, TA_OPTIONS()) +TA_LOOKBACK(CDLDRAGONFLYDOJI, TA_OPTIONS()) +TA_LOOKBACK(CDLENGULFING, TA_OPTIONS()) +TA_LOOKBACK(CDLEVENINGDOJISTAR, TA_OPTIONS(OPTIONAL_DOUBLE(optInPenetration))) +TA_LOOKBACK(CDLEVENINGSTAR, TA_OPTIONS(OPTIONAL_DOUBLE(optInPenetration))) +TA_LOOKBACK(CDLGAPSIDESIDEWHITE, TA_OPTIONS()) +TA_LOOKBACK(CDLGRAVESTONEDOJI, TA_OPTIONS()) +TA_LOOKBACK(CDLHAMMER, TA_OPTIONS()) +TA_LOOKBACK(CDLHANGINGMAN, TA_OPTIONS()) +TA_LOOKBACK(CDLHARAMI, TA_OPTIONS()) +TA_LOOKBACK(CDLHARAMICROSS, TA_OPTIONS()) +TA_LOOKBACK(CDLHIGHWAVE, TA_OPTIONS()) +TA_LOOKBACK(CDLHIKKAKE, TA_OPTIONS()) +TA_LOOKBACK(CDLHIKKAKEMOD, TA_OPTIONS()) +TA_LOOKBACK(CDLHOMINGPIGEON, TA_OPTIONS()) +TA_LOOKBACK(CDLIDENTICAL3CROWS, TA_OPTIONS()) +TA_LOOKBACK(CDLINNECK, TA_OPTIONS()) +TA_LOOKBACK(CDLINVERTEDHAMMER, TA_OPTIONS()) +TA_LOOKBACK(CDLKICKING, TA_OPTIONS()) +TA_LOOKBACK(CDLKICKINGBYLENGTH, TA_OPTIONS()) +TA_LOOKBACK(CDLLADDERBOTTOM, TA_OPTIONS()) +TA_LOOKBACK(CDLLONGLEGGEDDOJI, TA_OPTIONS()) +TA_LOOKBACK(CDLLONGLINE, TA_OPTIONS()) +TA_LOOKBACK(CDLMARUBOZU, TA_OPTIONS()) +TA_LOOKBACK(CDLMATCHINGLOW, TA_OPTIONS()) +TA_LOOKBACK(CDLMATHOLD, TA_OPTIONS(OPTIONAL_DOUBLE(optInPenetration))) +TA_LOOKBACK(CDLMORNINGDOJISTAR, TA_OPTIONS(OPTIONAL_DOUBLE(optInPenetration))) +TA_LOOKBACK(CDLMORNINGSTAR, TA_OPTIONS(OPTIONAL_DOUBLE(optInPenetration))) +TA_LOOKBACK(CDLONNECK, TA_OPTIONS()) +TA_LOOKBACK(CDLPIERCING, TA_OPTIONS()) +TA_LOOKBACK(CDLRICKSHAWMAN, TA_OPTIONS()) +TA_LOOKBACK(CDLRISEFALL3METHODS, TA_OPTIONS()) +TA_LOOKBACK(CDLSEPARATINGLINES, TA_OPTIONS()) +TA_LOOKBACK(CDLSHOOTINGSTAR, TA_OPTIONS()) +TA_LOOKBACK(CDLSHORTLINE, TA_OPTIONS()) +TA_LOOKBACK(CDLSPINNINGTOP, TA_OPTIONS()) +TA_LOOKBACK(CDLSTALLEDPATTERN, TA_OPTIONS()) +TA_LOOKBACK(CDLSTICKSANDWICH, TA_OPTIONS()) +TA_LOOKBACK(CDLTAKURI, TA_OPTIONS()) +TA_LOOKBACK(CDLTASUKIGAP, TA_OPTIONS()) +TA_LOOKBACK(CDLTHRUSTING, TA_OPTIONS()) +TA_LOOKBACK(CDLTRISTAR, TA_OPTIONS()) +TA_LOOKBACK(CDLUNIQUE3RIVER, TA_OPTIONS()) +TA_LOOKBACK(CDLUPSIDEGAP2CROWS, TA_OPTIONS()) +TA_LOOKBACK(CDLXSIDEGAP3METHODS, TA_OPTIONS()) +TA_LOOKBACK(CMO, TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod))) +TA_LOOKBACK(CORREL, TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod))) +TA_LOOKBACK(DEMA, TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod))) +TA_LOOKBACK(DX, TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod))) +TA_LOOKBACK(EMA, TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod))) +TA_LOOKBACK(HT_DCPERIOD, TA_OPTIONS()) +TA_LOOKBACK(HT_DCPHASE, TA_OPTIONS()) +TA_LOOKBACK(HT_PHASOR, TA_OPTIONS()) +TA_LOOKBACK(HT_SINE, TA_OPTIONS()) +TA_LOOKBACK(HT_TRENDLINE, TA_OPTIONS()) +TA_LOOKBACK(HT_TRENDMODE, TA_OPTIONS()) +TA_LOOKBACK(IMI, TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod))) +TA_LOOKBACK(KAMA, TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod))) +TA_LOOKBACK(MACD, TA_OPTIONS(OPTIONAL_INTEGER(optInFastPeriod), OPTIONAL_INTEGER(optInSlowPeriod), OPTIONAL_INTEGER(optInSignalPeriod))) +TA_LOOKBACK(MACDEXT, TA_OPTIONS(OPTIONAL_INTEGER(optInFastPeriod), OPTIONAL_MATYPE(optInFastMAType), OPTIONAL_INTEGER(optInSlowPeriod), OPTIONAL_MATYPE(optInSlowMAType), OPTIONAL_INTEGER(optInSignalPeriod), OPTIONAL_MATYPE(optInSignalMAType))) +TA_LOOKBACK(MACDFIX, TA_OPTIONS(OPTIONAL_INTEGER(optInSignalPeriod))) +TA_LOOKBACK(MAMA, TA_OPTIONS(OPTIONAL_DOUBLE(optInFastLimit), OPTIONAL_DOUBLE(optInSlowLimit))) +TA_LOOKBACK(MAVP, TA_OPTIONS(OPTIONAL_INTEGER(optInMinPeriod), OPTIONAL_INTEGER(optInMaxPeriod), OPTIONAL_MATYPE(optInMAType))) +TA_LOOKBACK(MAX, TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod))) +TA_LOOKBACK(MEDPRICE, TA_OPTIONS()) +TA_LOOKBACK(MFI, TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod))) +TA_LOOKBACK(MIDPOINT, TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod))) +TA_LOOKBACK(MIDPRICE, TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod))) +TA_LOOKBACK(MIN, TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod))) +TA_LOOKBACK(MINUS_DI, TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod))) +TA_LOOKBACK(MINUS_DM, TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod))) +TA_LOOKBACK(MOM, TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod))) +TA_LOOKBACK(NATR, TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod))) +TA_LOOKBACK(OBV, TA_OPTIONS()) +TA_LOOKBACK(PLUS_DI, TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod))) +TA_LOOKBACK(PLUS_DM, TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod))) +TA_LOOKBACK(PPO, TA_OPTIONS(OPTIONAL_INTEGER(optInFastPeriod), OPTIONAL_INTEGER(optInSlowPeriod), OPTIONAL_MATYPE(optInMAType))) +TA_LOOKBACK(ROCR, TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod))) +TA_LOOKBACK(RSI, TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod))) +TA_LOOKBACK(SAR, TA_OPTIONS(OPTIONAL_DOUBLE(optInAcceleration), OPTIONAL_DOUBLE(optInMaximum))) +TA_LOOKBACK(SAREXT, TA_OPTIONS(OPTIONAL_DOUBLE(optInStartValue), OPTIONAL_DOUBLE(optInOffsetOnReverse), OPTIONAL_DOUBLE(optInAccelerationInitLong), OPTIONAL_DOUBLE(optInAccelerationLong), OPTIONAL_DOUBLE(optInAccelerationMaxLong), OPTIONAL_DOUBLE(optInAccelerationInitShort), OPTIONAL_DOUBLE(optInAccelerationShort), OPTIONAL_DOUBLE(optInAccelerationMaxShort))) +TA_LOOKBACK(SMA, TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod))) +TA_LOOKBACK(STDDEV, TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod), OPTIONAL_DOUBLE(optInNbDev))) +TA_LOOKBACK(STOCH, TA_OPTIONS(OPTIONAL_INTEGER(optInFastK_Period), OPTIONAL_INTEGER(optInSlowK_Period), OPTIONAL_MATYPE(optInSlowK_MAType), OPTIONAL_INTEGER(optInSlowD_Period), OPTIONAL_MATYPE(optInSlowD_MAType))) +TA_LOOKBACK(STOCHF, TA_OPTIONS(OPTIONAL_INTEGER(optInFastK_Period), OPTIONAL_INTEGER(optInFastD_Period), OPTIONAL_MATYPE(optInFastD_MAType))) +TA_LOOKBACK(STOCHRSI, TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod), OPTIONAL_INTEGER(optInFastK_Period), OPTIONAL_INTEGER(optInFastD_Period), OPTIONAL_MATYPE(optInFastD_MAType))) +TA_LOOKBACK(SUM, TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod))) +TA_LOOKBACK(T3, TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod), OPTIONAL_DOUBLE(optInVFactor))) +TA_LOOKBACK(TEMA, TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod))) +TA_LOOKBACK(TRANGE, TA_OPTIONS()) +TA_LOOKBACK(TRIMA, TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod))) +TA_LOOKBACK(TRIX, TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod))) +TA_LOOKBACK(TYPPRICE, TA_OPTIONS()) +TA_LOOKBACK(ULTOSC, TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod1), OPTIONAL_INTEGER(optInTimePeriod2), OPTIONAL_INTEGER(optInTimePeriod3))) +TA_LOOKBACK(VAR, TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod), OPTIONAL_DOUBLE(optInNbDev))) +TA_LOOKBACK(WCLPRICE, TA_OPTIONS()) +TA_LOOKBACK(WILLR, TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod))) +TA_LOOKBACK(WMA, TA_OPTIONS(OPTIONAL_INTEGER(optInTimePeriod))) +// clang-format on diff --git a/src/api.h b/src/api.h deleted file mode 100644 index a119d9431..000000000 --- a/src/api.h +++ /dev/null @@ -1,146 +0,0 @@ -// Generated from codegen/generate_API.sh -#ifndef _API_H_ -#define _API_H_ - -#include - -// clang-format off -SEXP impl_ta_ACCBANDS(SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInTimePeriod, SEXP na_bridge); -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_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(SEXP inReal, SEXP optInFastPeriod, SEXP optInSlowPeriod, SEXP optInMAType, SEXP na_bridge); -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(SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInTimePeriod, SEXP na_bridge); -SEXP impl_ta_AVGPRICE(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP na_bridge); -SEXP impl_ta_BBANDS(SEXP inReal, SEXP optInTimePeriod, SEXP optInNbDevUp, SEXP optInNbDevDn, SEXP optInMAType, SEXP na_bridge); -SEXP impl_ta_BETA(SEXP inReal0, SEXP inReal1, SEXP optInTimePeriod, SEXP na_bridge); -SEXP impl_ta_BOP(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP na_bridge); -SEXP impl_ta_CCI(SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInTimePeriod, SEXP na_bridge); -SEXP impl_ta_CDL2CROWS(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDL3BLACKCROWS(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDL3INSIDE(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDL3LINESTRIKE(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDL3OUTSIDE(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDL3STARSINSOUTH(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDL3WHITESOLDIERS(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDLABANDONEDBABY(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInPenetration, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDLADVANCEBLOCK(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDLBELTHOLD(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDLBREAKAWAY(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDLCLOSINGMARUBOZU(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDLCONCEALBABYSWALL(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDLCOUNTERATTACK(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDLDARKCLOUDCOVER(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInPenetration, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDLDOJI(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDLDOJISTAR(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDLDRAGONFLYDOJI(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDLENGULFING(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDLEVENINGDOJISTAR(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInPenetration, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDLEVENINGSTAR(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInPenetration, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDLGAPSIDESIDEWHITE(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDLGRAVESTONEDOJI(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDLHAMMER(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDLHANGINGMAN(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDLHARAMICROSS(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDLHARAMI(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDLHIGHWAVE(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); -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(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDLIDENTICAL3CROWS(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDLINNECK(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDLINVERTEDHAMMER(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDLKICKINGBYLENGTH(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDLKICKING(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDLLADDERBOTTOM(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDLLONGLEGGEDDOJI(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDLLONGLINE(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDLMARUBOZU(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDLMATCHINGLOW(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDLMATHOLD(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInPenetration, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDLMORNINGDOJISTAR(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInPenetration, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDLMORNINGSTAR(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInPenetration, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDLONNECK(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDLPIERCING(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDLRICKSHAWMAN(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDLRISEFALL3METHODS(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDLSEPARATINGLINES(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDLSHOOTINGSTAR(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDLSHORTLINE(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDLSPINNINGTOP(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDLSTALLEDPATTERN(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDLSTICKSANDWICH(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDLTAKURI(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDLTASUKIGAP(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDLTHRUSTING(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDLTRISTAR(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDLUNIQUE3RIVER(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDLUPSIDEGAP2CROWS(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CDLXSIDEGAP3METHODS(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); -SEXP impl_ta_CMO(SEXP inReal, SEXP optInTimePeriod, SEXP na_bridge); -SEXP impl_ta_CORREL(SEXP inReal0, SEXP inReal1, SEXP optInTimePeriod, SEXP na_bridge); -SEXP impl_ta_DEMA(SEXP inReal, SEXP optInTimePeriod, SEXP na_bridge); -SEXP impl_ta_DX(SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInTimePeriod, SEXP na_bridge); -SEXP impl_ta_EMA(SEXP inReal, SEXP optInTimePeriod, SEXP na_bridge); -SEXP impl_ta_HT_DCPERIOD(SEXP inReal, SEXP na_bridge); -SEXP impl_ta_HT_DCPHASE(SEXP inReal, SEXP na_bridge); -SEXP impl_ta_HT_PHASOR(SEXP inReal, SEXP na_bridge); -SEXP impl_ta_HT_SINE(SEXP inReal, SEXP na_bridge); -SEXP impl_ta_HT_TRENDLINE(SEXP inReal, SEXP na_bridge); -SEXP impl_ta_HT_TRENDMODE(SEXP inReal, SEXP na_bridge); -SEXP impl_ta_IMI(SEXP inOpen, SEXP inClose, SEXP optInTimePeriod, SEXP na_bridge); -SEXP impl_ta_KAMA(SEXP inReal, SEXP optInTimePeriod, SEXP na_bridge); -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(SEXP inReal, SEXP optInSignalPeriod, SEXP na_bridge); -SEXP impl_ta_MACD(SEXP inReal, SEXP optInFastPeriod, SEXP optInSlowPeriod, SEXP optInSignalPeriod, SEXP na_bridge); -SEXP impl_ta_MAMA(SEXP inReal, SEXP optInFastLimit, SEXP optInSlowLimit, SEXP na_bridge); -SEXP impl_ta_MAX(SEXP inReal, SEXP optInTimePeriod, SEXP na_bridge); -SEXP impl_ta_MEDPRICE(SEXP inHigh, SEXP inLow, SEXP na_bridge); -SEXP impl_ta_MFI(SEXP inHigh, SEXP inLow, SEXP inClose, SEXP inVolume, SEXP optInTimePeriod, SEXP na_bridge); -SEXP impl_ta_MIDPRICE(SEXP inHigh, SEXP inLow, SEXP optInTimePeriod, SEXP na_bridge); -SEXP impl_ta_MIN(SEXP inReal, SEXP optInTimePeriod, SEXP na_bridge); -SEXP impl_ta_MINUS_DI(SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInTimePeriod, SEXP na_bridge); -SEXP impl_ta_MINUS_DM(SEXP inHigh, SEXP inLow, SEXP optInTimePeriod, SEXP na_bridge); -SEXP impl_ta_MOM(SEXP inReal, SEXP optInTimePeriod, SEXP na_bridge); -SEXP impl_ta_NATR(SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInTimePeriod, SEXP na_bridge); -SEXP impl_ta_OBV(SEXP inReal, SEXP inVolume, SEXP na_bridge); -SEXP impl_ta_PLUS_DI(SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInTimePeriod, SEXP na_bridge); -SEXP impl_ta_PLUS_DM(SEXP inHigh, SEXP inLow, SEXP optInTimePeriod, SEXP na_bridge); -SEXP impl_ta_PPO(SEXP inReal, SEXP optInFastPeriod, SEXP optInSlowPeriod, SEXP optInMAType, SEXP na_bridge); -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(SEXP inReal, SEXP optInTimePeriod, SEXP na_bridge); -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(SEXP inHigh, SEXP inLow, SEXP optInAcceleration, SEXP optInMaximum, SEXP na_bridge); -SEXP impl_ta_SMA(SEXP inReal, SEXP optInTimePeriod, SEXP na_bridge); -SEXP impl_ta_STDDEV(SEXP inReal, SEXP optInTimePeriod, SEXP optInNbDev, SEXP na_bridge); -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_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(SEXP inReal, SEXP optInTimePeriod, SEXP na_bridge); -SEXP impl_ta_T3(SEXP inReal, SEXP optInTimePeriod, SEXP optInVFactor, SEXP na_bridge); -SEXP impl_ta_TEMA(SEXP inReal, SEXP optInTimePeriod, SEXP na_bridge); -SEXP impl_ta_TRANGE(SEXP inHigh, SEXP inLow, SEXP inClose, SEXP na_bridge); -SEXP impl_ta_TRIMA(SEXP inReal, SEXP optInTimePeriod, SEXP na_bridge); -SEXP impl_ta_TRIX(SEXP inReal, SEXP optInTimePeriod, SEXP na_bridge); -SEXP impl_ta_TYPPRICE(SEXP inHigh, SEXP inLow, SEXP inClose, SEXP na_bridge); -SEXP impl_ta_ULTOSC(SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInTimePeriod1, SEXP optInTimePeriod2, SEXP optInTimePeriod3, SEXP na_bridge); -SEXP impl_ta_VAR(SEXP inReal, SEXP optInTimePeriod, SEXP optInNbDev, SEXP na_bridge); -SEXP impl_ta_VOLUME(SEXP inReal, SEXP maSpec, SEXP na_rm); -SEXP impl_ta_WCLPRICE(SEXP inHigh, SEXP inLow, SEXP inClose, SEXP na_bridge); -SEXP impl_ta_WILLR(SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInTimePeriod, SEXP na_bridge); -SEXP impl_ta_WMA(SEXP inReal, SEXP optInTimePeriod, SEXP na_bridge); -SEXP initialize_ta_lib(void); -SEXP map_dfr_double(SEXP x); -SEXP map_dfr_integer(SEXP x); -SEXP reset_candle_setting(void); -SEXP rownames_data_frame(SEXP x, SEXP rownames); -SEXP rownames_matrix(SEXP x, SEXP rownames, SEXP colnames); -SEXP set_candle_setting(SEXP s_settingType, SEXP s_rangeType, SEXP s_avgPeriod, SEXP s_factor); -SEXP shutdown_ta_lib(void); -// clang-format on - -#endif //_API_H diff --git a/src/attributes.c b/src/attributes.c index 61757ad08..6ccf364c7 100644 --- a/src/attributes.c +++ b/src/attributes.c @@ -2,40 +2,67 @@ // // This 'C'-program sets the attributes of the // output container. -// - Its currently hardcoded for lookback only -// but it will be expanded if there is any demand -// for it. +// - Attributes are dispatched by a attribute tag so new +// attributes can be added without changing the call sites: +// add an enum entry and a case in attribute_symbol() below. // #include "attributes.h" +#include "Rinternals.h" -// initialize the lookback value -static SEXP lookback_value = NULL; - -// set lookback value -static inline SEXP ta_lookback(void) { - - if (lookback_value == NULL) { - lookback_value = Rf_install("lookback"); +// resolve (and cache) the R symbol for an attribute +// clang-format off +static SEXP attribute_symbol(attribute attr) { + switch (attr) { + case LOOKBACK: { + static SEXP lookback = NULL; + if (lookback == NULL) { + lookback = Rf_install("lookback"); + } + return lookback; + } } - - return lookback_value; + + return R_NilValue; } +// clang-format on + +// Normalize lookback values +// +// Description: +// TA-Lib returns 0 for indicators that can +// be calculated as-is, which from an R perspective +// makes no sense as it is not possible to calculate +// indicators on "nothing." The normalization here translates +// to minimum number of observations. +int normalize_lookback(int lookback) { return lookback <= 0 ? 1 : lookback; } -// workhorse function to -// set the attribute // clang-format off void set_attribute( - SEXP output_object, - int lookback, - int *protection_count) { + SEXP x, // object + attribute attr, // attribute + SEXP attr_value, // attribute value + int *protection_count +) +// clang-format on +{ + + // clang-format off + switch (attr) { + case LOOKBACK: { + attr_value = Rf_ScalarInteger( + normalize_lookback( + Rf_asInteger(attr_value) + ) + ); + } + } // clang-format on - SEXP symbolic_value = ta_lookback(); + SEXP protected_value = PROTECT(attr_value); - SEXP value = PROTECT(Rf_ScalarInteger(lookback)); if (protection_count) { (*protection_count)++; } - Rf_setAttrib(output_object, symbolic_value, value); + Rf_setAttrib(x, attribute_symbol(attr), protected_value); } diff --git a/src/attributes.h b/src/attributes.h index c4bbf77f4..ee74b0003 100644 --- a/src/attributes.h +++ b/src/attributes.h @@ -7,6 +7,18 @@ // #include -void set_attribute(SEXP obj, int lookback, int *protection_count); +// Extensible attribute identifiers +// +// Description +// Add new attribute(s) here and process it in attribute_symbol() +// to implement it. +typedef enum { + LOOKBACK, +} attribute; + +void set_attribute( + SEXP obj, attribute attr, SEXP attr_value, int *protection_count); + +int normalize_lookback(int lookback); #endif /* ATTRIBUTES_H */ diff --git a/src/container.h b/src/container.h deleted file mode 100644 index 0cc2e71e0..000000000 --- a/src/container.h +++ /dev/null @@ -1,132 +0,0 @@ -#ifndef _CONTAINER_H -#define _CONTAINER_H -// conainter.h -// -// This header file abstracts a big part of the -// of common function calls: -// -// output_container: -// A generic function for constructing a double or integer matrix -// which is determined by out_ptr. -// -// The function returns an integer which serves as flag for the remaining -// function which if 1 passes the call to TA-Lib, or exits the function -// otherwise. -// -// See ta_AD.c for an example on how to use it -#include "lib.h" -#include "names.h" -#include -#include -#include - -// double -// clang-format off -static inline int double_container( - int n, - int lookback, - int ncol, - SEXP *out_sexp, - double **out_ptr, - int *protect_count) { - // clang-format on - - // construct matrix and iterate - // protect counter - // clang-format off - SEXP matrix = PROTECT( - allocMatrix(REALSXP, n, ncol) - ); - - (*protect_count)++; - // clang-format on - - // construct pointers to - // matrix - *out_sexp = matrix; - *out_ptr = REAL(matrix); - - // if N is less than lookback - // the function returns with the - // same length - if (n < lookback) { - - Rf_warning( - "Input length (%d) is smaller than required lookback (%d).", - n, - lookback); - - const int total = n * ncol; - for (int i = 0; i < total; ++i) { - (*out_ptr)[i] = NA_REAL; - } - - return 0; - } - - return 1; -} - -// integer -// clang-format off -static inline int integer_container( - int n, - int lookback, - int ncol, - SEXP *out_sexp, - int **out_ptr, - int *protect_count) { - // clang-format on - - // construct matrix and iterate - // protect counter - // clang-format off - SEXP matrix = PROTECT( - allocMatrix(INTSXP, n, ncol) - ); - - (*protect_count)++; - // clang-format on - - // construct pointers to - // matrix - *out_sexp = matrix; - *out_ptr = INTEGER(matrix); - - // if N is less than lookback - // the function returns with the - // same length - if (n < lookback) { - - Rf_warning( - "Input length (%d) is smaller than required lookback (%d).", - n, - lookback); - - const int total = n * ncol; - for (int i = 0; i < total; ++i) - (*out_ptr)[i] = NA_INTEGER; - return 0; - } - - return 1; -} - -// check output -// -// -static inline void check_output(TA_RetCode x, int protect_count) { - - if (x != TA_SUCCESS) { - Rf_unprotect(protect_count); - Rf_error("Failed with code %d", x); - } -} - -// clang-format off -#define output_container(n, lookback, ncol, out_sexp, out_ptr, protect_count) \ - _Generic(*(out_ptr), double *: double_container, int *: integer_container) \ - ((n), (lookback), (ncol), (out_sexp), (out_ptr), (protect_count)) -// clang-format on - -#endif /* _CONTAINER_H */ diff --git a/src/dataframe.c b/src/data-frame.c similarity index 50% rename from src/dataframe.c rename to src/data-frame.c index add02c167..e44492cf4 100644 --- a/src/dataframe.c +++ b/src/data-frame.c @@ -1,10 +1,37 @@ -// dataframe.c +// data-frame.c +// +// Description: +// This C-routine converts a to a +// on the R-side. It is implemented specifically for {talib} +// and its portability across other packages are, at best, zero to none. +// The only reason it has been written is to reduce the time taken to convert +// a to (see benchmarks below) +// +// Benchmark: +// +// ``` r +// x <- as.matrix(mtcars) +// +// bench::mark( +// `{talib}` = talib:::map_dfr(x), +// `{base}` = as.data.frame(x) +// ) +// +// #> # A tibble: 2 × 6 +// #> expression min median `itr/sec` mem_alloc `gc/sec` +// #> +// #> 1 {talib} 1.72µs 2.56µs 372826. 1.88MB 0 +// #> 2 {base} 16.04µs 19.4µs 49028. 13.36KB 29.4 +// ``` +// +// Created on 2026-07-13 with [reprex +// v2.1.1](https://reprex.tidyverse.org) #include #include #include // clang-format off -static SEXP map_dfr_impl( +static SEXP impl_map_dfr( SEXP x, SEXPTYPE type ) @@ -14,7 +41,7 @@ static SEXP map_dfr_impl( int protection_counter = 0; // input dimensions - SEXP dim = getAttrib(x, R_DimSymbol); + SEXP dim = Rf_getAttrib(x, R_DimSymbol); const int nrows = INTEGER(dim)[0]; const int ncols = INTEGER(dim)[1]; @@ -23,26 +50,29 @@ static SEXP map_dfr_impl( // clang-format off SEXP data_frame = PROTECT( - allocVector(VECSXP, ncols) + Rf_allocVector(VECSXP, ncols) ); // clang-format on ++protection_counter; // construct columns + // + // Each column is stored straight into data_frame with SET_VECTOR_ELT and + // then filled. allocVector() returns the vector before SET_VECTOR_ELT runs, + // and SET_VECTOR_ELT itself does not allocate, so the fresh column is rooted + // in the already-protected data_frame with no intervening GC - no per-column + // PROTECT is needed, and the protection stack stays at constant depth. if (type == REALSXP) { const double *restrict x_ptr = REAL(x); const size_t col_bytes = nrow_len * sizeof(double); for (int j = 0; j < ncols; ++j) { - SEXP column = PROTECT(allocVector(REALSXP, nrows)); - ++protection_counter; + SEXP column = Rf_allocVector(REALSXP, nrows); + SET_VECTOR_ELT(data_frame, j, column); double *restrict column_ptr = REAL(column); - const double *restrict src = x_ptr + (size_t)j * nrows; memcpy(column_ptr, src, col_bytes); - - SET_VECTOR_ELT(data_frame, j, column); } } else { @@ -50,19 +80,17 @@ static SEXP map_dfr_impl( const size_t col_bytes = nrow_len * sizeof(int); for (int j = 0; j < ncols; ++j) { - SEXP column = PROTECT(allocVector(INTSXP, nrows)); - ++protection_counter; + SEXP column = Rf_allocVector(INTSXP, nrows); + SET_VECTOR_ELT(data_frame, j, column); int *restrict column_ptr = INTEGER(column); const int *restrict src = x_ptr + (size_t)j * nrows; memcpy(column_ptr, src, col_bytes); - - SET_VECTOR_ELT(data_frame, j, column); } } // dimension names - SEXP dimnames = getAttrib(x, R_DimNamesSymbol); + SEXP dimnames = Rf_getAttrib(x, R_DimNamesSymbol); SEXP row_names = (dimnames == R_NilValue) ? R_NilValue : VECTOR_ELT(dimnames, 0); SEXP col_names = @@ -72,37 +100,42 @@ static SEXP map_dfr_impl( // c(NA_integer_, -nrows) - same representation base R uses for // automatic row names - when the matrix carries no row dimnames. if (row_names == R_NilValue) { - row_names = PROTECT(allocVector(INTSXP, 2)); + row_names = PROTECT(Rf_allocVector(INTSXP, 2)); ++protection_counter; INTEGER(row_names)[0] = NA_INTEGER; INTEGER(row_names)[1] = -nrows; } - setAttrib(data_frame, R_RowNamesSymbol, row_names); - setAttrib(data_frame, R_NamesSymbol, col_names); + Rf_setAttrib(data_frame, R_RowNamesSymbol, row_names); + Rf_setAttrib(data_frame, R_NamesSymbol, col_names); // clang-format off SEXP class = PROTECT( - mkString("data.frame") + Rf_mkString("data.frame") ); // clang-format on ++protection_counter; - setAttrib(data_frame, R_ClassSymbol, class); + Rf_setAttrib(data_frame, R_ClassSymbol, class); UNPROTECT(protection_counter); return data_frame; } +// Map to +// +// Description: +// Exported functions that converts to . +// Integers and doubles are handled on the R-side via utils.R // clang-format off SEXP map_dfr_double(SEXP x) // clang-format on { - return map_dfr_impl(x, REALSXP); + return impl_map_dfr(x, REALSXP); } // clang-format off SEXP map_dfr_integer(SEXP x) // clang-format on { - return map_dfr_impl(x, INTSXP); -} + return impl_map_dfr(x, INTSXP); +} \ No newline at end of file diff --git a/src/init.c b/src/init.c index a245ced9f..1d5ad3068 100644 --- a/src/init.c +++ b/src/init.c @@ -1,156 +1,116 @@ -// Generated from codegen/generate_FFI.sh -#include +// init.c +// +// Description: +// This is where TA-Lib.h is being ported to +// R, and is the workhorse of the R package. +// +// Author: Serkan Korkmaz +#include "ta_libc.h" +#include "utils.h" +#include "wrapper.h" #include #include -#include - -#include "api.h" +#include +// TA_DECL / TA_LB_DECL emit the forward declarations (prototypes) for the +// mined TA-Lib entry points. They reuse the argument-shape helpers from +// wrapper.h, so each prototype tracks its TA_WRAPPER-generated definition. // clang-format off -#define CALLDEF(name, n) {#name, (DL_FUNC) &name, n} +#define TA_DECL(NAME, RT, INS_, OPTS_, OUTS_, TA_OUTPUT_NAME_, KIND) \ + extern SEXP impl_ta_##NAME( \ + TA_APPLY(TA_IN_ARG, INS_) \ + TA_APPLY(TA_OPT_ARG, OPTS_) \ + SEXP s_na_bridge \ + TA_CAT(TA_NORM_ARG_, KIND) \ + ); // clang-format on +#define TA_LB_DECL(NAME, OPTS_) \ + extern SEXP impl_ta_##NAME##_lookback(TA_LB_PARAMS(OPTS_)); + +// forward declaration of all +// mined TA-Lib functions (indicator + lookback) +#define TA_INDICATOR(...) TA_DECL(__VA_ARGS__) +#define TA_LOOKBACK(...) TA_LB_DECL(__VA_ARGS__) +#include "TA-Lib.h" +#undef TA_INDICATOR +#undef TA_LOOKBACK + +// construct TA-Lib wrappers (indicator + lookback) +#define TA_INDICATOR(...) TA_WRAPPER(__VA_ARGS__) +#define TA_LOOKBACK(...) TA_LB_WRAPPER(__VA_ARGS__) +#include "TA-Lib.h" +#undef TA_INDICATOR +#undef TA_LOOKBACK + +// trading-volume wrappers (volume.c) +extern SEXP impl_ta_VOLUME(SEXP, SEXP, SEXP); +extern SEXP impl_ta_VOLUME_lookback(SEXP, SEXP); + +// global-setter wrappers (TA-Lib.c) +extern SEXP ta_set_unstable_period(SEXP, SEXP); +extern SEXP ta_set_compatibility(SEXP); +extern SEXP set_candle_setting(SEXP, SEXP, SEXP, SEXP); +extern SEXP reset_candle_setting(SEXP); +extern SEXP initialize_ta_lib(void); +extern SEXP map_dfr_double(SEXP); +extern SEXP map_dfr_integer(SEXP); +extern SEXP shutdown_ta_lib(void); + +// TA_REG / TA_LB_REG emit the R_CallMethodDef rows. Arity is derived from the +// same TA_COUNT_ARGUMENTS / TA_NORM_ARITY helpers the wrapper signature uses: +// indicator = #inputs + #opts + 1 (na_bridge) + candlestick normalize arg +// lookback = #opts +// The registration STRING (not the C symbol) is what R names the routine: +// with useDynLib(.fixes = "C_"), R exposes C_ + this string, matching the +// generated .Call(C_impl_ta_, ...). +#define TA_REG(NAME, RT, INS_, OPTS_, OUTS_, TA_OUTPUT_NAME_, KIND) \ + {"impl_ta_" #NAME, \ + (DL_FUNC) & impl_ta_##NAME, \ + (TA_COUNT_ARGUMENTS INS_) + (TA_COUNT_ARGUMENTS OPTS_) + 1 + \ + TA_CAT(TA_NORM_ARITY_, KIND)}, +#define TA_LB_REG(NAME, OPTS_) \ + {"impl_ta_" #NAME "_lookback", \ + (DL_FUNC) & impl_ta_##NAME##_lookback, \ + TA_COUNT_ARGUMENTS OPTS_}, static const R_CallMethodDef CallEntries[] = { - CALLDEF(impl_ta_ACCBANDS, 5), - CALLDEF(impl_ta_ADOSC, 7), - CALLDEF(impl_ta_AD, 5), - CALLDEF(impl_ta_ADXR, 5), - CALLDEF(impl_ta_ADX, 5), - CALLDEF(impl_ta_APO, 5), - CALLDEF(impl_ta_AROONOSC, 4), - CALLDEF(impl_ta_AROON, 4), - CALLDEF(impl_ta_ATR, 5), - CALLDEF(impl_ta_AVGPRICE, 5), - CALLDEF(impl_ta_BBANDS, 6), - CALLDEF(impl_ta_BETA, 4), - CALLDEF(impl_ta_BOP, 5), - CALLDEF(impl_ta_CCI, 5), - CALLDEF(impl_ta_CDL2CROWS, 6), - CALLDEF(impl_ta_CDL3BLACKCROWS, 6), - CALLDEF(impl_ta_CDL3INSIDE, 6), - CALLDEF(impl_ta_CDL3LINESTRIKE, 6), - CALLDEF(impl_ta_CDL3OUTSIDE, 6), - CALLDEF(impl_ta_CDL3STARSINSOUTH, 6), - CALLDEF(impl_ta_CDL3WHITESOLDIERS, 6), - CALLDEF(impl_ta_CDLABANDONEDBABY, 7), - CALLDEF(impl_ta_CDLADVANCEBLOCK, 6), - CALLDEF(impl_ta_CDLBELTHOLD, 6), - CALLDEF(impl_ta_CDLBREAKAWAY, 6), - CALLDEF(impl_ta_CDLCLOSINGMARUBOZU, 6), - CALLDEF(impl_ta_CDLCONCEALBABYSWALL, 6), - CALLDEF(impl_ta_CDLCOUNTERATTACK, 6), - CALLDEF(impl_ta_CDLDARKCLOUDCOVER, 7), - CALLDEF(impl_ta_CDLDOJI, 6), - CALLDEF(impl_ta_CDLDOJISTAR, 6), - CALLDEF(impl_ta_CDLDRAGONFLYDOJI, 6), - CALLDEF(impl_ta_CDLENGULFING, 6), - CALLDEF(impl_ta_CDLEVENINGDOJISTAR, 7), - CALLDEF(impl_ta_CDLEVENINGSTAR, 7), - CALLDEF(impl_ta_CDLGAPSIDESIDEWHITE, 6), - CALLDEF(impl_ta_CDLGRAVESTONEDOJI, 6), - CALLDEF(impl_ta_CDLHAMMER, 6), - CALLDEF(impl_ta_CDLHANGINGMAN, 6), - CALLDEF(impl_ta_CDLHARAMICROSS, 6), - CALLDEF(impl_ta_CDLHARAMI, 6), - CALLDEF(impl_ta_CDLHIGHWAVE, 6), - CALLDEF(impl_ta_CDLHIKKAKEMOD, 6), - CALLDEF(impl_ta_CDLHIKKAKE, 6), - CALLDEF(impl_ta_CDLHOMINGPIGEON, 6), - CALLDEF(impl_ta_CDLIDENTICAL3CROWS, 6), - CALLDEF(impl_ta_CDLINNECK, 6), - CALLDEF(impl_ta_CDLINVERTEDHAMMER, 6), - CALLDEF(impl_ta_CDLKICKINGBYLENGTH, 6), - CALLDEF(impl_ta_CDLKICKING, 6), - CALLDEF(impl_ta_CDLLADDERBOTTOM, 6), - CALLDEF(impl_ta_CDLLONGLEGGEDDOJI, 6), - CALLDEF(impl_ta_CDLLONGLINE, 6), - CALLDEF(impl_ta_CDLMARUBOZU, 6), - CALLDEF(impl_ta_CDLMATCHINGLOW, 6), - CALLDEF(impl_ta_CDLMATHOLD, 7), - CALLDEF(impl_ta_CDLMORNINGDOJISTAR, 7), - CALLDEF(impl_ta_CDLMORNINGSTAR, 7), - CALLDEF(impl_ta_CDLONNECK, 6), - CALLDEF(impl_ta_CDLPIERCING, 6), - CALLDEF(impl_ta_CDLRICKSHAWMAN, 6), - CALLDEF(impl_ta_CDLRISEFALL3METHODS, 6), - CALLDEF(impl_ta_CDLSEPARATINGLINES, 6), - CALLDEF(impl_ta_CDLSHOOTINGSTAR, 6), - CALLDEF(impl_ta_CDLSHORTLINE, 6), - CALLDEF(impl_ta_CDLSPINNINGTOP, 6), - CALLDEF(impl_ta_CDLSTALLEDPATTERN, 6), - CALLDEF(impl_ta_CDLSTICKSANDWICH, 6), - CALLDEF(impl_ta_CDLTAKURI, 6), - CALLDEF(impl_ta_CDLTASUKIGAP, 6), - CALLDEF(impl_ta_CDLTHRUSTING, 6), - CALLDEF(impl_ta_CDLTRISTAR, 6), - CALLDEF(impl_ta_CDLUNIQUE3RIVER, 6), - CALLDEF(impl_ta_CDLUPSIDEGAP2CROWS, 6), - CALLDEF(impl_ta_CDLXSIDEGAP3METHODS, 6), - CALLDEF(impl_ta_CMO, 3), - CALLDEF(impl_ta_CORREL, 4), - CALLDEF(impl_ta_DEMA, 3), - CALLDEF(impl_ta_DX, 5), - CALLDEF(impl_ta_EMA, 3), - CALLDEF(impl_ta_HT_DCPERIOD, 2), - CALLDEF(impl_ta_HT_DCPHASE, 2), - CALLDEF(impl_ta_HT_PHASOR, 2), - CALLDEF(impl_ta_HT_SINE, 2), - CALLDEF(impl_ta_HT_TRENDLINE, 2), - CALLDEF(impl_ta_HT_TRENDMODE, 2), - CALLDEF(impl_ta_IMI, 4), - CALLDEF(impl_ta_KAMA, 3), - CALLDEF(impl_ta_MACDEXT, 8), - CALLDEF(impl_ta_MACDFIX, 3), - CALLDEF(impl_ta_MACD, 5), - CALLDEF(impl_ta_MAMA, 4), - CALLDEF(impl_ta_MAX, 3), - CALLDEF(impl_ta_MEDPRICE, 3), - CALLDEF(impl_ta_MFI, 6), - CALLDEF(impl_ta_MIDPRICE, 4), - CALLDEF(impl_ta_MIN, 3), - CALLDEF(impl_ta_MINUS_DI, 5), - CALLDEF(impl_ta_MINUS_DM, 4), - CALLDEF(impl_ta_MOM, 3), - CALLDEF(impl_ta_NATR, 5), - CALLDEF(impl_ta_OBV, 3), - CALLDEF(impl_ta_PLUS_DI, 5), - CALLDEF(impl_ta_PLUS_DM, 4), - CALLDEF(impl_ta_PPO, 5), - CALLDEF(impl_ta_ROCR, 3), - CALLDEF(impl_ta_ROC, 3), - CALLDEF(impl_ta_RSI, 3), - CALLDEF(impl_ta_SAREXT, 11), - CALLDEF(impl_ta_SAR, 5), - CALLDEF(impl_ta_SMA, 3), - CALLDEF(impl_ta_STDDEV, 4), - CALLDEF(impl_ta_STOCHF, 7), - CALLDEF(impl_ta_STOCHRSI, 6), - CALLDEF(impl_ta_STOCH, 9), - CALLDEF(impl_ta_SUM, 3), - CALLDEF(impl_ta_T3, 4), - CALLDEF(impl_ta_TEMA, 3), - CALLDEF(impl_ta_TRANGE, 4), - CALLDEF(impl_ta_TRIMA, 3), - CALLDEF(impl_ta_TRIX, 3), - CALLDEF(impl_ta_TYPPRICE, 4), - CALLDEF(impl_ta_ULTOSC, 7), - CALLDEF(impl_ta_VAR, 4), - CALLDEF(impl_ta_VOLUME, 3), - CALLDEF(impl_ta_WCLPRICE, 4), - CALLDEF(impl_ta_WILLR, 5), - CALLDEF(impl_ta_WMA, 3), - CALLDEF(initialize_ta_lib, 0), - CALLDEF(map_dfr_double, 1), - CALLDEF(map_dfr_integer, 1), - CALLDEF(reset_candle_setting, 0), - CALLDEF(rownames_data_frame, 2), - CALLDEF(rownames_matrix, 3), - CALLDEF(set_candle_setting, 4), - CALLDEF(shutdown_ta_lib, 0), +#define TA_INDICATOR(...) TA_REG(__VA_ARGS__) +#define TA_LOOKBACK(...) TA_LB_REG(__VA_ARGS__) +#include "TA-Lib.h" +#undef TA_INDICATOR +#undef TA_LOOKBACK + {"impl_ta_VOLUME", (DL_FUNC)&impl_ta_VOLUME, 3}, + {"impl_ta_VOLUME_lookback", (DL_FUNC)&impl_ta_VOLUME_lookback, 2}, + {"ta_set_unstable_period", (DL_FUNC)&ta_set_unstable_period, 2}, + {"ta_set_compatibility", (DL_FUNC)&ta_set_compatibility, 1}, + {"set_candle_setting", (DL_FUNC)&set_candle_setting, 4}, + {"reset_candle_setting", (DL_FUNC)&reset_candle_setting, 1}, + {"rownames_data_frame", (DL_FUNC)&rownames_data_frame, 2}, + {"rownames_matrix", (DL_FUNC)&rownames_matrix, 3}, + {"map_dfr_double", (DL_FUNC)&map_dfr_double, 1}, + {"map_dfr_integer", (DL_FUNC)&map_dfr_integer, 1}, + {"initialize_ta_lib", (DL_FUNC)&initialize_ta_lib, 0}, + {"shutdown_ta_lib", (DL_FUNC)&shutdown_ta_lib, 0}, {NULL, NULL, 0}}; +// Initialize/Unload {talib} +// +// This section corresponds to zzz.R regarding load()/library() +// and unload() and it will initialize/shutdown TA-Lib when needed +// +// void R_init_talib(DllInfo *dll) { + + if (TA_Initialize() != TA_SUCCESS) { + Rf_error("TA_Initialize() failed"); + } + R_registerRoutines(dll, NULL, CallEntries, NULL, NULL); R_useDynamicSymbols(dll, FALSE); R_forceSymbols(dll, TRUE); } + +void R_unload_talib(DllInfo *dll) { + (void)dll; + TA_Shutdown(); +} diff --git a/src/lib.h b/src/lib.h deleted file mode 100644 index b1b7a29de..000000000 --- a/src/lib.h +++ /dev/null @@ -1,29 +0,0 @@ -// lib.h -// -// Description -// Common high-level TA-lib agnostic functionality -// and other implementations -#ifndef _LIB_H_ -#define _LIB_H_ - -#define R_RANDOM_H -// R Headers -#include -#include -#include - -#undef R_RANDOM_H - -// C Headers -#include "shift.h" -#include - -// Redifne integers to avoid -// R definition clashes -// clang-format off -#define Int32 TA_Lib_Int32 - #include -#undef Int32 -// clang-format on - -#endif // _LIB_H_ \ No newline at end of file diff --git a/src/na.h b/src/na.h deleted file mode 100644 index 23541b250..000000000 --- a/src/na.h +++ /dev/null @@ -1,187 +0,0 @@ -// na.h -// -// C-level NA handling for the na.ignore parameter. -// -// Provides: -// build_na_mask - scan input arrays, build boolean mask, return clean count -// compact_array - copy non-masked elements into a compact buffer -// reexpand_double_matrix - re-expand compact double output to full size -// reexpand_int_matrix - re-expand compact int output to full size -// reexpand_matrix - generic dispatch via _Generic -// -#ifndef _NA_H -#define _NA_H - -#include -#include -#include - -// Build NA mask from multiple double input arrays. -// mask[i] = 1 if any array has NA/NaN at position i. -// Returns count of non-NA rows. -// clang-format off -static inline int build_na_mask( - int *mask, - int n, - int n_arrays, - const double *const *arrays -) { - // clang-format on - int clean = 0; - for (int i = 0; i < n; i++) { - mask[i] = 0; - for (int j = 0; j < n_arrays; j++) { - if (ISNAN(arrays[j][i])) { - mask[i] = 1; - break; - } - } - if (!mask[i]) - clean++; - } - return clean; -} - -// Copy non-masked elements from src to dest. -// clang-format off -static inline void compact_array( - double *restrict dest, - const double *restrict src, - const int *mask, - int n -) { - // clang-format on - int j = 0; - for (int i = 0; i < n; i++) { - if (!mask[i]) - dest[j++] = src[i]; - } -} - -// Compact multiple input arrays in-place. -// For each pointer in ptrs[], allocates a clean buffer via R_alloc, -// copies non-masked elements into it, and replaces the pointer. -// clang-format off -static inline void compact_arrays( - const double **ptrs, - int n_arrays, - const int *mask, - int n_original, - int n_clean -) { - // clang-format on - for (int j = 0; j < n_arrays; j++) { - double *buf = (double *)R_alloc(n_clean, sizeof(double)); - compact_array(buf, ptrs[j], mask, n_original); - ptrs[j] = buf; - } -} - -// Re-expand a compact double matrix to full size, -// inserting NA_REAL at masked positions. -// Returns new PROTECTed SEXP; increments protection_count. -// clang-format off -static inline SEXP reexpand_double_matrix( - SEXP compact, - const int *mask, - int n_full, - int *protection_count -) { - // clang-format on - const int ncol = Rf_ncols(compact); - const int n_compact = Rf_nrows(compact); - - SEXP full = PROTECT(allocMatrix(REALSXP, n_full, ncol)); - (*protection_count)++; - - const double *src = REAL(compact); - double *dest = REAL(full); - - for (int col = 0; col < ncol; col++) { - const double *s = src + col * n_compact; - double *d = dest + col * n_full; - int j = 0; - for (int i = 0; i < n_full; i++) { - d[i] = mask[i] ? NA_REAL : s[j++]; - } - } - - // copy dimnames (column names) - SEXP dn = Rf_getAttrib(compact, R_DimNamesSymbol); - if (dn != R_NilValue) { - SEXP new_dn = PROTECT(Rf_allocVector(VECSXP, 2)); - (*protection_count)++; - SET_VECTOR_ELT(new_dn, 0, R_NilValue); - SET_VECTOR_ELT(new_dn, 1, VECTOR_ELT(dn, 1)); - Rf_dimnamesgets(full, new_dn); - } - - // copy lookback attribute - SEXP lb = Rf_getAttrib(compact, Rf_install("lookback")); - if (lb != R_NilValue) { - Rf_setAttrib(full, Rf_install("lookback"), lb); - } - - return full; -} - -// Re-expand a compact integer matrix to full size, -// inserting NA_INTEGER at masked positions. -// Returns new PROTECTed SEXP; increments protection_count. -// clang-format off -static inline SEXP reexpand_int_matrix( - SEXP compact, - const int *mask, - int n_full, - int *protection_count -) { - // clang-format on - const int ncol = Rf_ncols(compact); - const int n_compact = Rf_nrows(compact); - - SEXP full = PROTECT(allocMatrix(INTSXP, n_full, ncol)); - (*protection_count)++; - - const int *src = INTEGER(compact); - int *dest = INTEGER(full); - - for (int col = 0; col < ncol; col++) { - const int *s = src + col * n_compact; - int *d = dest + col * n_full; - int j = 0; - for (int i = 0; i < n_full; i++) { - d[i] = mask[i] ? NA_INTEGER : s[j++]; - } - } - - // copy dimnames (column names) - SEXP dn = Rf_getAttrib(compact, R_DimNamesSymbol); - if (dn != R_NilValue) { - SEXP new_dn = PROTECT(Rf_allocVector(VECSXP, 2)); - (*protection_count)++; - SET_VECTOR_ELT(new_dn, 0, R_NilValue); - SET_VECTOR_ELT(new_dn, 1, VECTOR_ELT(dn, 1)); - Rf_dimnamesgets(full, new_dn); - } - - // copy lookback attribute - SEXP lb = Rf_getAttrib(compact, Rf_install("lookback")); - if (lb != R_NilValue) { - Rf_setAttrib(full, Rf_install("lookback"), lb); - } - - return full; -} - -// Generic re-expand dispatch based on output pointer type. -// Usage: output = reexpand_matrix(output, output_ptr, na_mask, n_original, -// &protection_count); -// clang-format off -#define reexpand_matrix(compact, out_ptr, mask, n_full, pcount) \ - _Generic(*(out_ptr), \ - double: reexpand_double_matrix, \ - int: reexpand_int_matrix \ - )((compact), (mask), (n_full), (pcount)) -// clang-format on - -#endif /* _NA_H */ diff --git a/src/names.c b/src/names.c index 018991319..afea23cdb 100644 --- a/src/names.c +++ b/src/names.c @@ -1,3 +1,46 @@ +#include "names.h" + +// Column Names +// +// Description: +// Set the column names of the -object +// clang-format off +void set_colnames( + SEXP x, // assumed to be a matrix + const char *const *names, + int k // columns +) +// clang-format on +{ + // protection counter + int protection_counter = 0; + + // clang-format off + SEXP dimensions = PROTECT( + Rf_allocVector(VECSXP, 2) + ); + protection_counter++; + + SEXP colnames = PROTECT( + Rf_allocVector(STRSXP, k) + ); + protection_counter++; + // clang-format on + + for (int j = 0; j < k; j++) { + SET_STRING_ELT(colnames, j, Rf_mkChar(names[j])); + } + + SET_VECTOR_ELT(dimensions, 0, R_NilValue); + SET_VECTOR_ELT(dimensions, 1, colnames); + + // set attributes of + // the underlying + Rf_setAttrib(x, R_DimNamesSymbol, dimensions); + + UNPROTECT(protection_counter); +} + // names.c // // When using rownames(x) <- x_names from R @@ -17,23 +60,21 @@ // // NOTE: If colnames is NOT passed in matrix methods // it will crash. -#include -#include -#include // clang-format off -SEXP rownames_data_frame( +void rownames_data_frame( SEXP x, SEXP rownames ) // clang-format on { - setAttrib(x, R_RowNamesSymbol, rownames); - return R_NilValue; + Rf_setAttrib(x, R_RowNamesSymbol, rownames); + + return; } // clang-format off -SEXP rownames_matrix( +void rownames_matrix( SEXP x, SEXP rownames, SEXP colnames @@ -42,15 +83,16 @@ SEXP rownames_matrix( { // clang-format off SEXP container = PROTECT( - allocVector(VECSXP, 2) + Rf_allocVector(VECSXP, 2) ); // clang-format on SET_VECTOR_ELT(container, 0, rownames); SET_VECTOR_ELT(container, 1, colnames); - setAttrib(x, R_DimNamesSymbol, container); + Rf_setAttrib(x, R_DimNamesSymbol, container); UNPROTECT(1); - return R_NilValue; -} + + return; +} \ No newline at end of file diff --git a/src/names.h b/src/names.h index 1ebcc42eb..3c9d04916 100644 --- a/src/names.h +++ b/src/names.h @@ -1,34 +1,10 @@ -// names -// -// Description -// Set names of matrices -#ifndef _names_h -#define _names_h +#ifndef NAMES_H +#define NAMES_H -#include #include -static inline void -column_names(SEXP x, int n_cols, const char *const *colnames) { +void set_colnames(SEXP x, const char *const *names, int k); +void rownames_data_frame(SEXP x, SEXP rownames); +void rownames_matrix(SEXP x, SEXP rownames, SEXP colnames); - SEXP dn = PROTECT(Rf_allocVector(VECSXP, 2)); - SEXP cn = PROTECT(Rf_allocVector(STRSXP, n_cols)); - for (int j = 0; j < n_cols; ++j) { - SET_STRING_ELT(cn, j, Rf_mkCharCE(colnames[j], CE_UTF8)); - } - - SET_VECTOR_ELT(dn, 0, R_NilValue); - SET_VECTOR_ELT(dn, 1, cn); - Rf_dimnamesgets(x, dn); - UNPROTECT(2); -} - -// clang-format off -#define set_colnames(x, ...) \ - do { \ - const char *_cn_[] = {__VA_ARGS__}; \ - column_names((x), (int) (sizeof _cn_ / sizeof *_cn_), _cn_); \ - } while (0) -// clang-format on - -#endif // _names_h \ No newline at end of file +#endif /* NAMES_H */ diff --git a/src/normalize.h b/src/normalize.h index 1277bcb62..dba9616b3 100644 --- a/src/normalize.h +++ b/src/normalize.h @@ -1,4 +1,4 @@ -// normalize +// normalize.h // // Parameters // arr: The array to be normalized. Double or int pointer @@ -11,7 +11,7 @@ // This function modifies the array in-place by scaling with // a factor. The shifting parameter sets the starting point // of the iterator. -// Its necesseary because the ta_CDL*.c programs returns -100, 0, 100 +// Its necessary because the ta_CDL*.c programs returns -100, 0, 100 // which is not R agnostic. // // Note @@ -42,82 +42,4 @@ static inline void normalize_int(int *arr, int n, int factor, int shift) { #define normalize(arr, n, factor, shift) _Generic((arr), double*: normalize_double, int*: normalize_int)((arr),(n),(factor), (shift)) // clang-format on -// normalize_int_to_real -// -// Parameters -// integer_matrix: INTSXP matrix (candlestick output after shift and reexpand) -// divisor: The factor to divide by (typically 100.0) -// has_scattered_na: Whether NA values exist beyond the lookback -// region. Set to 1 when na_ignore reexpansion was -// performed, 0 otherwise. -// protection_count: Pointer to the PROTECT counter -// -// Description -// Converts an INTSXP matrix to REALSXP by dividing each element -// by divisor. The leading lookback region is filled with NA_REAL -// directly (no division). When has_scattered_na is 0 (the common -// path), the data region is divided unconditionally with no -// per-element NA check. When has_scattered_na is 1, elements -// equal to NA_INTEGER are mapped to NA_REAL. -// -// Returns a PROTECTed REALSXP matrix with dimnames and -// lookback attribute copied from the input. -static inline SEXP normalize_int_to_real( - SEXP integer_matrix, - double divisor, - int has_scattered_na, - int *protection_count) { - const int num_rows = Rf_nrows(integer_matrix); - const int num_cols = Rf_ncols(integer_matrix); - const int total_elements = num_rows * num_cols; - - SEXP lookback_sexp = Rf_getAttrib(integer_matrix, Rf_install("lookback")); - const int lookback_length = - (lookback_sexp != R_NilValue) ? INTEGER(lookback_sexp)[0] : 0; - - SEXP real_matrix = PROTECT(allocMatrix(REALSXP, num_rows, num_cols)); - (*protection_count)++; - - const int *source_values = INTEGER(integer_matrix); - double *destination_values = REAL(real_matrix); - - // leading NA region: write NA_REAL directly - for (int i = 0; i < lookback_length; i++) { - destination_values[i] = NA_REAL; - } - - // data region - if (has_scattered_na) { - // safe path: check each element for NA_INTEGER - // (needed after na_ignore reexpansion inserts scattered NAs) - for (int i = lookback_length; i < total_elements; i++) { - destination_values[i] = (source_values[i] == NA_INTEGER) - ? NA_REAL - : (double)source_values[i] / divisor; - } - } else { - // fast path: no scattered NAs, unconditional division - for (int i = lookback_length; i < total_elements; i++) { - destination_values[i] = (double)source_values[i] / divisor; - } - } - - // copy dimnames (column names) - SEXP dimnames_sexp = Rf_getAttrib(integer_matrix, R_DimNamesSymbol); - if (dimnames_sexp != R_NilValue) { - SEXP new_dimnames = PROTECT(Rf_allocVector(VECSXP, 2)); - (*protection_count)++; - SET_VECTOR_ELT(new_dimnames, 0, R_NilValue); - SET_VECTOR_ELT(new_dimnames, 1, VECTOR_ELT(dimnames_sexp, 1)); - Rf_dimnamesgets(real_matrix, new_dimnames); - } - - // copy lookback attribute - if (lookback_sexp != R_NilValue) { - Rf_setAttrib(real_matrix, Rf_install("lookback"), lookback_sexp); - } - - return real_matrix; -} - -#endif /* _NORMALIZE_H */ \ No newline at end of file +#endif /* _NORMALIZE_H */ diff --git a/src/preprocessor.h b/src/preprocessor.h new file mode 100644 index 000000000..e08a63e15 --- /dev/null +++ b/src/preprocessor.h @@ -0,0 +1,64 @@ +// preprocessor.h +// +// Generic preprocessor metaprogramming primitives +// (token paste, arg count, list map/join) used to +// drive the TA_WRAPPER X-macros. +#ifndef PREPROCESSOR_H +#define PREPROCESSOR_H + +// Token pasting with argument pre-expansion. +#define TA_CAT(a, b) TA_CAT_(a, b) +#define TA_CAT_(a, b) a##b + +// Strip parenthesis from an expression - +// can be used as follows: TA_STRIP_PARENTHESIS (a,b) -> a, b +#define TA_STRIP_PARENTHESIS(...) __VA_ARGS__ + +// HEAD, used via juxtaposition against a parenthesised group to pull the +// first element: TA_HEAD (a,b,c) -> a ; TA_HEAD (a) -> a +#define TA_HEAD(a, ...) a + +// Count the number of arguments given +// an expression - can be used as follows: +// #define FOO(SOME_MACRO_VALUE_) (TA_COUNT_ARGUMENTS SOME_MACRO_VALUE_) +#define TA_COUNT_ARGUMENTS(...) \ + TA_COUNT_ARGUMENTS_(0 __VA_OPT__(, ) __VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1, 0) +#define TA_COUNT_ARGUMENTS_(_0, _1, _2, _3, _4, _5, _6, _7, _8, N, ...) N + +// Apply worker m(x) to each element of a PARENTHESISED group (0..8 elements), +// results space-separated. The two indirections (TA_APPLY_D/_D_) let +// TA_COUNT_ARGUMENTS and TA_STRIP_PARENTHESIS of the group expand — revealing +// the element commas — before the TA_APPLY_ dispatcher enumerates them. +#define TA_APPLY(m, group) \ + TA_APPLY_D(m, TA_COUNT_ARGUMENTS group, TA_STRIP_PARENTHESIS group) +#define TA_APPLY_D(m, n, ...) TA_APPLY_D_(m, n, __VA_ARGS__) +#define TA_APPLY_D_(m, n, ...) TA_CAT(TA_APPLY_, n)(m, __VA_ARGS__) +#define TA_APPLY_0(m, ...) +#define TA_APPLY_1(m, a) m(a) +#define TA_APPLY_2(m, a, ...) m(a) TA_APPLY_1(m, __VA_ARGS__) +#define TA_APPLY_3(m, a, ...) m(a) TA_APPLY_2(m, __VA_ARGS__) +#define TA_APPLY_4(m, a, ...) m(a) TA_APPLY_3(m, __VA_ARGS__) +#define TA_APPLY_5(m, a, ...) m(a) TA_APPLY_4(m, __VA_ARGS__) +#define TA_APPLY_6(m, a, ...) m(a) TA_APPLY_5(m, __VA_ARGS__) +#define TA_APPLY_7(m, a, ...) m(a) TA_APPLY_6(m, __VA_ARGS__) +#define TA_APPLY_8(m, a, ...) m(a) TA_APPLY_7(m, __VA_ARGS__) + +// Like TA_APPLY, but the worker results are separated by commas (not +// juxtaposed) and there is no trailing comma - i.e. a valid function-call +// argument list. Used to synthesise TA__Lookback() in wrapper.h. +// An empty group expands to nothing (the (void) lookbacks). +#define TA_JOIN(m, group) \ + TA_JOIN_D(m, TA_COUNT_ARGUMENTS group, TA_STRIP_PARENTHESIS group) +#define TA_JOIN_D(m, n, ...) TA_JOIN_D_(m, n, __VA_ARGS__) +#define TA_JOIN_D_(m, n, ...) TA_CAT(TA_JOIN_, n)(m, __VA_ARGS__) +#define TA_JOIN_0(m, ...) +#define TA_JOIN_1(m, a) m(a) +#define TA_JOIN_2(m, a, ...) m(a), TA_JOIN_1(m, __VA_ARGS__) +#define TA_JOIN_3(m, a, ...) m(a), TA_JOIN_2(m, __VA_ARGS__) +#define TA_JOIN_4(m, a, ...) m(a), TA_JOIN_3(m, __VA_ARGS__) +#define TA_JOIN_5(m, a, ...) m(a), TA_JOIN_4(m, __VA_ARGS__) +#define TA_JOIN_6(m, a, ...) m(a), TA_JOIN_5(m, __VA_ARGS__) +#define TA_JOIN_7(m, a, ...) m(a), TA_JOIN_6(m, __VA_ARGS__) +#define TA_JOIN_8(m, a, ...) m(a), TA_JOIN_7(m, __VA_ARGS__) + +#endif /* PREPROCESSOR_H */ diff --git a/src/shift.c b/src/shift.c new file mode 100644 index 000000000..f03ea47da --- /dev/null +++ b/src/shift.c @@ -0,0 +1,112 @@ + +// Shift array +// +// Parameters +// col: the array to be shifted. Double or int pointer +// n: the size of the input array. Int. +// begIdx: the amount of shifting. Int. +// nbElement: +// +// Description +// This function shifts an array to the right, or down in memory, and adds +// leading NAs from 0 to the shift value. +// +// Details +// arr + shift advances pointer, ie. shifts +// the entire array in memory. So an array of +// {0,1,2} shifted with 1 does {garbage value, 1, +// 2}, a shift by 0 just returns the {0,1,2} array +// +// Generic +// It has a generic version shift_array(...) +// +// Note +// See: https://gist.github.com/barosl/e0af4a92b2b8cabd05a7 +// See: +// https://stackoverflow.com/questions/479207/how-to-achieve-function-overloading-in-c +// See: +// https://stackoverflow.com/questions/479207/how-to-achieve-function-overloading-in-c/25026358#25026358 +#include "shift.h" +#include +// clang-format off +#define MAX(x, y) (((x) < (y)) ? (y) : (x)) +#define MIN(x, y) (((x) < (y)) ? (x) : (y)) +void shift_double_array( + double *col, + R_xlen_t n, + int begIdx, + int nbElement +) +// clang-format on +{ + // clip begIdx between 0 and n + begIdx = MIN(MAX(begIdx, 0), (int)n); + + // clip nbElement between 0 and n - begIdx + // clang-format off + nbElement = MAX(nbElement, 0); + nbElement = (int) MIN( + (R_xlen_t) nbElement, + n - (R_xlen_t) begIdx + ); + // clang-format on + + // clang-format off + memmove( + col + begIdx, + col, + (size_t)nbElement * sizeof(double) + ); + // clang-format on + + // padding + for (R_xlen_t i = 0; i < begIdx; i++) { + col[i] = NA_REAL; + } + + for (R_xlen_t i = (R_xlen_t)begIdx + nbElement; i < n; i++) { + col[i] = NA_REAL; + } +} + +// clang-format off +void shift_integer_array( + int *col, + R_xlen_t n, + int begIdx, + int nbElement +) +// clang-format on +{ + + // clip begIdx between 0 and n + begIdx = MIN(MAX(begIdx, 0), (int)n); + + // clip nbElement between 0 and n - begIdx + // clang-format off + nbElement = MAX(nbElement, 0); + nbElement = (int) MIN( + (R_xlen_t) nbElement, + n - (R_xlen_t) begIdx + ); + // clang-format on + + // clang-format off + memmove( + col + begIdx, + col, + (size_t)nbElement * sizeof(int) + ); + // clang-format on + + // padding + for (R_xlen_t i = 0; i < begIdx; i++) { + col[i] = NA_INTEGER; + } + for (R_xlen_t i = (R_xlen_t)begIdx + nbElement; i < n; i++) { + col[i] = NA_INTEGER; + } +} +#undef MAX +#undef MIN +// shift array end \ No newline at end of file diff --git a/src/shift.h b/src/shift.h index 7ceedf348..f80040d13 100644 --- a/src/shift.h +++ b/src/shift.h @@ -1,113 +1,20 @@ -// shift_array -// -// Parameters -// arr: the array to be shifted. Double or int pointer -// len: the size of the input array. Int. -// shift: the amount of shifting. Int. -// -// Description -// This function shifts an array to the right, or down in memory, and adds -// leading NAs from 0 to the shift value. -// -// Details -// arr + shift advances pointer, ie. shifts -// the entire array in memory. So an array of -// {0,1,2} shifted with 1 does {garbage value, 1, -// 2}, a shift by 0 just returns the {0,1,2} array -// -// Note -// See: https://gist.github.com/barosl/e0af4a92b2b8cabd05a7 -// See: -// https://stackoverflow.com/questions/479207/how-to-achieve-function-overloading-in-c -// See: -// https://stackoverflow.com/questions/479207/how-to-achieve-function-overloading-in-c/25026358#25026358 -// -// -// shift each array -// -// NOTE: There is most likely a better -// way to do this. But as it is, -// this move costs 3 x 5.33 ms for a -// normally distributed double vector of -// of length 1e7; the SMA costs 57ms -// its 10% overhead, which is alot. But -// if anyone is doing calculations on 1e7 -// they probably have bigger thing to worry -// about. -#ifndef _SHIFT_H -#define _SHIFT_H +#ifndef SHIFT_H +#define SHIFT_H -#include "R_ext/Arith.h" -#include +#include -static void shift_double_array(double *arr, int len, int shift) { - // 0) edge-case: - // If the shift is greater than - // the length of the array, or the shift - // is lte 0, everything is NA. - // - // **NOTE:** this is highly unlikely but - // added just in case to avoid crashes. - // - // It could probably be a better idea just - // terminate the function instead. - if (shift < 0 || shift >= len) { - for (int i = 0; i < len; ++i) { - arr[i] = NA_REAL; - } - return; - } - - // 1) shift the arrayy - // in place - memmove( - /*dest:*/ arr + shift, - /*src*/ arr, - /*n*/ (size_t)(len - shift) * sizeof(double)); - - // 2) add leading NAs - // as NA_REAL for - // type compatibility - for (int i = 0; i < shift; ++i) { - arr[i] = NA_REAL; - } -} - -static void shift_int_array(int *arr, int len, int shift) { - // 0) edge-case: - // If the shift is greater than - // the length of the array, or the shift - // is lte 0, everything is NA. - // - // **NOTE:** this is highly unlikely but - // added just in case to avoid crashes. - // - // It could probably be a better idea just - // terminate the function instead. - if (shift < 0 || shift >= len) { - for (int i = 0; i < len; ++i) { - arr[i] = NA_INTEGER; - } - return; - } - - // 1) shift the arrayy - // in place - memmove( - /*dest:*/ arr + shift, - /*src*/ arr, - /*n*/ (size_t)(len - shift) * sizeof(int)); - - // 2) add leading NAs - // as NA_REAL for - // type compatibility - for (int i = 0; i < shift; ++i) { - arr[i] = NA_INTEGER; - } -} +void shift_double_array(double *col, R_xlen_t n, int begIdx, int nbElement); +void shift_integer_array(int *col, R_xlen_t n, int begIdx, int nbElement); // clang-format off -#define shift_array(arr, len, shift) _Generic((arr), int*: shift_int_array, double*: shift_double_array)(arr, len, shift) +// Generic shift_array +// +// Description +// Works similar to S3 functions in R +// _Generic( (x), type: dispatch ) ( signature ) +#define shift_array(col, n, begIdx, nbElement) \ + _Generic((col), double*: shift_double_array, int*: shift_integer_array) \ + ((col), (n), (begIdx), (nbElement)) // clang-format on -#endif // _SHIFT_H \ No newline at end of file +#endif /* SHIFT_H */ \ No newline at end of file diff --git a/src/ta-lib b/src/ta-lib index c042ea3a7..a8272d0c2 160000 --- a/src/ta-lib +++ b/src/ta-lib @@ -1 +1 @@ -Subproject commit c042ea3a7b38baa05b57764cdbb1288da9baf5bf +Subproject commit a8272d0c2a90c6974dad2c2e2358c0bd4127d57f diff --git a/src/ta_ACCBANDS.c b/src/ta_ACCBANDS.c deleted file mode 100644 index 7fc4a395c..000000000 --- a/src/ta_ACCBANDS.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_ACCBANDS.c -// -// Parameters -// double inHigh -// double inLow -// double inClose -// integer optInTimePeriod -// -// Returns -// matrix (n x 3) with colum: -// "UpperBand", "MiddleBand", "LowerBand" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_ACCBANDS.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_ACCBANDS( - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP optInTimePeriod, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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]; - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inHigh_ptr, inLow_ptr, inClose_ptr}; - n = build_na_mask(na_mask, n, 3, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 3, na_mask, n_original, n); - inHigh_ptr = na_arrays[0]; - inLow_ptr = na_arrays[1]; - inClose_ptr = na_arrays[2]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_ACCBANDS_Lookback(optInTimePeriod_value); - - // 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 - const int proceed = - output_container(n, lookback, 3, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *realupperband = output_ptr; - double *realmiddleband = output_ptr + 1 * n; - double *reallowerband = output_ptr + 2 * n; - - // TA_ACCBANDS returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_ACCBANDS( - 0, - n - 1, - inHigh_ptr, - inLow_ptr, - inClose_ptr, - optInTimePeriod_value, - &start_idx, - &end_idx, - realupperband, - realmiddleband, - reallowerband); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(realupperband, n, start_idx); - shift_array(realmiddleband, n, start_idx); - shift_array(reallowerband, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "UpperBand", "MiddleBand", "LowerBand"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_AD.c b/src/ta_AD.c deleted file mode 100644 index 0b765e71d..000000000 --- a/src/ta_AD.c +++ /dev/null @@ -1,141 +0,0 @@ -// interface to ta_AD.c -// -// Parameters -// double inHigh -// double inLow -// double inClose -// double inVolume -// -// Returns -// matrix (n x 1) with colum: -// "AD" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_AD.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_AD( - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP inVolume, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = - {inHigh_ptr, inLow_ptr, inClose_ptr, inVolume_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - inHigh_ptr = na_arrays[0]; - inLow_ptr = na_arrays[1]; - inClose_ptr = na_arrays[2]; - inVolume_ptr = na_arrays[3]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_AD_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *real = output_ptr; - - // TA_AD returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_AD( - 0, - n - 1, - inHigh_ptr, - inLow_ptr, - inClose_ptr, - inVolume_ptr, - &start_idx, - &end_idx, - real); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(real, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "AD"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_ADOSC.c b/src/ta_ADOSC.c deleted file mode 100644 index f1dca97c6..000000000 --- a/src/ta_ADOSC.c +++ /dev/null @@ -1,152 +0,0 @@ -// interface to ta_ADOSC.c -// -// Parameters -// double inHigh -// double inLow -// double inClose -// double inVolume -// integer optInFastPeriod -// integer optInSlowPeriod -// -// Returns -// matrix (n x 1) with colum: -// "ADOSC" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_ADOSC.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_ADOSC( - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP inVolume, - SEXP optInFastPeriod, - SEXP optInSlowPeriod, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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]; - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = - {inHigh_ptr, inLow_ptr, inClose_ptr, inVolume_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - inHigh_ptr = na_arrays[0]; - inLow_ptr = na_arrays[1]; - inClose_ptr = na_arrays[2]; - inVolume_ptr = na_arrays[3]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = - TA_ADOSC_Lookback(optInFastPeriod_value, optInSlowPeriod_value); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *real = output_ptr; - - // TA_ADOSC returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_ADOSC( - 0, - n - 1, - inHigh_ptr, - inLow_ptr, - inClose_ptr, - inVolume_ptr, - optInFastPeriod_value, - optInSlowPeriod_value, - &start_idx, - &end_idx, - real); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(real, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "ADOSC"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_ADX.c b/src/ta_ADX.c deleted file mode 100644 index 1a066ab49..000000000 --- a/src/ta_ADX.c +++ /dev/null @@ -1,141 +0,0 @@ -// interface to ta_ADX.c -// -// Parameters -// double inHigh -// double inLow -// double inClose -// integer optInTimePeriod -// -// Returns -// matrix (n x 1) with colum: -// "ADX" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_ADX.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_ADX( - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP optInTimePeriod, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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]; - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inHigh_ptr, inLow_ptr, inClose_ptr}; - n = build_na_mask(na_mask, n, 3, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 3, na_mask, n_original, n); - inHigh_ptr = na_arrays[0]; - inLow_ptr = na_arrays[1]; - inClose_ptr = na_arrays[2]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_ADX_Lookback(optInTimePeriod_value); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *real = output_ptr; - - // TA_ADX returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_ADX( - 0, - n - 1, - inHigh_ptr, - inLow_ptr, - inClose_ptr, - optInTimePeriod_value, - &start_idx, - &end_idx, - real); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(real, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "ADX"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_ADXR.c b/src/ta_ADXR.c deleted file mode 100644 index 90dda8633..000000000 --- a/src/ta_ADXR.c +++ /dev/null @@ -1,141 +0,0 @@ -// interface to ta_ADXR.c -// -// Parameters -// double inHigh -// double inLow -// double inClose -// integer optInTimePeriod -// -// Returns -// matrix (n x 1) with colum: -// "ADXR" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_ADXR.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_ADXR( - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP optInTimePeriod, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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]; - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inHigh_ptr, inLow_ptr, inClose_ptr}; - n = build_na_mask(na_mask, n, 3, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 3, na_mask, n_original, n); - inHigh_ptr = na_arrays[0]; - inLow_ptr = na_arrays[1]; - inClose_ptr = na_arrays[2]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_ADXR_Lookback(optInTimePeriod_value); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *real = output_ptr; - - // TA_ADXR returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_ADXR( - 0, - n - 1, - inHigh_ptr, - inLow_ptr, - inClose_ptr, - optInTimePeriod_value, - &start_idx, - &end_idx, - real); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(real, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "ADXR"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_APO.c b/src/ta_APO.c deleted file mode 100644 index f71189e3c..000000000 --- a/src/ta_APO.c +++ /dev/null @@ -1,142 +0,0 @@ -// interface to ta_APO.c -// -// Parameters -// double inReal -// integer optInFastPeriod -// integer optInSlowPeriod -// integer optInMAType (MAType) -// -// Returns -// matrix (n x 1) with colum: -// "APO" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_APO.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_APO( - SEXP inReal, - SEXP optInFastPeriod, - SEXP optInSlowPeriod, - SEXP optInMAType, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inReal_ptr}; - n = build_na_mask(na_mask, n, 1, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 1, na_mask, n_original, n); - inReal_ptr = na_arrays[0]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_APO_Lookback( - optInFastPeriod_value, - optInSlowPeriod_value, - optInMAType_value); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *real = output_ptr; - - // TA_APO returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_APO( - 0, - n - 1, - inReal_ptr, - optInFastPeriod_value, - optInSlowPeriod_value, - optInMAType_value, - &start_idx, - &end_idx, - real); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(real, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "APO"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_AROON.c b/src/ta_AROON.c deleted file mode 100644 index 948c9b941..000000000 --- a/src/ta_AROON.c +++ /dev/null @@ -1,139 +0,0 @@ -// interface to ta_AROON.c -// -// Parameters -// double inHigh -// double inLow -// integer optInTimePeriod -// -// Returns -// matrix (n x 2) with colum: -// "AroonDown", "AroonUp" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_AROON.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_AROON( - SEXP inHigh, - SEXP inLow, - SEXP optInTimePeriod, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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]; - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inHigh_ptr, inLow_ptr}; - n = build_na_mask(na_mask, n, 2, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 2, na_mask, n_original, n); - inHigh_ptr = na_arrays[0]; - inLow_ptr = na_arrays[1]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_AROON_Lookback(optInTimePeriod_value); - - // 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 - const int proceed = - output_container(n, lookback, 2, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *aroondown = output_ptr; - double *aroonup = output_ptr + 1 * n; - - // TA_AROON returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_AROON( - 0, - n - 1, - inHigh_ptr, - inLow_ptr, - optInTimePeriod_value, - &start_idx, - &end_idx, - aroondown, - aroonup); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(aroondown, n, start_idx); - shift_array(aroonup, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "AroonDown", "AroonUp"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_AROONOSC.c b/src/ta_AROONOSC.c deleted file mode 100644 index a0247912a..000000000 --- a/src/ta_AROONOSC.c +++ /dev/null @@ -1,136 +0,0 @@ -// interface to ta_AROONOSC.c -// -// Parameters -// double inHigh -// double inLow -// integer optInTimePeriod -// -// Returns -// matrix (n x 1) with colum: -// "AROONOSC" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_AROONOSC.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_AROONOSC( - SEXP inHigh, - SEXP inLow, - SEXP optInTimePeriod, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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]; - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inHigh_ptr, inLow_ptr}; - n = build_na_mask(na_mask, n, 2, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 2, na_mask, n_original, n); - inHigh_ptr = na_arrays[0]; - inLow_ptr = na_arrays[1]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_AROONOSC_Lookback(optInTimePeriod_value); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *real = output_ptr; - - // TA_AROONOSC returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_AROONOSC( - 0, - n - 1, - inHigh_ptr, - inLow_ptr, - optInTimePeriod_value, - &start_idx, - &end_idx, - real); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(real, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "AROONOSC"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_ATR.c b/src/ta_ATR.c deleted file mode 100644 index e9c41d9e6..000000000 --- a/src/ta_ATR.c +++ /dev/null @@ -1,141 +0,0 @@ -// interface to ta_ATR.c -// -// Parameters -// double inHigh -// double inLow -// double inClose -// integer optInTimePeriod -// -// Returns -// matrix (n x 1) with colum: -// "ATR" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_ATR.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_ATR( - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP optInTimePeriod, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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]; - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inHigh_ptr, inLow_ptr, inClose_ptr}; - n = build_na_mask(na_mask, n, 3, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 3, na_mask, n_original, n); - inHigh_ptr = na_arrays[0]; - inLow_ptr = na_arrays[1]; - inClose_ptr = na_arrays[2]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_ATR_Lookback(optInTimePeriod_value); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *real = output_ptr; - - // TA_ATR returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_ATR( - 0, - n - 1, - inHigh_ptr, - inLow_ptr, - inClose_ptr, - optInTimePeriod_value, - &start_idx, - &end_idx, - real); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(real, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "ATR"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_AVGPRICE.c b/src/ta_AVGPRICE.c deleted file mode 100644 index 1ea08e875..000000000 --- a/src/ta_AVGPRICE.c +++ /dev/null @@ -1,141 +0,0 @@ -// interface to ta_AVGPRICE.c -// -// Parameters -// double inOpen -// double inHigh -// double inLow -// double inClose -// -// Returns -// matrix (n x 1) with colum: -// "AVGPRICE" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_AVGPRICE.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_AVGPRICE( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = - {inOpen_ptr, inHigh_ptr, inLow_ptr, inClose_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - inOpen_ptr = na_arrays[0]; - inHigh_ptr = na_arrays[1]; - inLow_ptr = na_arrays[2]; - inClose_ptr = na_arrays[3]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_AVGPRICE_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *real = output_ptr; - - // TA_AVGPRICE returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_AVGPRICE( - 0, - n - 1, - inOpen_ptr, - inHigh_ptr, - inLow_ptr, - inClose_ptr, - &start_idx, - &end_idx, - real); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(real, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "AVGPRICE"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_BBANDS.c b/src/ta_BBANDS.c deleted file mode 100644 index 81f68e0df..000000000 --- a/src/ta_BBANDS.c +++ /dev/null @@ -1,153 +0,0 @@ -// interface to ta_BBANDS.c -// -// Parameters -// double inReal -// integer optInTimePeriod -// double optInNbDevUp -// double optInNbDevDn -// integer optInMAType (MAType) -// -// Returns -// matrix (n x 3) with colum: -// "UpperBand", "MiddleBand", "LowerBand" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_BBANDS.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_BBANDS( - SEXP inReal, - SEXP optInTimePeriod, - SEXP optInNbDevUp, - SEXP optInNbDevDn, - SEXP optInMAType, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inReal_ptr}; - n = build_na_mask(na_mask, n, 1, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 1, na_mask, n_original, n); - inReal_ptr = na_arrays[0]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_BBANDS_Lookback( - optInTimePeriod_value, - optInNbDevUp_value, - optInNbDevDn_value, - optInMAType_value); - - // 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 - const int proceed = - output_container(n, lookback, 3, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *realupperband = output_ptr; - double *realmiddleband = output_ptr + 1 * n; - double *reallowerband = output_ptr + 2 * n; - - // TA_BBANDS returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_BBANDS( - 0, - n - 1, - inReal_ptr, - optInTimePeriod_value, - optInNbDevUp_value, - optInNbDevDn_value, - optInMAType_value, - &start_idx, - &end_idx, - realupperband, - realmiddleband, - reallowerband); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(realupperband, n, start_idx); - shift_array(realmiddleband, n, start_idx); - shift_array(reallowerband, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "UpperBand", "MiddleBand", "LowerBand"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_BETA.c b/src/ta_BETA.c deleted file mode 100644 index d1d0476f4..000000000 --- a/src/ta_BETA.c +++ /dev/null @@ -1,136 +0,0 @@ -// interface to ta_BETA.c -// -// Parameters -// double inReal0 -// double inReal1 -// integer optInTimePeriod -// -// Returns -// matrix (n x 1) with colum: -// "BETA" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_BETA.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_BETA( - SEXP inReal0, - SEXP inReal1, - SEXP optInTimePeriod, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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]; - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inReal0_ptr, inReal1_ptr}; - n = build_na_mask(na_mask, n, 2, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 2, na_mask, n_original, n); - inReal0_ptr = na_arrays[0]; - inReal1_ptr = na_arrays[1]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_BETA_Lookback(optInTimePeriod_value); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *real = output_ptr; - - // TA_BETA returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_BETA( - 0, - n - 1, - inReal0_ptr, - inReal1_ptr, - optInTimePeriod_value, - &start_idx, - &end_idx, - real); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(real, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "BETA"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_BOP.c b/src/ta_BOP.c deleted file mode 100644 index 430c1d552..000000000 --- a/src/ta_BOP.c +++ /dev/null @@ -1,141 +0,0 @@ -// interface to ta_BOP.c -// -// Parameters -// double inOpen -// double inHigh -// double inLow -// double inClose -// -// Returns -// matrix (n x 1) with colum: -// "BOP" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_BOP.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_BOP( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = - {inOpen_ptr, inHigh_ptr, inLow_ptr, inClose_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - inOpen_ptr = na_arrays[0]; - inHigh_ptr = na_arrays[1]; - inLow_ptr = na_arrays[2]; - inClose_ptr = na_arrays[3]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_BOP_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *real = output_ptr; - - // TA_BOP returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_BOP( - 0, - n - 1, - inOpen_ptr, - inHigh_ptr, - inLow_ptr, - inClose_ptr, - &start_idx, - &end_idx, - real); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(real, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "BOP"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CCI.c b/src/ta_CCI.c deleted file mode 100644 index 467dfd77a..000000000 --- a/src/ta_CCI.c +++ /dev/null @@ -1,141 +0,0 @@ -// interface to ta_CCI.c -// -// Parameters -// double inHigh -// double inLow -// double inClose -// integer optInTimePeriod -// -// Returns -// matrix (n x 1) with colum: -// "CCI" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CCI.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_CCI( - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP optInTimePeriod, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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]; - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inHigh_ptr, inLow_ptr, inClose_ptr}; - n = build_na_mask(na_mask, n, 3, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 3, na_mask, n_original, n); - inHigh_ptr = na_arrays[0]; - inLow_ptr = na_arrays[1]; - inClose_ptr = na_arrays[2]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CCI_Lookback(optInTimePeriod_value); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *real = output_ptr; - - // TA_CCI returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CCI( - 0, - n - 1, - inHigh_ptr, - inLow_ptr, - inClose_ptr, - optInTimePeriod_value, - &start_idx, - &end_idx, - real); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(real, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CCI"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDL2CROWS.c b/src/ta_CDL2CROWS.c deleted file mode 100644 index 0ba19c781..000000000 --- a/src/ta_CDL2CROWS.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_CDL2CROWS.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDL2CROWS" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDL2CROWS.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDL2CROWS( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDL2CROWS_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDL2CROWS returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDL2CROWS( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDL2CROWS"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDL2CROWS returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDL3BLACKCROWS.c b/src/ta_CDL3BLACKCROWS.c deleted file mode 100644 index 2119b9524..000000000 --- a/src/ta_CDL3BLACKCROWS.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_CDL3BLACKCROWS.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDL3BLACKCROWS" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDL3BLACKCROWS.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDL3BLACKCROWS( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDL3BLACKCROWS_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDL3BLACKCROWS returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDL3BLACKCROWS( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDL3BLACKCROWS"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDL3BLACKCROWS returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDL3INSIDE.c b/src/ta_CDL3INSIDE.c deleted file mode 100644 index 23220d6a6..000000000 --- a/src/ta_CDL3INSIDE.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_CDL3INSIDE.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDL3INSIDE" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDL3INSIDE.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDL3INSIDE( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDL3INSIDE_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDL3INSIDE returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDL3INSIDE( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDL3INSIDE"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDL3INSIDE returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDL3LINESTRIKE.c b/src/ta_CDL3LINESTRIKE.c deleted file mode 100644 index a0ee4b6ec..000000000 --- a/src/ta_CDL3LINESTRIKE.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_CDL3LINESTRIKE.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDL3LINESTRIKE" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDL3LINESTRIKE.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDL3LINESTRIKE( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDL3LINESTRIKE_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDL3LINESTRIKE returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDL3LINESTRIKE( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDL3LINESTRIKE"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDL3LINESTRIKE returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDL3OUTSIDE.c b/src/ta_CDL3OUTSIDE.c deleted file mode 100644 index 5cf16e81a..000000000 --- a/src/ta_CDL3OUTSIDE.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_CDL3OUTSIDE.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDL3OUTSIDE" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDL3OUTSIDE.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDL3OUTSIDE( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDL3OUTSIDE_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDL3OUTSIDE returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDL3OUTSIDE( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDL3OUTSIDE"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDL3OUTSIDE returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDL3STARSINSOUTH.c b/src/ta_CDL3STARSINSOUTH.c deleted file mode 100644 index 93083dc43..000000000 --- a/src/ta_CDL3STARSINSOUTH.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_CDL3STARSINSOUTH.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDL3STARSINSOUTH" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDL3STARSINSOUTH.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDL3STARSINSOUTH( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDL3STARSINSOUTH_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDL3STARSINSOUTH returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDL3STARSINSOUTH( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDL3STARSINSOUTH"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDL3STARSINSOUTH returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDL3WHITESOLDIERS.c b/src/ta_CDL3WHITESOLDIERS.c deleted file mode 100644 index d0cfd8ef3..000000000 --- a/src/ta_CDL3WHITESOLDIERS.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_CDL3WHITESOLDIERS.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDL3WHITESOLDIERS" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDL3WHITESOLDIERS.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDL3WHITESOLDIERS( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDL3WHITESOLDIERS_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDL3WHITESOLDIERS returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDL3WHITESOLDIERS( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDL3WHITESOLDIERS"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDL3WHITESOLDIERS returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDLABANDONEDBABY.c b/src/ta_CDLABANDONEDBABY.c deleted file mode 100644 index af02a6a29..000000000 --- a/src/ta_CDLABANDONEDBABY.c +++ /dev/null @@ -1,152 +0,0 @@ -// interface to ta_CDLABANDONEDBABY.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// double optInPenetration -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDLABANDONEDBABY" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDLABANDONEDBABY.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDLABANDONEDBABY( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP optInPenetration, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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]; - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDLABANDONEDBABY_Lookback(penetration); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDLABANDONEDBABY returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDLABANDONEDBABY( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - penetration, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDLABANDONEDBABY"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDLABANDONEDBABY returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDLADVANCEBLOCK.c b/src/ta_CDLADVANCEBLOCK.c deleted file mode 100644 index 2ddb9f16b..000000000 --- a/src/ta_CDLADVANCEBLOCK.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_CDLADVANCEBLOCK.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDLADVANCEBLOCK" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDLADVANCEBLOCK.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDLADVANCEBLOCK( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDLADVANCEBLOCK_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDLADVANCEBLOCK returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDLADVANCEBLOCK( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDLADVANCEBLOCK"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDLADVANCEBLOCK returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDLBELTHOLD.c b/src/ta_CDLBELTHOLD.c deleted file mode 100644 index 86e808c23..000000000 --- a/src/ta_CDLBELTHOLD.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_CDLBELTHOLD.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDLBELTHOLD" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDLBELTHOLD.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDLBELTHOLD( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDLBELTHOLD_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDLBELTHOLD returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDLBELTHOLD( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDLBELTHOLD"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDLBELTHOLD returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDLBREAKAWAY.c b/src/ta_CDLBREAKAWAY.c deleted file mode 100644 index 122ca67d5..000000000 --- a/src/ta_CDLBREAKAWAY.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_CDLBREAKAWAY.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDLBREAKAWAY" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDLBREAKAWAY.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDLBREAKAWAY( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDLBREAKAWAY_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDLBREAKAWAY returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDLBREAKAWAY( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDLBREAKAWAY"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDLBREAKAWAY returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDLCLOSINGMARUBOZU.c b/src/ta_CDLCLOSINGMARUBOZU.c deleted file mode 100644 index 35b7f2e88..000000000 --- a/src/ta_CDLCLOSINGMARUBOZU.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_CDLCLOSINGMARUBOZU.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDLCLOSINGMARUBOZU" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDLCLOSINGMARUBOZU.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDLCLOSINGMARUBOZU( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDLCLOSINGMARUBOZU_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDLCLOSINGMARUBOZU returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDLCLOSINGMARUBOZU( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDLCLOSINGMARUBOZU"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDLCLOSINGMARUBOZU returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDLCONCEALBABYSWALL.c b/src/ta_CDLCONCEALBABYSWALL.c deleted file mode 100644 index 31c1e9d9d..000000000 --- a/src/ta_CDLCONCEALBABYSWALL.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_CDLCONCEALBABYSWALL.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDLCONCEALBABYSWALL" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDLCONCEALBABYSWALL.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDLCONCEALBABYSWALL( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDLCONCEALBABYSWALL_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDLCONCEALBABYSWALL returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDLCONCEALBABYSWALL( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDLCONCEALBABYSWALL"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDLCONCEALBABYSWALL returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDLCOUNTERATTACK.c b/src/ta_CDLCOUNTERATTACK.c deleted file mode 100644 index ecc8e9f72..000000000 --- a/src/ta_CDLCOUNTERATTACK.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_CDLCOUNTERATTACK.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDLCOUNTERATTACK" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDLCOUNTERATTACK.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDLCOUNTERATTACK( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDLCOUNTERATTACK_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDLCOUNTERATTACK returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDLCOUNTERATTACK( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDLCOUNTERATTACK"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDLCOUNTERATTACK returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDLDARKCLOUDCOVER.c b/src/ta_CDLDARKCLOUDCOVER.c deleted file mode 100644 index 9abf0809f..000000000 --- a/src/ta_CDLDARKCLOUDCOVER.c +++ /dev/null @@ -1,152 +0,0 @@ -// interface to ta_CDLDARKCLOUDCOVER.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// double optInPenetration -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDLDARKCLOUDCOVER" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDLDARKCLOUDCOVER.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDLDARKCLOUDCOVER( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP optInPenetration, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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]; - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDLDARKCLOUDCOVER_Lookback(penetration); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDLDARKCLOUDCOVER returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDLDARKCLOUDCOVER( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - penetration, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDLDARKCLOUDCOVER"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDLDARKCLOUDCOVER returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDLDOJI.c b/src/ta_CDLDOJI.c deleted file mode 100644 index e9faf5f87..000000000 --- a/src/ta_CDLDOJI.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_CDLDOJI.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDLDOJI" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDLDOJI.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDLDOJI( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDLDOJI_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDLDOJI returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDLDOJI( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDLDOJI"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDLDOJI returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDLDOJISTAR.c b/src/ta_CDLDOJISTAR.c deleted file mode 100644 index 9241eeaad..000000000 --- a/src/ta_CDLDOJISTAR.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_CDLDOJISTAR.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDLDOJISTAR" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDLDOJISTAR.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDLDOJISTAR( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDLDOJISTAR_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDLDOJISTAR returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDLDOJISTAR( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDLDOJISTAR"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDLDOJISTAR returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDLDRAGONFLYDOJI.c b/src/ta_CDLDRAGONFLYDOJI.c deleted file mode 100644 index 03be99e17..000000000 --- a/src/ta_CDLDRAGONFLYDOJI.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_CDLDRAGONFLYDOJI.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDLDRAGONFLYDOJI" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDLDRAGONFLYDOJI.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDLDRAGONFLYDOJI( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDLDRAGONFLYDOJI_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDLDRAGONFLYDOJI returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDLDRAGONFLYDOJI( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDLDRAGONFLYDOJI"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDLDRAGONFLYDOJI returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDLENGULFING.c b/src/ta_CDLENGULFING.c deleted file mode 100644 index 8dbb06d85..000000000 --- a/src/ta_CDLENGULFING.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_CDLENGULFING.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDLENGULFING" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDLENGULFING.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDLENGULFING( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDLENGULFING_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDLENGULFING returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDLENGULFING( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDLENGULFING"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDLENGULFING returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDLEVENINGDOJISTAR.c b/src/ta_CDLEVENINGDOJISTAR.c deleted file mode 100644 index ba51e0f05..000000000 --- a/src/ta_CDLEVENINGDOJISTAR.c +++ /dev/null @@ -1,152 +0,0 @@ -// interface to ta_CDLEVENINGDOJISTAR.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// double optInPenetration -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDLEVENINGDOJISTAR" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDLEVENINGDOJISTAR.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDLEVENINGDOJISTAR( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP optInPenetration, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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]; - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDLEVENINGDOJISTAR_Lookback(penetration); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDLEVENINGDOJISTAR returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDLEVENINGDOJISTAR( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - penetration, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDLEVENINGDOJISTAR"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDLEVENINGDOJISTAR returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDLEVENINGSTAR.c b/src/ta_CDLEVENINGSTAR.c deleted file mode 100644 index 1b82c5724..000000000 --- a/src/ta_CDLEVENINGSTAR.c +++ /dev/null @@ -1,152 +0,0 @@ -// interface to ta_CDLEVENINGSTAR.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// double optInPenetration -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDLEVENINGSTAR" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDLEVENINGSTAR.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDLEVENINGSTAR( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP optInPenetration, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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]; - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDLEVENINGSTAR_Lookback(penetration); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDLEVENINGSTAR returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDLEVENINGSTAR( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - penetration, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDLEVENINGSTAR"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDLEVENINGSTAR returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDLGAPSIDESIDEWHITE.c b/src/ta_CDLGAPSIDESIDEWHITE.c deleted file mode 100644 index eaceff14a..000000000 --- a/src/ta_CDLGAPSIDESIDEWHITE.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_CDLGAPSIDESIDEWHITE.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDLGAPSIDESIDEWHITE" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDLGAPSIDESIDEWHITE.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDLGAPSIDESIDEWHITE( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDLGAPSIDESIDEWHITE_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDLGAPSIDESIDEWHITE returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDLGAPSIDESIDEWHITE( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDLGAPSIDESIDEWHITE"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDLGAPSIDESIDEWHITE returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDLGRAVESTONEDOJI.c b/src/ta_CDLGRAVESTONEDOJI.c deleted file mode 100644 index fb73cf388..000000000 --- a/src/ta_CDLGRAVESTONEDOJI.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_CDLGRAVESTONEDOJI.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDLGRAVESTONEDOJI" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDLGRAVESTONEDOJI.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDLGRAVESTONEDOJI( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDLGRAVESTONEDOJI_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDLGRAVESTONEDOJI returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDLGRAVESTONEDOJI( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDLGRAVESTONEDOJI"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDLGRAVESTONEDOJI returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDLHAMMER.c b/src/ta_CDLHAMMER.c deleted file mode 100644 index 6f8ceba46..000000000 --- a/src/ta_CDLHAMMER.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_CDLHAMMER.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDLHAMMER" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDLHAMMER.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDLHAMMER( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDLHAMMER_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDLHAMMER returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDLHAMMER( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDLHAMMER"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDLHAMMER returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDLHANGINGMAN.c b/src/ta_CDLHANGINGMAN.c deleted file mode 100644 index 87eea059c..000000000 --- a/src/ta_CDLHANGINGMAN.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_CDLHANGINGMAN.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDLHANGINGMAN" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDLHANGINGMAN.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDLHANGINGMAN( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDLHANGINGMAN_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDLHANGINGMAN returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDLHANGINGMAN( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDLHANGINGMAN"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDLHANGINGMAN returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDLHARAMI.c b/src/ta_CDLHARAMI.c deleted file mode 100644 index 60ed602c2..000000000 --- a/src/ta_CDLHARAMI.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_CDLHARAMI.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDLHARAMI" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDLHARAMI.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDLHARAMI( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDLHARAMI_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDLHARAMI returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDLHARAMI( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDLHARAMI"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDLHARAMI returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDLHARAMICROSS.c b/src/ta_CDLHARAMICROSS.c deleted file mode 100644 index e392cfbed..000000000 --- a/src/ta_CDLHARAMICROSS.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_CDLHARAMICROSS.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDLHARAMICROSS" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDLHARAMICROSS.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDLHARAMICROSS( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDLHARAMICROSS_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDLHARAMICROSS returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDLHARAMICROSS( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDLHARAMICROSS"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDLHARAMICROSS returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDLHIGHWAVE.c b/src/ta_CDLHIGHWAVE.c deleted file mode 100644 index 9d1b0de94..000000000 --- a/src/ta_CDLHIGHWAVE.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_CDLHIGHWAVE.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDLHIGHWAVE" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDLHIGHWAVE.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDLHIGHWAVE( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDLHIGHWAVE_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDLHIGHWAVE returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDLHIGHWAVE( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDLHIGHWAVE"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDLHIGHWAVE returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDLHIKKAKE.c b/src/ta_CDLHIKKAKE.c deleted file mode 100644 index 5f70a053a..000000000 --- a/src/ta_CDLHIKKAKE.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_CDLHIKKAKE.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDLHIKKAKE" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDLHIKKAKE.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDLHIKKAKE( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDLHIKKAKE_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDLHIKKAKE returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDLHIKKAKE( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDLHIKKAKE"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDLHIKKAKE returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDLHIKKAKEMOD.c b/src/ta_CDLHIKKAKEMOD.c deleted file mode 100644 index d1a721947..000000000 --- a/src/ta_CDLHIKKAKEMOD.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_CDLHIKKAKEMOD.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDLHIKKAKEMOD" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDLHIKKAKEMOD.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDLHIKKAKEMOD( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDLHIKKAKEMOD_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDLHIKKAKEMOD returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDLHIKKAKEMOD( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDLHIKKAKEMOD"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDLHIKKAKEMOD returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDLHOMINGPIGEON.c b/src/ta_CDLHOMINGPIGEON.c deleted file mode 100644 index b26f446de..000000000 --- a/src/ta_CDLHOMINGPIGEON.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_CDLHOMINGPIGEON.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDLHOMINGPIGEON" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDLHOMINGPIGEON.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDLHOMINGPIGEON( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDLHOMINGPIGEON_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDLHOMINGPIGEON returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDLHOMINGPIGEON( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDLHOMINGPIGEON"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDLHOMINGPIGEON returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDLIDENTICAL3CROWS.c b/src/ta_CDLIDENTICAL3CROWS.c deleted file mode 100644 index 97aa530de..000000000 --- a/src/ta_CDLIDENTICAL3CROWS.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_CDLIDENTICAL3CROWS.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDLIDENTICAL3CROWS" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDLIDENTICAL3CROWS.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDLIDENTICAL3CROWS( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDLIDENTICAL3CROWS_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDLIDENTICAL3CROWS returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDLIDENTICAL3CROWS( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDLIDENTICAL3CROWS"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDLIDENTICAL3CROWS returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDLINNECK.c b/src/ta_CDLINNECK.c deleted file mode 100644 index e248af245..000000000 --- a/src/ta_CDLINNECK.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_CDLINNECK.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDLINNECK" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDLINNECK.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDLINNECK( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDLINNECK_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDLINNECK returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDLINNECK( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDLINNECK"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDLINNECK returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDLINVERTEDHAMMER.c b/src/ta_CDLINVERTEDHAMMER.c deleted file mode 100644 index 66df11952..000000000 --- a/src/ta_CDLINVERTEDHAMMER.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_CDLINVERTEDHAMMER.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDLINVERTEDHAMMER" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDLINVERTEDHAMMER.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDLINVERTEDHAMMER( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDLINVERTEDHAMMER_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDLINVERTEDHAMMER returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDLINVERTEDHAMMER( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDLINVERTEDHAMMER"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDLINVERTEDHAMMER returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDLKICKING.c b/src/ta_CDLKICKING.c deleted file mode 100644 index 4bbad2514..000000000 --- a/src/ta_CDLKICKING.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_CDLKICKING.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDLKICKING" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDLKICKING.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDLKICKING( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDLKICKING_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDLKICKING returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDLKICKING( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDLKICKING"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDLKICKING returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDLKICKINGBYLENGTH.c b/src/ta_CDLKICKINGBYLENGTH.c deleted file mode 100644 index f5f6faf88..000000000 --- a/src/ta_CDLKICKINGBYLENGTH.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_CDLKICKINGBYLENGTH.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDLKICKINGBYLENGTH" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDLKICKINGBYLENGTH.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDLKICKINGBYLENGTH( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDLKICKINGBYLENGTH_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDLKICKINGBYLENGTH returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDLKICKINGBYLENGTH( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDLKICKINGBYLENGTH"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDLKICKINGBYLENGTH returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDLLADDERBOTTOM.c b/src/ta_CDLLADDERBOTTOM.c deleted file mode 100644 index 81b29ae46..000000000 --- a/src/ta_CDLLADDERBOTTOM.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_CDLLADDERBOTTOM.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDLLADDERBOTTOM" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDLLADDERBOTTOM.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDLLADDERBOTTOM( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDLLADDERBOTTOM_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDLLADDERBOTTOM returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDLLADDERBOTTOM( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDLLADDERBOTTOM"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDLLADDERBOTTOM returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDLLONGLEGGEDDOJI.c b/src/ta_CDLLONGLEGGEDDOJI.c deleted file mode 100644 index c1920a94e..000000000 --- a/src/ta_CDLLONGLEGGEDDOJI.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_CDLLONGLEGGEDDOJI.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDLLONGLEGGEDDOJI" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDLLONGLEGGEDDOJI.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDLLONGLEGGEDDOJI( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDLLONGLEGGEDDOJI_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDLLONGLEGGEDDOJI returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDLLONGLEGGEDDOJI( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDLLONGLEGGEDDOJI"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDLLONGLEGGEDDOJI returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDLLONGLINE.c b/src/ta_CDLLONGLINE.c deleted file mode 100644 index 577a53aad..000000000 --- a/src/ta_CDLLONGLINE.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_CDLLONGLINE.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDLLONGLINE" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDLLONGLINE.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDLLONGLINE( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDLLONGLINE_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDLLONGLINE returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDLLONGLINE( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDLLONGLINE"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDLLONGLINE returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDLMARUBOZU.c b/src/ta_CDLMARUBOZU.c deleted file mode 100644 index 846bbf2dd..000000000 --- a/src/ta_CDLMARUBOZU.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_CDLMARUBOZU.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDLMARUBOZU" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDLMARUBOZU.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDLMARUBOZU( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDLMARUBOZU_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDLMARUBOZU returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDLMARUBOZU( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDLMARUBOZU"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDLMARUBOZU returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDLMATCHINGLOW.c b/src/ta_CDLMATCHINGLOW.c deleted file mode 100644 index 12cb8ff39..000000000 --- a/src/ta_CDLMATCHINGLOW.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_CDLMATCHINGLOW.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDLMATCHINGLOW" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDLMATCHINGLOW.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDLMATCHINGLOW( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDLMATCHINGLOW_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDLMATCHINGLOW returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDLMATCHINGLOW( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDLMATCHINGLOW"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDLMATCHINGLOW returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDLMATHOLD.c b/src/ta_CDLMATHOLD.c deleted file mode 100644 index 7332f3f2c..000000000 --- a/src/ta_CDLMATHOLD.c +++ /dev/null @@ -1,152 +0,0 @@ -// interface to ta_CDLMATHOLD.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// double optInPenetration -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDLMATHOLD" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDLMATHOLD.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDLMATHOLD( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP optInPenetration, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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]; - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDLMATHOLD_Lookback(penetration); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDLMATHOLD returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDLMATHOLD( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - penetration, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDLMATHOLD"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDLMATHOLD returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDLMORNINGDOJISTAR.c b/src/ta_CDLMORNINGDOJISTAR.c deleted file mode 100644 index dc6217651..000000000 --- a/src/ta_CDLMORNINGDOJISTAR.c +++ /dev/null @@ -1,152 +0,0 @@ -// interface to ta_CDLMORNINGDOJISTAR.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// double optInPenetration -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDLMORNINGDOJISTAR" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDLMORNINGDOJISTAR.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDLMORNINGDOJISTAR( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP optInPenetration, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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]; - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDLMORNINGDOJISTAR_Lookback(penetration); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDLMORNINGDOJISTAR returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDLMORNINGDOJISTAR( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - penetration, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDLMORNINGDOJISTAR"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDLMORNINGDOJISTAR returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDLMORNINGSTAR.c b/src/ta_CDLMORNINGSTAR.c deleted file mode 100644 index e08d38953..000000000 --- a/src/ta_CDLMORNINGSTAR.c +++ /dev/null @@ -1,152 +0,0 @@ -// interface to ta_CDLMORNINGSTAR.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// double optInPenetration -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDLMORNINGSTAR" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDLMORNINGSTAR.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDLMORNINGSTAR( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP optInPenetration, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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]; - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDLMORNINGSTAR_Lookback(penetration); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDLMORNINGSTAR returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDLMORNINGSTAR( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - penetration, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDLMORNINGSTAR"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDLMORNINGSTAR returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDLONNECK.c b/src/ta_CDLONNECK.c deleted file mode 100644 index 3788cd921..000000000 --- a/src/ta_CDLONNECK.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_CDLONNECK.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDLONNECK" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDLONNECK.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDLONNECK( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDLONNECK_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDLONNECK returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDLONNECK( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDLONNECK"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDLONNECK returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDLPIERCING.c b/src/ta_CDLPIERCING.c deleted file mode 100644 index 8a8c150fa..000000000 --- a/src/ta_CDLPIERCING.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_CDLPIERCING.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDLPIERCING" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDLPIERCING.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDLPIERCING( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDLPIERCING_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDLPIERCING returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDLPIERCING( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDLPIERCING"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDLPIERCING returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDLRICKSHAWMAN.c b/src/ta_CDLRICKSHAWMAN.c deleted file mode 100644 index de0c14010..000000000 --- a/src/ta_CDLRICKSHAWMAN.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_CDLRICKSHAWMAN.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDLRICKSHAWMAN" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDLRICKSHAWMAN.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDLRICKSHAWMAN( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDLRICKSHAWMAN_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDLRICKSHAWMAN returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDLRICKSHAWMAN( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDLRICKSHAWMAN"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDLRICKSHAWMAN returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDLRISEFALL3METHODS.c b/src/ta_CDLRISEFALL3METHODS.c deleted file mode 100644 index 7fdce1d58..000000000 --- a/src/ta_CDLRISEFALL3METHODS.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_CDLRISEFALL3METHODS.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDLRISEFALL3METHODS" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDLRISEFALL3METHODS.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDLRISEFALL3METHODS( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDLRISEFALL3METHODS_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDLRISEFALL3METHODS returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDLRISEFALL3METHODS( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDLRISEFALL3METHODS"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDLRISEFALL3METHODS returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDLSEPARATINGLINES.c b/src/ta_CDLSEPARATINGLINES.c deleted file mode 100644 index 57d3820b6..000000000 --- a/src/ta_CDLSEPARATINGLINES.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_CDLSEPARATINGLINES.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDLSEPARATINGLINES" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDLSEPARATINGLINES.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDLSEPARATINGLINES( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDLSEPARATINGLINES_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDLSEPARATINGLINES returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDLSEPARATINGLINES( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDLSEPARATINGLINES"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDLSEPARATINGLINES returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDLSHOOTINGSTAR.c b/src/ta_CDLSHOOTINGSTAR.c deleted file mode 100644 index 9affb530f..000000000 --- a/src/ta_CDLSHOOTINGSTAR.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_CDLSHOOTINGSTAR.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDLSHOOTINGSTAR" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDLSHOOTINGSTAR.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDLSHOOTINGSTAR( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDLSHOOTINGSTAR_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDLSHOOTINGSTAR returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDLSHOOTINGSTAR( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDLSHOOTINGSTAR"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDLSHOOTINGSTAR returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDLSHORTLINE.c b/src/ta_CDLSHORTLINE.c deleted file mode 100644 index a3e6f8259..000000000 --- a/src/ta_CDLSHORTLINE.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_CDLSHORTLINE.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDLSHORTLINE" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDLSHORTLINE.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDLSHORTLINE( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDLSHORTLINE_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDLSHORTLINE returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDLSHORTLINE( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDLSHORTLINE"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDLSHORTLINE returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDLSPINNINGTOP.c b/src/ta_CDLSPINNINGTOP.c deleted file mode 100644 index 174122fee..000000000 --- a/src/ta_CDLSPINNINGTOP.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_CDLSPINNINGTOP.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDLSPINNINGTOP" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDLSPINNINGTOP.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDLSPINNINGTOP( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDLSPINNINGTOP_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDLSPINNINGTOP returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDLSPINNINGTOP( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDLSPINNINGTOP"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDLSPINNINGTOP returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDLSTALLEDPATTERN.c b/src/ta_CDLSTALLEDPATTERN.c deleted file mode 100644 index 1f1932dfe..000000000 --- a/src/ta_CDLSTALLEDPATTERN.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_CDLSTALLEDPATTERN.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDLSTALLEDPATTERN" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDLSTALLEDPATTERN.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDLSTALLEDPATTERN( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDLSTALLEDPATTERN_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDLSTALLEDPATTERN returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDLSTALLEDPATTERN( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDLSTALLEDPATTERN"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDLSTALLEDPATTERN returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDLSTICKSANDWICH.c b/src/ta_CDLSTICKSANDWICH.c deleted file mode 100644 index bfbf8faf3..000000000 --- a/src/ta_CDLSTICKSANDWICH.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_CDLSTICKSANDWICH.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDLSTICKSANDWICH" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDLSTICKSANDWICH.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDLSTICKSANDWICH( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDLSTICKSANDWICH_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDLSTICKSANDWICH returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDLSTICKSANDWICH( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDLSTICKSANDWICH"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDLSTICKSANDWICH returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDLTAKURI.c b/src/ta_CDLTAKURI.c deleted file mode 100644 index bbc4b4063..000000000 --- a/src/ta_CDLTAKURI.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_CDLTAKURI.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDLTAKURI" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDLTAKURI.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDLTAKURI( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDLTAKURI_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDLTAKURI returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDLTAKURI( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDLTAKURI"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDLTAKURI returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDLTASUKIGAP.c b/src/ta_CDLTASUKIGAP.c deleted file mode 100644 index b4f3a7f0b..000000000 --- a/src/ta_CDLTASUKIGAP.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_CDLTASUKIGAP.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDLTASUKIGAP" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDLTASUKIGAP.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDLTASUKIGAP( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDLTASUKIGAP_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDLTASUKIGAP returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDLTASUKIGAP( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDLTASUKIGAP"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDLTASUKIGAP returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDLTHRUSTING.c b/src/ta_CDLTHRUSTING.c deleted file mode 100644 index 1518ce8e9..000000000 --- a/src/ta_CDLTHRUSTING.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_CDLTHRUSTING.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDLTHRUSTING" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDLTHRUSTING.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDLTHRUSTING( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDLTHRUSTING_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDLTHRUSTING returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDLTHRUSTING( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDLTHRUSTING"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDLTHRUSTING returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDLTRISTAR.c b/src/ta_CDLTRISTAR.c deleted file mode 100644 index 974f9b78a..000000000 --- a/src/ta_CDLTRISTAR.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_CDLTRISTAR.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDLTRISTAR" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDLTRISTAR.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDLTRISTAR( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDLTRISTAR_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDLTRISTAR returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDLTRISTAR( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDLTRISTAR"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDLTRISTAR returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDLUNIQUE3RIVER.c b/src/ta_CDLUNIQUE3RIVER.c deleted file mode 100644 index d48f92206..000000000 --- a/src/ta_CDLUNIQUE3RIVER.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_CDLUNIQUE3RIVER.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDLUNIQUE3RIVER" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDLUNIQUE3RIVER.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDLUNIQUE3RIVER( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDLUNIQUE3RIVER_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDLUNIQUE3RIVER returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDLUNIQUE3RIVER( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDLUNIQUE3RIVER"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDLUNIQUE3RIVER returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDLUPSIDEGAP2CROWS.c b/src/ta_CDLUPSIDEGAP2CROWS.c deleted file mode 100644 index 1fa4e148c..000000000 --- a/src/ta_CDLUPSIDEGAP2CROWS.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_CDLUPSIDEGAP2CROWS.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDLUPSIDEGAP2CROWS" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDLUPSIDEGAP2CROWS.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDLUPSIDEGAP2CROWS( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDLUPSIDEGAP2CROWS_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDLUPSIDEGAP2CROWS returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDLUPSIDEGAP2CROWS( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDLUPSIDEGAP2CROWS"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDLUPSIDEGAP2CROWS returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CDLXSIDEGAP3METHODS.c b/src/ta_CDLXSIDEGAP3METHODS.c deleted file mode 100644 index 0b988b8f6..000000000 --- a/src/ta_CDLXSIDEGAP3METHODS.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_CDLXSIDEGAP3METHODS.c -// -// Parameters -// double inOpen -// double inClose -// double inLow -// double inClose -// bool flag -// -// Returns -// matrix (n x 1) with colum: -// "CDLXSIDEGAP3METHODS" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CDLXSIDEGAP3METHODS.c -// -#include "Rinternals.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "normalize.h" -#include "shift.h" -#include - -// clang-format off -SEXP impl_ta_CDLXSIDEGAP3METHODS( - SEXP inOpen, - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP flag, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {open_ptr, high_ptr, low_ptr, close_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - open_ptr = na_arrays[0]; - high_ptr = na_arrays[1]; - low_ptr = na_arrays[2]; - close_ptr = na_arrays[3]; - } else { - na_mask = NULL; - } - } - - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CDLXSIDEGAP3METHODS_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - // TA_CDLXSIDEGAP3METHODS returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CDLXSIDEGAP3METHODS( - 0, - n - 1, - open_ptr, - high_ptr, - low_ptr, - close_ptr, - &start_idx, - &end_idx, - output_ptr); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(output_ptr, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CDLXSIDEGAP3METHODS"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - // ta_CDLXSIDEGAP3METHODS returns values in the range [-200, 200] - // if flag is TRUE the output is converted from INTSXP - // to REALSXP and divided by 100, preserving pattern strength - // see normalize.h for more details - if (LOGICAL_ELT(flag, 0)) { - output = normalize_int_to_real( - output, - 100.0, - (na_mask != NULL), - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CMO.c b/src/ta_CMO.c deleted file mode 100644 index c1dc4969d..000000000 --- a/src/ta_CMO.c +++ /dev/null @@ -1,131 +0,0 @@ -// interface to ta_CMO.c -// -// Parameters -// double inReal -// integer optInTimePeriod -// -// Returns -// matrix (n x 1) with colum: -// "CMO" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CMO.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_CMO( - SEXP inReal, - SEXP optInTimePeriod, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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]; - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inReal_ptr}; - n = build_na_mask(na_mask, n, 1, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 1, na_mask, n_original, n); - inReal_ptr = na_arrays[0]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CMO_Lookback(optInTimePeriod_value); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *real = output_ptr; - - // TA_CMO returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CMO( - 0, - n - 1, - inReal_ptr, - optInTimePeriod_value, - &start_idx, - &end_idx, - real); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(real, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CMO"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_CORREL.c b/src/ta_CORREL.c deleted file mode 100644 index 08476beeb..000000000 --- a/src/ta_CORREL.c +++ /dev/null @@ -1,136 +0,0 @@ -// interface to ta_CORREL.c -// -// Parameters -// double inReal0 -// double inReal1 -// integer optInTimePeriod -// -// Returns -// matrix (n x 1) with colum: -// "CORREL" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_CORREL.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_CORREL( - SEXP inReal0, - SEXP inReal1, - SEXP optInTimePeriod, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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]; - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inReal0_ptr, inReal1_ptr}; - n = build_na_mask(na_mask, n, 2, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 2, na_mask, n_original, n); - inReal0_ptr = na_arrays[0]; - inReal1_ptr = na_arrays[1]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_CORREL_Lookback(optInTimePeriod_value); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *real = output_ptr; - - // TA_CORREL returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_CORREL( - 0, - n - 1, - inReal0_ptr, - inReal1_ptr, - optInTimePeriod_value, - &start_idx, - &end_idx, - real); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(real, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "CORREL"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_DEMA.c b/src/ta_DEMA.c deleted file mode 100644 index b56cd536f..000000000 --- a/src/ta_DEMA.c +++ /dev/null @@ -1,131 +0,0 @@ -// interface to ta_DEMA.c -// -// Parameters -// double inReal -// integer optInTimePeriod -// -// Returns -// matrix (n x 1) with colum: -// "DEMA" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_DEMA.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_DEMA( - SEXP inReal, - SEXP optInTimePeriod, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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]; - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inReal_ptr}; - n = build_na_mask(na_mask, n, 1, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 1, na_mask, n_original, n); - inReal_ptr = na_arrays[0]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_DEMA_Lookback(optInTimePeriod_value); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *real = output_ptr; - - // TA_DEMA returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_DEMA( - 0, - n - 1, - inReal_ptr, - optInTimePeriod_value, - &start_idx, - &end_idx, - real); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(real, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "DEMA"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_DX.c b/src/ta_DX.c deleted file mode 100644 index a031498b1..000000000 --- a/src/ta_DX.c +++ /dev/null @@ -1,141 +0,0 @@ -// interface to ta_DX.c -// -// Parameters -// double inHigh -// double inLow -// double inClose -// integer optInTimePeriod -// -// Returns -// matrix (n x 1) with colum: -// "DX" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_DX.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_DX( - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP optInTimePeriod, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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]; - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inHigh_ptr, inLow_ptr, inClose_ptr}; - n = build_na_mask(na_mask, n, 3, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 3, na_mask, n_original, n); - inHigh_ptr = na_arrays[0]; - inLow_ptr = na_arrays[1]; - inClose_ptr = na_arrays[2]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_DX_Lookback(optInTimePeriod_value); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *real = output_ptr; - - // TA_DX returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_DX( - 0, - n - 1, - inHigh_ptr, - inLow_ptr, - inClose_ptr, - optInTimePeriod_value, - &start_idx, - &end_idx, - real); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(real, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "DX"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_EMA.c b/src/ta_EMA.c deleted file mode 100644 index 02067a543..000000000 --- a/src/ta_EMA.c +++ /dev/null @@ -1,131 +0,0 @@ -// interface to ta_EMA.c -// -// Parameters -// double inReal -// integer optInTimePeriod -// -// Returns -// matrix (n x 1) with colum: -// "EMA" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_EMA.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_EMA( - SEXP inReal, - SEXP optInTimePeriod, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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]; - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inReal_ptr}; - n = build_na_mask(na_mask, n, 1, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 1, na_mask, n_original, n); - inReal_ptr = na_arrays[0]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_EMA_Lookback(optInTimePeriod_value); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *real = output_ptr; - - // TA_EMA returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_EMA( - 0, - n - 1, - inReal_ptr, - optInTimePeriod_value, - &start_idx, - &end_idx, - real); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(real, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "EMA"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_HT_DCPERIOD.c b/src/ta_HT_DCPERIOD.c deleted file mode 100644 index 3d72afc46..000000000 --- a/src/ta_HT_DCPERIOD.c +++ /dev/null @@ -1,120 +0,0 @@ -// interface to ta_HT_DCPERIOD.c -// -// Parameters -// double inReal -// -// Returns -// matrix (n x 1) with colum: -// "HT_DCPERIOD" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_HT_DCPERIOD.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_HT_DCPERIOD( - SEXP inReal, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // get length of 'inReal' (assumes equal length across input) - int n = LENGTH(inReal); - - // pointers to input arrays - const double *inReal_ptr = REAL(inReal); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inReal_ptr}; - n = build_na_mask(na_mask, n, 1, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 1, na_mask, n_original, n); - inReal_ptr = na_arrays[0]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_HT_DCPERIOD_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *real = output_ptr; - - // TA_HT_DCPERIOD returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = - TA_HT_DCPERIOD(0, n - 1, inReal_ptr, &start_idx, &end_idx, real); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(real, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "HT_DCPERIOD"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_HT_DCPHASE.c b/src/ta_HT_DCPHASE.c deleted file mode 100644 index a05c7abd0..000000000 --- a/src/ta_HT_DCPHASE.c +++ /dev/null @@ -1,120 +0,0 @@ -// interface to ta_HT_DCPHASE.c -// -// Parameters -// double inReal -// -// Returns -// matrix (n x 1) with colum: -// "HT_DCPHASE" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_HT_DCPHASE.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_HT_DCPHASE( - SEXP inReal, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // get length of 'inReal' (assumes equal length across input) - int n = LENGTH(inReal); - - // pointers to input arrays - const double *inReal_ptr = REAL(inReal); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inReal_ptr}; - n = build_na_mask(na_mask, n, 1, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 1, na_mask, n_original, n); - inReal_ptr = na_arrays[0]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_HT_DCPHASE_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *real = output_ptr; - - // TA_HT_DCPHASE returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = - TA_HT_DCPHASE(0, n - 1, inReal_ptr, &start_idx, &end_idx, real); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(real, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "HT_DCPHASE"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_HT_PHASOR.c b/src/ta_HT_PHASOR.c deleted file mode 100644 index 2d73a4854..000000000 --- a/src/ta_HT_PHASOR.c +++ /dev/null @@ -1,128 +0,0 @@ -// interface to ta_HT_PHASOR.c -// -// Parameters -// double inReal -// -// Returns -// matrix (n x 2) with colum: -// "InPhase", "Quadrature" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_HT_PHASOR.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_HT_PHASOR( - SEXP inReal, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // get length of 'inReal' (assumes equal length across input) - int n = LENGTH(inReal); - - // pointers to input arrays - const double *inReal_ptr = REAL(inReal); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inReal_ptr}; - n = build_na_mask(na_mask, n, 1, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 1, na_mask, n_original, n); - inReal_ptr = na_arrays[0]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_HT_PHASOR_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 2, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *inphase = output_ptr; - double *quadrature = output_ptr + 1 * n; - - // TA_HT_PHASOR returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_HT_PHASOR( - 0, - n - 1, - inReal_ptr, - &start_idx, - &end_idx, - inphase, - quadrature); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(inphase, n, start_idx); - shift_array(quadrature, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "InPhase", "Quadrature"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_HT_SINE.c b/src/ta_HT_SINE.c deleted file mode 100644 index fe50ba65c..000000000 --- a/src/ta_HT_SINE.c +++ /dev/null @@ -1,122 +0,0 @@ -// interface to ta_HT_SINE.c -// -// Parameters -// double inReal -// -// Returns -// matrix (n x 2) with colum: -// "Sine", "LeadSine" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_HT_SINE.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_HT_SINE( - SEXP inReal, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // get length of 'inReal' (assumes equal length across input) - int n = LENGTH(inReal); - - // pointers to input arrays - const double *inReal_ptr = REAL(inReal); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inReal_ptr}; - n = build_na_mask(na_mask, n, 1, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 1, na_mask, n_original, n); - inReal_ptr = na_arrays[0]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_HT_SINE_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 2, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *sine = output_ptr; - double *leadsine = output_ptr + 1 * n; - - // TA_HT_SINE returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = - TA_HT_SINE(0, n - 1, inReal_ptr, &start_idx, &end_idx, sine, leadsine); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(sine, n, start_idx); - shift_array(leadsine, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "Sine", "LeadSine"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_HT_TRENDLINE.c b/src/ta_HT_TRENDLINE.c deleted file mode 100644 index 3a05c0f38..000000000 --- a/src/ta_HT_TRENDLINE.c +++ /dev/null @@ -1,120 +0,0 @@ -// interface to ta_HT_TRENDLINE.c -// -// Parameters -// double inReal -// -// Returns -// matrix (n x 1) with colum: -// "HT_TRENDLINE" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_HT_TRENDLINE.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_HT_TRENDLINE( - SEXP inReal, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // get length of 'inReal' (assumes equal length across input) - int n = LENGTH(inReal); - - // pointers to input arrays - const double *inReal_ptr = REAL(inReal); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inReal_ptr}; - n = build_na_mask(na_mask, n, 1, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 1, na_mask, n_original, n); - inReal_ptr = na_arrays[0]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_HT_TRENDLINE_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *real = output_ptr; - - // TA_HT_TRENDLINE returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = - TA_HT_TRENDLINE(0, n - 1, inReal_ptr, &start_idx, &end_idx, real); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(real, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "HT_TRENDLINE"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_HT_TRENDMODE.c b/src/ta_HT_TRENDMODE.c deleted file mode 100644 index 62eaa65cf..000000000 --- a/src/ta_HT_TRENDMODE.c +++ /dev/null @@ -1,120 +0,0 @@ -// interface to ta_HT_TRENDMODE.c -// -// Parameters -// double inReal -// -// Returns -// matrix (n x 1) with colum: -// "HT_TRENDMODE" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_HT_TRENDMODE.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_HT_TRENDMODE( - SEXP inReal, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // get length of 'inReal' (assumes equal length across input) - int n = LENGTH(inReal); - - // pointers to input arrays - const double *inReal_ptr = REAL(inReal); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inReal_ptr}; - n = build_na_mask(na_mask, n, 1, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 1, na_mask, n_original, n); - inReal_ptr = na_arrays[0]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - int *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_HT_TRENDMODE_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - int *integer = output_ptr; - - // TA_HT_TRENDMODE returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = - TA_HT_TRENDMODE(0, n - 1, inReal_ptr, &start_idx, &end_idx, integer); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(integer, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "HT_TRENDMODE"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_IMI.c b/src/ta_IMI.c deleted file mode 100644 index 10eff2938..000000000 --- a/src/ta_IMI.c +++ /dev/null @@ -1,136 +0,0 @@ -// interface to ta_IMI.c -// -// Parameters -// double inOpen -// double inClose -// integer optInTimePeriod -// -// Returns -// matrix (n x 1) with colum: -// "IMI" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_IMI.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_IMI( - SEXP inOpen, - SEXP inClose, - SEXP optInTimePeriod, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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]; - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inOpen_ptr, inClose_ptr}; - n = build_na_mask(na_mask, n, 2, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 2, na_mask, n_original, n); - inOpen_ptr = na_arrays[0]; - inClose_ptr = na_arrays[1]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_IMI_Lookback(optInTimePeriod_value); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *real = output_ptr; - - // TA_IMI returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_IMI( - 0, - n - 1, - inOpen_ptr, - inClose_ptr, - optInTimePeriod_value, - &start_idx, - &end_idx, - real); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(real, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "IMI"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_KAMA.c b/src/ta_KAMA.c deleted file mode 100644 index bc7ce4716..000000000 --- a/src/ta_KAMA.c +++ /dev/null @@ -1,131 +0,0 @@ -// interface to ta_KAMA.c -// -// Parameters -// double inReal -// integer optInTimePeriod -// -// Returns -// matrix (n x 1) with colum: -// "KAMA" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_KAMA.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_KAMA( - SEXP inReal, - SEXP optInTimePeriod, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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]; - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inReal_ptr}; - n = build_na_mask(na_mask, n, 1, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 1, na_mask, n_original, n); - inReal_ptr = na_arrays[0]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_KAMA_Lookback(optInTimePeriod_value); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *real = output_ptr; - - // TA_KAMA returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_KAMA( - 0, - n - 1, - inReal_ptr, - optInTimePeriod_value, - &start_idx, - &end_idx, - real); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(real, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "KAMA"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_MACD.c b/src/ta_MACD.c deleted file mode 100644 index df86ecc44..000000000 --- a/src/ta_MACD.c +++ /dev/null @@ -1,148 +0,0 @@ -// interface to ta_MACD.c -// -// Parameters -// double inReal -// integer optInFastPeriod -// integer optInSlowPeriod -// integer optInSignalPeriod -// -// Returns -// matrix (n x 3) with colum: -// "MACD", "MACDSignal", "MACDHist" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_MACD.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_MACD( - SEXP inReal, - SEXP optInFastPeriod, - SEXP optInSlowPeriod, - SEXP optInSignalPeriod, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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]; - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inReal_ptr}; - n = build_na_mask(na_mask, n, 1, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 1, na_mask, n_original, n); - inReal_ptr = na_arrays[0]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_MACD_Lookback( - optInFastPeriod_value, - optInSlowPeriod_value, - optInSignalPeriod_value); - - // 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 - const int proceed = - output_container(n, lookback, 3, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *macd = output_ptr; - double *macdsignal = output_ptr + 1 * n; - double *macdhist = output_ptr + 2 * n; - - // TA_MACD returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_MACD( - 0, - n - 1, - inReal_ptr, - optInFastPeriod_value, - optInSlowPeriod_value, - optInSignalPeriod_value, - &start_idx, - &end_idx, - macd, - macdsignal, - macdhist); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(macd, n, start_idx); - shift_array(macdsignal, n, start_idx); - shift_array(macdhist, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "MACD", "MACDSignal", "MACDHist"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_MACDEXT.c b/src/ta_MACDEXT.c deleted file mode 100644 index 275176b6f..000000000 --- a/src/ta_MACDEXT.c +++ /dev/null @@ -1,163 +0,0 @@ -// interface to ta_MACDEXT.c -// -// Parameters -// double inReal -// integer optInFastPeriod -// integer optInFastMAType (MAType) -// integer optInSlowPeriod -// integer optInSlowMAType (MAType) -// integer optInSignalPeriod -// integer optInSignalMAType (MAType) -// -// Returns -// matrix (n x 3) with colum: -// "MACD", "MACDSignal", "MACDHist" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_MACDEXT.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_MACDEXT( - SEXP inReal, - SEXP optInFastPeriod, - SEXP optInFastMAType, - SEXP optInSlowPeriod, - SEXP optInSlowMAType, - SEXP optInSignalPeriod, - SEXP optInSignalMAType, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inReal_ptr}; - n = build_na_mask(na_mask, n, 1, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 1, na_mask, n_original, n); - inReal_ptr = na_arrays[0]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_MACDEXT_Lookback( - optInFastPeriod_value, - optInFastMAType_value, - optInSlowPeriod_value, - optInSlowMAType_value, - optInSignalPeriod_value, - optInSignalMAType_value); - - // 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 - const int proceed = - output_container(n, lookback, 3, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *macd = output_ptr; - double *macdsignal = output_ptr + 1 * n; - double *macdhist = output_ptr + 2 * n; - - // TA_MACDEXT returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_MACDEXT( - 0, - n - 1, - inReal_ptr, - optInFastPeriod_value, - optInFastMAType_value, - optInSlowPeriod_value, - optInSlowMAType_value, - optInSignalPeriod_value, - optInSignalMAType_value, - &start_idx, - &end_idx, - macd, - macdsignal, - macdhist); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(macd, n, start_idx); - shift_array(macdsignal, n, start_idx); - shift_array(macdhist, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "MACD", "MACDSignal", "MACDHist"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_MACDFIX.c b/src/ta_MACDFIX.c deleted file mode 100644 index f34ce64b0..000000000 --- a/src/ta_MACDFIX.c +++ /dev/null @@ -1,137 +0,0 @@ -// interface to ta_MACDFIX.c -// -// Parameters -// double inReal -// integer optInSignalPeriod -// -// Returns -// matrix (n x 3) with colum: -// "MACD", "MACDSignal", "MACDHist" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_MACDFIX.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_MACDFIX( - SEXP inReal, - SEXP optInSignalPeriod, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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]; - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inReal_ptr}; - n = build_na_mask(na_mask, n, 1, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 1, na_mask, n_original, n); - inReal_ptr = na_arrays[0]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_MACDFIX_Lookback(optInSignalPeriod_value); - - // 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 - const int proceed = - output_container(n, lookback, 3, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *macd = output_ptr; - double *macdsignal = output_ptr + 1 * n; - double *macdhist = output_ptr + 2 * n; - - // TA_MACDFIX returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_MACDFIX( - 0, - n - 1, - inReal_ptr, - optInSignalPeriod_value, - &start_idx, - &end_idx, - macd, - macdsignal, - macdhist); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(macd, n, start_idx); - shift_array(macdsignal, n, start_idx); - shift_array(macdhist, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "MACD", "MACDSignal", "MACDHist"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_MAMA.c b/src/ta_MAMA.c deleted file mode 100644 index e8011f613..000000000 --- a/src/ta_MAMA.c +++ /dev/null @@ -1,139 +0,0 @@ -// interface to ta_MAMA.c -// -// Parameters -// double inReal -// double optInFastLimit -// double optInSlowLimit -// -// Returns -// matrix (n x 2) with colum: -// "MAMA", "FAMA" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_MAMA.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_MAMA( - SEXP inReal, - SEXP optInFastLimit, - SEXP optInSlowLimit, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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]; - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inReal_ptr}; - n = build_na_mask(na_mask, n, 1, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 1, na_mask, n_original, n); - inReal_ptr = na_arrays[0]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = - TA_MAMA_Lookback(optInFastLimit_value, optInSlowLimit_value); - - // 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 - const int proceed = - output_container(n, lookback, 2, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *mama = output_ptr; - double *fama = output_ptr + 1 * n; - - // TA_MAMA returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_MAMA( - 0, - n - 1, - inReal_ptr, - optInFastLimit_value, - optInSlowLimit_value, - &start_idx, - &end_idx, - mama, - fama); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(mama, n, start_idx); - shift_array(fama, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "MAMA", "FAMA"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_MAX.c b/src/ta_MAX.c deleted file mode 100644 index 6ab70ef6d..000000000 --- a/src/ta_MAX.c +++ /dev/null @@ -1,131 +0,0 @@ -// interface to ta_MAX.c -// -// Parameters -// double inReal -// integer optInTimePeriod -// -// Returns -// matrix (n x 1) with colum: -// "MAX" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_MAX.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_MAX( - SEXP inReal, - SEXP optInTimePeriod, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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]; - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inReal_ptr}; - n = build_na_mask(na_mask, n, 1, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 1, na_mask, n_original, n); - inReal_ptr = na_arrays[0]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_MAX_Lookback(optInTimePeriod_value); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *real = output_ptr; - - // TA_MAX returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_MAX( - 0, - n - 1, - inReal_ptr, - optInTimePeriod_value, - &start_idx, - &end_idx, - real); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(real, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "MAX"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_MEDPRICE.c b/src/ta_MEDPRICE.c deleted file mode 100644 index 26f61945a..000000000 --- a/src/ta_MEDPRICE.c +++ /dev/null @@ -1,124 +0,0 @@ -// interface to ta_MEDPRICE.c -// -// Parameters -// double inHigh -// double inLow -// -// Returns -// matrix (n x 1) with colum: -// "MEDPRICE" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_MEDPRICE.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_MEDPRICE( - SEXP inHigh, - SEXP inLow, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inHigh_ptr, inLow_ptr}; - n = build_na_mask(na_mask, n, 2, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 2, na_mask, n_original, n); - inHigh_ptr = na_arrays[0]; - inLow_ptr = na_arrays[1]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_MEDPRICE_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *real = output_ptr; - - // TA_MEDPRICE returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = - TA_MEDPRICE(0, n - 1, inHigh_ptr, inLow_ptr, &start_idx, &end_idx, real); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(real, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "MEDPRICE"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_MFI.c b/src/ta_MFI.c deleted file mode 100644 index f5e102418..000000000 --- a/src/ta_MFI.c +++ /dev/null @@ -1,147 +0,0 @@ -// interface to ta_MFI.c -// -// Parameters -// double inHigh -// double inLow -// double inClose -// double inVolume -// integer optInTimePeriod -// -// Returns -// matrix (n x 1) with colum: -// "MFI" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_MFI.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_MFI( - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP inVolume, - SEXP optInTimePeriod, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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]; - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = - {inHigh_ptr, inLow_ptr, inClose_ptr, inVolume_ptr}; - n = build_na_mask(na_mask, n, 4, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 4, na_mask, n_original, n); - inHigh_ptr = na_arrays[0]; - inLow_ptr = na_arrays[1]; - inClose_ptr = na_arrays[2]; - inVolume_ptr = na_arrays[3]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_MFI_Lookback(optInTimePeriod_value); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *real = output_ptr; - - // TA_MFI returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_MFI( - 0, - n - 1, - inHigh_ptr, - inLow_ptr, - inClose_ptr, - inVolume_ptr, - optInTimePeriod_value, - &start_idx, - &end_idx, - real); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(real, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "MFI"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_MIDPRICE.c b/src/ta_MIDPRICE.c deleted file mode 100644 index defbb2caf..000000000 --- a/src/ta_MIDPRICE.c +++ /dev/null @@ -1,136 +0,0 @@ -// interface to ta_MIDPRICE.c -// -// Parameters -// double inHigh -// double inLow -// integer optInTimePeriod -// -// Returns -// matrix (n x 1) with colum: -// "MIDPRICE" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_MIDPRICE.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_MIDPRICE( - SEXP inHigh, - SEXP inLow, - SEXP optInTimePeriod, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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]; - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inHigh_ptr, inLow_ptr}; - n = build_na_mask(na_mask, n, 2, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 2, na_mask, n_original, n); - inHigh_ptr = na_arrays[0]; - inLow_ptr = na_arrays[1]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_MIDPRICE_Lookback(optInTimePeriod_value); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *real = output_ptr; - - // TA_MIDPRICE returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_MIDPRICE( - 0, - n - 1, - inHigh_ptr, - inLow_ptr, - optInTimePeriod_value, - &start_idx, - &end_idx, - real); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(real, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "MIDPRICE"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_MIN.c b/src/ta_MIN.c deleted file mode 100644 index 89a124f6b..000000000 --- a/src/ta_MIN.c +++ /dev/null @@ -1,131 +0,0 @@ -// interface to ta_MIN.c -// -// Parameters -// double inReal -// integer optInTimePeriod -// -// Returns -// matrix (n x 1) with colum: -// "MIN" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_MIN.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_MIN( - SEXP inReal, - SEXP optInTimePeriod, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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]; - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inReal_ptr}; - n = build_na_mask(na_mask, n, 1, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 1, na_mask, n_original, n); - inReal_ptr = na_arrays[0]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_MIN_Lookback(optInTimePeriod_value); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *real = output_ptr; - - // TA_MIN returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_MIN( - 0, - n - 1, - inReal_ptr, - optInTimePeriod_value, - &start_idx, - &end_idx, - real); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(real, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "MIN"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_MINUS_DI.c b/src/ta_MINUS_DI.c deleted file mode 100644 index ae883d4ad..000000000 --- a/src/ta_MINUS_DI.c +++ /dev/null @@ -1,141 +0,0 @@ -// interface to ta_MINUS_DI.c -// -// Parameters -// double inHigh -// double inLow -// double inClose -// integer optInTimePeriod -// -// Returns -// matrix (n x 1) with colum: -// "MINUS_DI" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_MINUS_DI.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_MINUS_DI( - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP optInTimePeriod, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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]; - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inHigh_ptr, inLow_ptr, inClose_ptr}; - n = build_na_mask(na_mask, n, 3, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 3, na_mask, n_original, n); - inHigh_ptr = na_arrays[0]; - inLow_ptr = na_arrays[1]; - inClose_ptr = na_arrays[2]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_MINUS_DI_Lookback(optInTimePeriod_value); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *real = output_ptr; - - // TA_MINUS_DI returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_MINUS_DI( - 0, - n - 1, - inHigh_ptr, - inLow_ptr, - inClose_ptr, - optInTimePeriod_value, - &start_idx, - &end_idx, - real); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(real, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "MINUS_DI"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_MINUS_DM.c b/src/ta_MINUS_DM.c deleted file mode 100644 index 29c65c0dc..000000000 --- a/src/ta_MINUS_DM.c +++ /dev/null @@ -1,136 +0,0 @@ -// interface to ta_MINUS_DM.c -// -// Parameters -// double inHigh -// double inLow -// integer optInTimePeriod -// -// Returns -// matrix (n x 1) with colum: -// "MINUS_DM" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_MINUS_DM.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_MINUS_DM( - SEXP inHigh, - SEXP inLow, - SEXP optInTimePeriod, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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]; - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inHigh_ptr, inLow_ptr}; - n = build_na_mask(na_mask, n, 2, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 2, na_mask, n_original, n); - inHigh_ptr = na_arrays[0]; - inLow_ptr = na_arrays[1]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_MINUS_DM_Lookback(optInTimePeriod_value); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *real = output_ptr; - - // TA_MINUS_DM returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_MINUS_DM( - 0, - n - 1, - inHigh_ptr, - inLow_ptr, - optInTimePeriod_value, - &start_idx, - &end_idx, - real); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(real, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "MINUS_DM"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_MOM.c b/src/ta_MOM.c deleted file mode 100644 index b381fb6ac..000000000 --- a/src/ta_MOM.c +++ /dev/null @@ -1,131 +0,0 @@ -// interface to ta_MOM.c -// -// Parameters -// double inReal -// integer optInTimePeriod -// -// Returns -// matrix (n x 1) with colum: -// "MOM" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_MOM.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_MOM( - SEXP inReal, - SEXP optInTimePeriod, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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]; - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inReal_ptr}; - n = build_na_mask(na_mask, n, 1, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 1, na_mask, n_original, n); - inReal_ptr = na_arrays[0]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_MOM_Lookback(optInTimePeriod_value); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *real = output_ptr; - - // TA_MOM returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_MOM( - 0, - n - 1, - inReal_ptr, - optInTimePeriod_value, - &start_idx, - &end_idx, - real); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(real, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "MOM"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_NATR.c b/src/ta_NATR.c deleted file mode 100644 index 776aa9842..000000000 --- a/src/ta_NATR.c +++ /dev/null @@ -1,141 +0,0 @@ -// interface to ta_NATR.c -// -// Parameters -// double inHigh -// double inLow -// double inClose -// integer optInTimePeriod -// -// Returns -// matrix (n x 1) with colum: -// "NATR" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_NATR.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_NATR( - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP optInTimePeriod, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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]; - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inHigh_ptr, inLow_ptr, inClose_ptr}; - n = build_na_mask(na_mask, n, 3, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 3, na_mask, n_original, n); - inHigh_ptr = na_arrays[0]; - inLow_ptr = na_arrays[1]; - inClose_ptr = na_arrays[2]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_NATR_Lookback(optInTimePeriod_value); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *real = output_ptr; - - // TA_NATR returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_NATR( - 0, - n - 1, - inHigh_ptr, - inLow_ptr, - inClose_ptr, - optInTimePeriod_value, - &start_idx, - &end_idx, - real); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(real, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "NATR"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_OBV.c b/src/ta_OBV.c deleted file mode 100644 index af8cc3778..000000000 --- a/src/ta_OBV.c +++ /dev/null @@ -1,124 +0,0 @@ -// interface to ta_OBV.c -// -// Parameters -// double inReal -// double inVolume -// -// Returns -// matrix (n x 1) with colum: -// "OBV" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_OBV.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_OBV( - SEXP inReal, - SEXP inVolume, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inReal_ptr, inVolume_ptr}; - n = build_na_mask(na_mask, n, 2, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 2, na_mask, n_original, n); - inReal_ptr = na_arrays[0]; - inVolume_ptr = na_arrays[1]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_OBV_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *real = output_ptr; - - // TA_OBV returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = - TA_OBV(0, n - 1, inReal_ptr, inVolume_ptr, &start_idx, &end_idx, real); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(real, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "OBV"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_PLUS_DI.c b/src/ta_PLUS_DI.c deleted file mode 100644 index ee1ebdd12..000000000 --- a/src/ta_PLUS_DI.c +++ /dev/null @@ -1,141 +0,0 @@ -// interface to ta_PLUS_DI.c -// -// Parameters -// double inHigh -// double inLow -// double inClose -// integer optInTimePeriod -// -// Returns -// matrix (n x 1) with colum: -// "PLUS_DI" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_PLUS_DI.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_PLUS_DI( - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP optInTimePeriod, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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]; - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inHigh_ptr, inLow_ptr, inClose_ptr}; - n = build_na_mask(na_mask, n, 3, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 3, na_mask, n_original, n); - inHigh_ptr = na_arrays[0]; - inLow_ptr = na_arrays[1]; - inClose_ptr = na_arrays[2]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_PLUS_DI_Lookback(optInTimePeriod_value); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *real = output_ptr; - - // TA_PLUS_DI returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_PLUS_DI( - 0, - n - 1, - inHigh_ptr, - inLow_ptr, - inClose_ptr, - optInTimePeriod_value, - &start_idx, - &end_idx, - real); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(real, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "PLUS_DI"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_PLUS_DM.c b/src/ta_PLUS_DM.c deleted file mode 100644 index 61bebf77c..000000000 --- a/src/ta_PLUS_DM.c +++ /dev/null @@ -1,136 +0,0 @@ -// interface to ta_PLUS_DM.c -// -// Parameters -// double inHigh -// double inLow -// integer optInTimePeriod -// -// Returns -// matrix (n x 1) with colum: -// "PLUS_DM" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_PLUS_DM.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_PLUS_DM( - SEXP inHigh, - SEXP inLow, - SEXP optInTimePeriod, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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]; - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inHigh_ptr, inLow_ptr}; - n = build_na_mask(na_mask, n, 2, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 2, na_mask, n_original, n); - inHigh_ptr = na_arrays[0]; - inLow_ptr = na_arrays[1]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_PLUS_DM_Lookback(optInTimePeriod_value); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *real = output_ptr; - - // TA_PLUS_DM returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_PLUS_DM( - 0, - n - 1, - inHigh_ptr, - inLow_ptr, - optInTimePeriod_value, - &start_idx, - &end_idx, - real); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(real, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "PLUS_DM"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_PPO.c b/src/ta_PPO.c deleted file mode 100644 index d4bee26ff..000000000 --- a/src/ta_PPO.c +++ /dev/null @@ -1,142 +0,0 @@ -// interface to ta_PPO.c -// -// Parameters -// double inReal -// integer optInFastPeriod -// integer optInSlowPeriod -// integer optInMAType (MAType) -// -// Returns -// matrix (n x 1) with colum: -// "PPO" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_PPO.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_PPO( - SEXP inReal, - SEXP optInFastPeriod, - SEXP optInSlowPeriod, - SEXP optInMAType, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inReal_ptr}; - n = build_na_mask(na_mask, n, 1, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 1, na_mask, n_original, n); - inReal_ptr = na_arrays[0]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_PPO_Lookback( - optInFastPeriod_value, - optInSlowPeriod_value, - optInMAType_value); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *real = output_ptr; - - // TA_PPO returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_PPO( - 0, - n - 1, - inReal_ptr, - optInFastPeriod_value, - optInSlowPeriod_value, - optInMAType_value, - &start_idx, - &end_idx, - real); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(real, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "PPO"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_ROC.c b/src/ta_ROC.c deleted file mode 100644 index 74e62e7eb..000000000 --- a/src/ta_ROC.c +++ /dev/null @@ -1,131 +0,0 @@ -// interface to ta_ROC.c -// -// Parameters -// double inReal -// integer optInTimePeriod -// -// Returns -// matrix (n x 1) with colum: -// "ROC" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_ROC.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_ROC( - SEXP inReal, - SEXP optInTimePeriod, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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]; - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inReal_ptr}; - n = build_na_mask(na_mask, n, 1, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 1, na_mask, n_original, n); - inReal_ptr = na_arrays[0]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_ROC_Lookback(optInTimePeriod_value); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *real = output_ptr; - - // TA_ROC returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_ROC( - 0, - n - 1, - inReal_ptr, - optInTimePeriod_value, - &start_idx, - &end_idx, - real); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(real, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "ROC"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_ROCR.c b/src/ta_ROCR.c deleted file mode 100644 index b6f4ac3dd..000000000 --- a/src/ta_ROCR.c +++ /dev/null @@ -1,131 +0,0 @@ -// interface to ta_ROCR.c -// -// Parameters -// double inReal -// integer optInTimePeriod -// -// Returns -// matrix (n x 1) with colum: -// "ROCR" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_ROCR.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_ROCR( - SEXP inReal, - SEXP optInTimePeriod, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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]; - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inReal_ptr}; - n = build_na_mask(na_mask, n, 1, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 1, na_mask, n_original, n); - inReal_ptr = na_arrays[0]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_ROCR_Lookback(optInTimePeriod_value); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *real = output_ptr; - - // TA_ROCR returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_ROCR( - 0, - n - 1, - inReal_ptr, - optInTimePeriod_value, - &start_idx, - &end_idx, - real); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(real, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "ROCR"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_RSI.c b/src/ta_RSI.c deleted file mode 100644 index 52f361838..000000000 --- a/src/ta_RSI.c +++ /dev/null @@ -1,131 +0,0 @@ -// interface to ta_RSI.c -// -// Parameters -// double inReal -// integer optInTimePeriod -// -// Returns -// matrix (n x 1) with colum: -// "RSI" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_RSI.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_RSI( - SEXP inReal, - SEXP optInTimePeriod, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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]; - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inReal_ptr}; - n = build_na_mask(na_mask, n, 1, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 1, na_mask, n_original, n); - inReal_ptr = na_arrays[0]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_RSI_Lookback(optInTimePeriod_value); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *real = output_ptr; - - // TA_RSI returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_RSI( - 0, - n - 1, - inReal_ptr, - optInTimePeriod_value, - &start_idx, - &end_idx, - real); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(real, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "RSI"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_SAR.c b/src/ta_SAR.c deleted file mode 100644 index db52561a3..000000000 --- a/src/ta_SAR.c +++ /dev/null @@ -1,141 +0,0 @@ -// interface to ta_SAR.c -// -// Parameters -// double inHigh -// double inLow -// double optInAcceleration -// double optInMaximum -// -// Returns -// matrix (n x 1) with colum: -// "SAR" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_SAR.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_SAR( - SEXP inHigh, - SEXP inLow, - SEXP optInAcceleration, - SEXP optInMaximum, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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]; - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inHigh_ptr, inLow_ptr}; - n = build_na_mask(na_mask, n, 2, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 2, na_mask, n_original, n); - inHigh_ptr = na_arrays[0]; - inLow_ptr = na_arrays[1]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = - TA_SAR_Lookback(optInAcceleration_value, optInMaximum_value); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *real = output_ptr; - - // TA_SAR returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_SAR( - 0, - n - 1, - inHigh_ptr, - inLow_ptr, - optInAcceleration_value, - optInMaximum_value, - &start_idx, - &end_idx, - real); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(real, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "SAR"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_SAREXT.c b/src/ta_SAREXT.c deleted file mode 100644 index d208e886c..000000000 --- a/src/ta_SAREXT.c +++ /dev/null @@ -1,176 +0,0 @@ -// interface to ta_SAREXT.c -// -// Parameters -// double inHigh -// double inLow -// double optInStartValue -// double optInOffsetOnReverse -// double optInAccelerationInitLong -// double optInAccelerationLong -// double optInAccelerationMaxLong -// double optInAccelerationInitShort -// double optInAccelerationShort -// double optInAccelerationMaxShort -// -// Returns -// matrix (n x 1) with colum: -// "SAREXT" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_SAREXT.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -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 -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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]; - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inHigh_ptr, inLow_ptr}; - n = build_na_mask(na_mask, n, 2, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 2, na_mask, n_original, n); - inHigh_ptr = na_arrays[0]; - inLow_ptr = na_arrays[1]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_SAREXT_Lookback( - optInStartValue_value, - optInOffsetOnReverse_value, - optInAccelerationInitLong_value, - optInAccelerationLong_value, - optInAccelerationMaxLong_value, - optInAccelerationInitShort_value, - optInAccelerationShort_value, - optInAccelerationMaxShort_value); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *real = output_ptr; - - // TA_SAREXT returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_SAREXT( - 0, - n - 1, - inHigh_ptr, - inLow_ptr, - optInStartValue_value, - optInOffsetOnReverse_value, - optInAccelerationInitLong_value, - optInAccelerationLong_value, - optInAccelerationMaxLong_value, - optInAccelerationInitShort_value, - optInAccelerationShort_value, - optInAccelerationMaxShort_value, - &start_idx, - &end_idx, - real); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(real, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "SAREXT"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_SMA.c b/src/ta_SMA.c deleted file mode 100644 index 5c0f2ee2d..000000000 --- a/src/ta_SMA.c +++ /dev/null @@ -1,131 +0,0 @@ -// interface to ta_SMA.c -// -// Parameters -// double inReal -// integer optInTimePeriod -// -// Returns -// matrix (n x 1) with colum: -// "SMA" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_SMA.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_SMA( - SEXP inReal, - SEXP optInTimePeriod, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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]; - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inReal_ptr}; - n = build_na_mask(na_mask, n, 1, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 1, na_mask, n_original, n); - inReal_ptr = na_arrays[0]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_SMA_Lookback(optInTimePeriod_value); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *real = output_ptr; - - // TA_SMA returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_SMA( - 0, - n - 1, - inReal_ptr, - optInTimePeriod_value, - &start_idx, - &end_idx, - real); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(real, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "SMA"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_STDDEV.c b/src/ta_STDDEV.c deleted file mode 100644 index 8849d5c3b..000000000 --- a/src/ta_STDDEV.c +++ /dev/null @@ -1,136 +0,0 @@ -// interface to ta_STDDEV.c -// -// Parameters -// double inReal -// integer optInTimePeriod -// double optInNbDev -// -// Returns -// matrix (n x 1) with colum: -// "STDDEV" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_STDDEV.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_STDDEV( - SEXP inReal, - SEXP optInTimePeriod, - SEXP optInNbDev, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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]; - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inReal_ptr}; - n = build_na_mask(na_mask, n, 1, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 1, na_mask, n_original, n); - inReal_ptr = na_arrays[0]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = - TA_STDDEV_Lookback(optInTimePeriod_value, optInNbDev_value); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *real = output_ptr; - - // TA_STDDEV returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_STDDEV( - 0, - n - 1, - inReal_ptr, - optInTimePeriod_value, - optInNbDev_value, - &start_idx, - &end_idx, - real); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(real, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "STDDEV"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_STOCH.c b/src/ta_STOCH.c deleted file mode 100644 index 6d0a3dab8..000000000 --- a/src/ta_STOCH.c +++ /dev/null @@ -1,165 +0,0 @@ -// interface to ta_STOCH.c -// -// Parameters -// double inHigh -// double inLow -// double inClose -// integer optInFastK_Period -// integer optInSlowK_Period -// integer optInSlowK_MAType (MAType) -// integer optInSlowD_Period -// integer optInSlowD_MAType (MAType) -// -// Returns -// matrix (n x 2) with colum: -// "SlowK", "SlowD" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_STOCH.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -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 -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inHigh_ptr, inLow_ptr, inClose_ptr}; - n = build_na_mask(na_mask, n, 3, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 3, na_mask, n_original, n); - inHigh_ptr = na_arrays[0]; - inLow_ptr = na_arrays[1]; - inClose_ptr = na_arrays[2]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_STOCH_Lookback( - optInFastK_Period_value, - optInSlowK_Period_value, - optInSlowK_MAType_value, - optInSlowD_Period_value, - optInSlowD_MAType_value); - - // 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 - const int proceed = - output_container(n, lookback, 2, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *slowk = output_ptr; - double *slowd = output_ptr + 1 * n; - - // TA_STOCH returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_STOCH( - 0, - n - 1, - inHigh_ptr, - inLow_ptr, - inClose_ptr, - optInFastK_Period_value, - optInSlowK_Period_value, - optInSlowK_MAType_value, - optInSlowD_Period_value, - optInSlowD_MAType_value, - &start_idx, - &end_idx, - slowk, - slowd); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(slowk, n, start_idx); - shift_array(slowd, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "SlowK", "SlowD"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_STOCHF.c b/src/ta_STOCHF.c deleted file mode 100644 index 45411baa5..000000000 --- a/src/ta_STOCHF.c +++ /dev/null @@ -1,155 +0,0 @@ -// interface to ta_STOCHF.c -// -// Parameters -// double inHigh -// double inLow -// double inClose -// integer optInFastK_Period -// integer optInFastD_Period -// integer optInFastD_MAType (MAType) -// -// Returns -// matrix (n x 2) with colum: -// "FastK", "FastD" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_STOCHF.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_STOCHF( - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP optInFastK_Period, - SEXP optInFastD_Period, - SEXP optInFastD_MAType, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inHigh_ptr, inLow_ptr, inClose_ptr}; - n = build_na_mask(na_mask, n, 3, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 3, na_mask, n_original, n); - inHigh_ptr = na_arrays[0]; - inLow_ptr = na_arrays[1]; - inClose_ptr = na_arrays[2]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_STOCHF_Lookback( - optInFastK_Period_value, - optInFastD_Period_value, - optInFastD_MAType_value); - - // 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 - const int proceed = - output_container(n, lookback, 2, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *fastk = output_ptr; - double *fastd = output_ptr + 1 * n; - - // TA_STOCHF returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_STOCHF( - 0, - n - 1, - inHigh_ptr, - inLow_ptr, - inClose_ptr, - optInFastK_Period_value, - optInFastD_Period_value, - optInFastD_MAType_value, - &start_idx, - &end_idx, - fastk, - fastd); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(fastk, n, start_idx); - shift_array(fastd, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "FastK", "FastD"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_STOCHRSI.c b/src/ta_STOCHRSI.c deleted file mode 100644 index 3f372b33f..000000000 --- a/src/ta_STOCHRSI.c +++ /dev/null @@ -1,150 +0,0 @@ -// interface to ta_STOCHRSI.c -// -// Parameters -// double inReal -// integer optInTimePeriod -// integer optInFastK_Period -// integer optInFastD_Period -// integer optInFastD_MAType (MAType) -// -// Returns -// matrix (n x 2) with colum: -// "FastK", "FastD" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_STOCHRSI.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_STOCHRSI( - SEXP inReal, - SEXP optInTimePeriod, - SEXP optInFastK_Period, - SEXP optInFastD_Period, - SEXP optInFastD_MAType, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inReal_ptr}; - n = build_na_mask(na_mask, n, 1, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 1, na_mask, n_original, n); - inReal_ptr = na_arrays[0]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_STOCHRSI_Lookback( - optInTimePeriod_value, - optInFastK_Period_value, - optInFastD_Period_value, - optInFastD_MAType_value); - - // 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 - const int proceed = - output_container(n, lookback, 2, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *fastk = output_ptr; - double *fastd = output_ptr + 1 * n; - - // TA_STOCHRSI returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_STOCHRSI( - 0, - n - 1, - inReal_ptr, - optInTimePeriod_value, - optInFastK_Period_value, - optInFastD_Period_value, - optInFastD_MAType_value, - &start_idx, - &end_idx, - fastk, - fastd); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(fastk, n, start_idx); - shift_array(fastd, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "FastK", "FastD"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_SUM.c b/src/ta_SUM.c deleted file mode 100644 index e6311185c..000000000 --- a/src/ta_SUM.c +++ /dev/null @@ -1,131 +0,0 @@ -// interface to ta_SUM.c -// -// Parameters -// double inReal -// integer optInTimePeriod -// -// Returns -// matrix (n x 1) with colum: -// "SUM" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_SUM.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_SUM( - SEXP inReal, - SEXP optInTimePeriod, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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]; - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inReal_ptr}; - n = build_na_mask(na_mask, n, 1, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 1, na_mask, n_original, n); - inReal_ptr = na_arrays[0]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_SUM_Lookback(optInTimePeriod_value); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *real = output_ptr; - - // TA_SUM returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_SUM( - 0, - n - 1, - inReal_ptr, - optInTimePeriod_value, - &start_idx, - &end_idx, - real); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(real, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "SUM"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_T3.c b/src/ta_T3.c deleted file mode 100644 index 7b1693b8d..000000000 --- a/src/ta_T3.c +++ /dev/null @@ -1,136 +0,0 @@ -// interface to ta_T3.c -// -// Parameters -// double inReal -// integer optInTimePeriod -// double optInVFactor -// -// Returns -// matrix (n x 1) with colum: -// "T3" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_T3.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_T3( - SEXP inReal, - SEXP optInTimePeriod, - SEXP optInVFactor, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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]; - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inReal_ptr}; - n = build_na_mask(na_mask, n, 1, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 1, na_mask, n_original, n); - inReal_ptr = na_arrays[0]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = - TA_T3_Lookback(optInTimePeriod_value, optInVFactor_value); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *real = output_ptr; - - // TA_T3 returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_T3( - 0, - n - 1, - inReal_ptr, - optInTimePeriod_value, - optInVFactor_value, - &start_idx, - &end_idx, - real); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(real, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "T3"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_TEMA.c b/src/ta_TEMA.c deleted file mode 100644 index e51ddd0f3..000000000 --- a/src/ta_TEMA.c +++ /dev/null @@ -1,131 +0,0 @@ -// interface to ta_TEMA.c -// -// Parameters -// double inReal -// integer optInTimePeriod -// -// Returns -// matrix (n x 1) with colum: -// "TEMA" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_TEMA.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_TEMA( - SEXP inReal, - SEXP optInTimePeriod, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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]; - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inReal_ptr}; - n = build_na_mask(na_mask, n, 1, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 1, na_mask, n_original, n); - inReal_ptr = na_arrays[0]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_TEMA_Lookback(optInTimePeriod_value); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *real = output_ptr; - - // TA_TEMA returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_TEMA( - 0, - n - 1, - inReal_ptr, - optInTimePeriod_value, - &start_idx, - &end_idx, - real); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(real, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "TEMA"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_TRANGE.c b/src/ta_TRANGE.c deleted file mode 100644 index 1baf58438..000000000 --- a/src/ta_TRANGE.c +++ /dev/null @@ -1,135 +0,0 @@ -// interface to ta_TRANGE.c -// -// Parameters -// double inHigh -// double inLow -// double inClose -// -// Returns -// matrix (n x 1) with colum: -// "TRANGE" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_TRANGE.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_TRANGE( - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inHigh_ptr, inLow_ptr, inClose_ptr}; - n = build_na_mask(na_mask, n, 3, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 3, na_mask, n_original, n); - inHigh_ptr = na_arrays[0]; - inLow_ptr = na_arrays[1]; - inClose_ptr = na_arrays[2]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_TRANGE_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *real = output_ptr; - - // TA_TRANGE returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_TRANGE( - 0, - n - 1, - inHigh_ptr, - inLow_ptr, - inClose_ptr, - &start_idx, - &end_idx, - real); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(real, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "TRANGE"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_TRIMA.c b/src/ta_TRIMA.c deleted file mode 100644 index 2439b6db8..000000000 --- a/src/ta_TRIMA.c +++ /dev/null @@ -1,131 +0,0 @@ -// interface to ta_TRIMA.c -// -// Parameters -// double inReal -// integer optInTimePeriod -// -// Returns -// matrix (n x 1) with colum: -// "TRIMA" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_TRIMA.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_TRIMA( - SEXP inReal, - SEXP optInTimePeriod, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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]; - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inReal_ptr}; - n = build_na_mask(na_mask, n, 1, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 1, na_mask, n_original, n); - inReal_ptr = na_arrays[0]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_TRIMA_Lookback(optInTimePeriod_value); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *real = output_ptr; - - // TA_TRIMA returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_TRIMA( - 0, - n - 1, - inReal_ptr, - optInTimePeriod_value, - &start_idx, - &end_idx, - real); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(real, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "TRIMA"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_TRIX.c b/src/ta_TRIX.c deleted file mode 100644 index 36db44046..000000000 --- a/src/ta_TRIX.c +++ /dev/null @@ -1,131 +0,0 @@ -// interface to ta_TRIX.c -// -// Parameters -// double inReal -// integer optInTimePeriod -// -// Returns -// matrix (n x 1) with colum: -// "TRIX" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_TRIX.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_TRIX( - SEXP inReal, - SEXP optInTimePeriod, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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]; - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inReal_ptr}; - n = build_na_mask(na_mask, n, 1, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 1, na_mask, n_original, n); - inReal_ptr = na_arrays[0]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_TRIX_Lookback(optInTimePeriod_value); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *real = output_ptr; - - // TA_TRIX returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_TRIX( - 0, - n - 1, - inReal_ptr, - optInTimePeriod_value, - &start_idx, - &end_idx, - real); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(real, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "TRIX"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_TYPPRICE.c b/src/ta_TYPPRICE.c deleted file mode 100644 index 68f6bb87b..000000000 --- a/src/ta_TYPPRICE.c +++ /dev/null @@ -1,135 +0,0 @@ -// interface to ta_TYPPRICE.c -// -// Parameters -// double inHigh -// double inLow -// double inClose -// -// Returns -// matrix (n x 1) with colum: -// "TYPPRICE" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_TYPPRICE.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_TYPPRICE( - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inHigh_ptr, inLow_ptr, inClose_ptr}; - n = build_na_mask(na_mask, n, 3, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 3, na_mask, n_original, n); - inHigh_ptr = na_arrays[0]; - inLow_ptr = na_arrays[1]; - inClose_ptr = na_arrays[2]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_TYPPRICE_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *real = output_ptr; - - // TA_TYPPRICE returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_TYPPRICE( - 0, - n - 1, - inHigh_ptr, - inLow_ptr, - inClose_ptr, - &start_idx, - &end_idx, - real); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(real, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "TYPPRICE"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_ULTOSC.c b/src/ta_ULTOSC.c deleted file mode 100644 index f8d7b8342..000000000 --- a/src/ta_ULTOSC.c +++ /dev/null @@ -1,152 +0,0 @@ -// interface to ta_ULTOSC.c -// -// Parameters -// double inHigh -// double inLow -// double inClose -// integer optInTimePeriod1 -// integer optInTimePeriod2 -// integer optInTimePeriod3 -// -// Returns -// matrix (n x 1) with colum: -// "ULTOSC" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_ULTOSC.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_ULTOSC( - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP optInTimePeriod1, - SEXP optInTimePeriod2, - SEXP optInTimePeriod3, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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]; - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inHigh_ptr, inLow_ptr, inClose_ptr}; - n = build_na_mask(na_mask, n, 3, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 3, na_mask, n_original, n); - inHigh_ptr = na_arrays[0]; - inLow_ptr = na_arrays[1]; - inClose_ptr = na_arrays[2]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_ULTOSC_Lookback( - optInTimePeriod1_value, - optInTimePeriod2_value, - optInTimePeriod3_value); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *real = output_ptr; - - // TA_ULTOSC returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_ULTOSC( - 0, - n - 1, - inHigh_ptr, - inLow_ptr, - inClose_ptr, - optInTimePeriod1_value, - optInTimePeriod2_value, - optInTimePeriod3_value, - &start_idx, - &end_idx, - real); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(real, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "ULTOSC"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_VAR.c b/src/ta_VAR.c deleted file mode 100644 index 7a4a863a3..000000000 --- a/src/ta_VAR.c +++ /dev/null @@ -1,135 +0,0 @@ -// interface to ta_VAR.c -// -// Parameters -// double inReal -// integer optInTimePeriod -// double optInNbDev -// -// Returns -// matrix (n x 1) with colum: -// "VAR" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_VAR.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_VAR( - SEXP inReal, - SEXP optInTimePeriod, - SEXP optInNbDev, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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]; - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inReal_ptr}; - n = build_na_mask(na_mask, n, 1, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 1, na_mask, n_original, n); - inReal_ptr = na_arrays[0]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_VAR_Lookback(optInTimePeriod_value, optInNbDev_value); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *real = output_ptr; - - // TA_VAR returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_VAR( - 0, - n - 1, - inReal_ptr, - optInTimePeriod_value, - optInNbDev_value, - &start_idx, - &end_idx, - real); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(real, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "VAR"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_VOLUME.c b/src/ta_VOLUME.c deleted file mode 100644 index 2a631aa06..000000000 --- a/src/ta_VOLUME.c +++ /dev/null @@ -1,136 +0,0 @@ -// ta_VOLUME.c -// -// Parameters -// double inReal -// list maSpec (each element is integer(2): c(period, maType)) -// -// Returns -// matrix (n x (1 + length(maSpec))) with columns: -// "VOLUME", "" e.g. "SMA7" -// -#include "MAType.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include -#include -#include - -// clang-format off -SEXP impl_ta_VOLUME( - SEXP inReal, - SEXP maSpec, - SEXP na_rm -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // get length of 'inReal' (assumes equal length across input) - int n = LENGTH(inReal); - const double *x = REAL(inReal); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_rm)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - 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; - } else { - na_mask = NULL; - } - } - - // determine maSpec input - const int n_ma = isNull(maSpec) ? 0 : LENGTH(maSpec); - const int n_cols = 1 + n_ma; - - // output - 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); - memcpy(output_ptr, x, (size_t)n * sizeof(double)); - - // set initial column name - 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; - - // 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); - - const int period = specification_ptr[0]; - const TA_MAType ma_type = (TA_MAType)specification_ptr[1]; - - double *restrict offset_real = output_ptr + (size_t)(j + 1) * (size_t)n; - - // clang-format off - // calculate moving averages - TA_RetCode return_value = TA_MA( - 0, - n - 1, - x, - period, - ma_type, - &start_idx, - &end_idx, - offset_real - ); - - // validate output - check_output(return_value, protection_count); - // clang-format on - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(offset_real, 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; - } - - // set the remaining column names - // see names.h for more details - column_names(output, n_cols, colname); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = - reexpand_double_matrix(output, na_mask, n_original, &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_WCLPRICE.c b/src/ta_WCLPRICE.c deleted file mode 100644 index 00874106a..000000000 --- a/src/ta_WCLPRICE.c +++ /dev/null @@ -1,135 +0,0 @@ -// interface to ta_WCLPRICE.c -// -// Parameters -// double inHigh -// double inLow -// double inClose -// -// Returns -// matrix (n x 1) with colum: -// "WCLPRICE" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_WCLPRICE.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_WCLPRICE( - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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); - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inHigh_ptr, inLow_ptr, inClose_ptr}; - n = build_na_mask(na_mask, n, 3, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 3, na_mask, n_original, n); - inHigh_ptr = na_arrays[0]; - inLow_ptr = na_arrays[1]; - inClose_ptr = na_arrays[2]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_WCLPRICE_Lookback(); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *real = output_ptr; - - // TA_WCLPRICE returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_WCLPRICE( - 0, - n - 1, - inHigh_ptr, - inLow_ptr, - inClose_ptr, - &start_idx, - &end_idx, - real); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(real, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "WCLPRICE"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_WILLR.c b/src/ta_WILLR.c deleted file mode 100644 index 7e581d889..000000000 --- a/src/ta_WILLR.c +++ /dev/null @@ -1,141 +0,0 @@ -// interface to ta_WILLR.c -// -// Parameters -// double inHigh -// double inLow -// double inClose -// integer optInTimePeriod -// -// Returns -// matrix (n x 1) with colum: -// "WILLR" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_WILLR.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_WILLR( - SEXP inHigh, - SEXP inLow, - SEXP inClose, - SEXP optInTimePeriod, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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]; - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inHigh_ptr, inLow_ptr, inClose_ptr}; - n = build_na_mask(na_mask, n, 3, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 3, na_mask, n_original, n); - inHigh_ptr = na_arrays[0]; - inLow_ptr = na_arrays[1]; - inClose_ptr = na_arrays[2]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_WILLR_Lookback(optInTimePeriod_value); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *real = output_ptr; - - // TA_WILLR returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_WILLR( - 0, - n - 1, - inHigh_ptr, - inLow_ptr, - inClose_ptr, - optInTimePeriod_value, - &start_idx, - &end_idx, - real); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(real, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "WILLR"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/ta_WMA.c b/src/ta_WMA.c deleted file mode 100644 index e6b5fe28e..000000000 --- a/src/ta_WMA.c +++ /dev/null @@ -1,131 +0,0 @@ -// interface to ta_WMA.c -// -// Parameters -// double inReal -// integer optInTimePeriod -// -// Returns -// matrix (n x 1) with colum: -// "WMA" -// -// Source -// https://github.com/TA-Lib/ta-lib/blob/main/src/ta_func/ta_WMA.c -// -#include "MAType.h" -#include "attributes.h" -#include "container.h" -#include "lib.h" -#include "na.h" -#include "names.h" -#include "shift.h" -#include -#include -#include - -// clang-format off -SEXP impl_ta_WMA( - SEXP inReal, - SEXP optInTimePeriod, - SEXP na_bridge -) -// clang-format on -{ - // protection counter - int protection_count = 0; - - // 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]; - - // NA handling - // see na.h for more details - int *na_mask = NULL; - const int n_original = n; - - if (LOGICAL(na_bridge)[0]) { - na_mask = (int *)R_alloc(n, sizeof(int)); - const double *na_arrays[] = {inReal_ptr}; - n = build_na_mask(na_mask, n, 1, na_arrays); - if (n < n_original) { - compact_arrays(na_arrays, 1, na_mask, n_original, n); - inReal_ptr = na_arrays[0]; - - } else { - na_mask = NULL; - } - } - - // output - SEXP output; - double *output_ptr; - - // calculate look back and exit - // the function function early if - // there is a mismatch - const int lookback = TA_WMA_Lookback(optInTimePeriod_value); - - // 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 - const int proceed = - output_container(n, lookback, 1, &output, &output_ptr, &protection_count); - - if (proceed) { - int start_idx = 0; - int end_idx = 0; - - double *real = output_ptr; - - // TA_WMA returns an TA_RetCode - // which is TA_SUCCESS if it succeeds - // values in output_ptr gets populated - // by pointers - TA_RetCode return_code = TA_WMA( - 0, - n - 1, - inReal_ptr, - optInTimePeriod_value, - &start_idx, - &end_idx, - real); - - // check if the output is valid - // and stop function with the TA_RetCode - // see container.h for more details - check_output(return_code, protection_count); - - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with - // see shift.h for more details - shift_array(real, n, start_idx); - } - - // set the column names and lookback attribute - // of the output container - // see names.h and attributes.h for more details - set_colnames(output, "WMA"); - set_attribute(output, lookback, &protection_count); - - // re-expand output if NAs were stripped - // see na.h for more details - if (na_mask != NULL) { - output = reexpand_matrix( - output, - output_ptr, - na_mask, - n_original, - &protection_count); - } - - UNPROTECT(protection_count); - return output; -} diff --git a/src/utils.c b/src/utils.c new file mode 100644 index 000000000..1a2d81b34 --- /dev/null +++ b/src/utils.c @@ -0,0 +1,27 @@ +#include "utils.h" +#include // ISNAN, NA_REAL, NA_INTEGER +#include // R_alloc +#include +#include + +const double *ta_real(SEXP s, R_xlen_t n, int *nprot, const char *name) { + if (XLENGTH(s) != n) + Rf_error( + "input '%s' has length %lld, expected %lld", + name, + (long long)XLENGTH(s), + (long long)n); + SEXP c = PROTECT(Rf_coerceVector(s, REALSXP)); + (*nprot)++; + return REAL(c); +} + +// NA-bridge helpers for the `na.bridge` path now live in NA-handling.{h,c}. + +void ta_check(TA_RetCode rc, const char *fn) { + if (rc == TA_SUCCESS) + return; + TA_RetCodeInfo info; + TA_SetRetCodeInfo(rc, &info); + Rf_error("%s: %s (%s)", fn, info.infoStr, info.enumStr); +} diff --git a/src/utils.h b/src/utils.h new file mode 100644 index 000000000..ec81bf4fb --- /dev/null +++ b/src/utils.h @@ -0,0 +1,22 @@ +// utils.h +// +// Description +// All functions are implemented in utils.c, and includes +// helper functions that ease the process in porting indicators +// to R. +// +#ifndef UTILS_H +#define UTILS_H + +#include "ta_libc.h" +#include + +/* Coerce s to a REAL buffer, PROTECT it (++*nprot), verify length == n. */ +const double *ta_real(SEXP s, R_xlen_t n, int *nprot, const char *name); + +/* NA-bridge helpers for the `na.bridge` path live in NA-handling.{h,c}. */ + +/* rc != TA_SUCCESS -> Rf_error(": ()"). */ +void ta_check(TA_RetCode rc, const char *fn); + +#endif /* UTILS_H */ diff --git a/src/volume.c b/src/volume.c new file mode 100644 index 000000000..5f4dd1987 --- /dev/null +++ b/src/volume.c @@ -0,0 +1,197 @@ +// Trading Volume +// +// Description: +// Trading volume is not an officially exported TA-Lib indicator, so this +// wrapper is hand-written instead of being generated by the TA_WRAPPER +// X-macro in wrapper.h. It returns the volume series alongside one moving +// average column per 'ma' specification. +// +// Parameters +// inReal REALSXP the volume series +// maSpec VECSXP list of integer(2) specs: c(period, maType); may be +// NULL na_bridge LGLSXP drop NA rows, compute on the dense series, scatter +// back +// +// Returns +// REALSXP matrix (n x (1 + length(maSpec))) with columns: +// "VOLUME", "" e.g. "SMA7" +// +// The "lookback" attribute is the (normalized) maximum lookback across all +// maSpec entries; the "VOLUME" column itself always has a lookback of 0. +// +#include "NA-handling.h" +#include "attributes.h" +#include "names.h" +#include "shift.h" +#include "utils.h" +#include +#include +#include +#include +#include + +// MAType names mapped by indices +// clang-format off +static const char *const MATypeNames[] = { + "SMA", + "EMA", + "WMA", + "DEMA", + "TEMA", + "TRIMA", + "KAMA", + "MAMA", + "T3" +}; +// clang-format on + +// Trading Volume lookback +// clang-format off +SEXP impl_ta_VOLUME_lookback( + SEXP maSpec +) +// clang-format on +{ + + const int n_ma = Rf_isNull(maSpec) ? 0 : LENGTH(maSpec); + int lookback = 0; + + if (n_ma > 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; + } + } + } else { + lookback += 1; + } + + return Rf_ScalarInteger(normalize_lookback(lookback)); +} + +// clang-format off +SEXP impl_ta_VOLUME( + SEXP inReal, + SEXP maSpec, + SEXP na_bridge +) +// clang-format on +{ + // protection counter + int protection_counter = 0; + + // extract length of the + // input vector + R_xlen_t ta_n = XLENGTH(inReal); + + // throw error if the length + // is larger than the allowed + if (ta_n > INT_MAX) { + Rf_error("TA_VOLUME: series length exceeds INT_MAX"); + } + + // clang-format off + const double *volume = ta_real( + inReal, + ta_n, + &protection_counter, + "inReal" + ); + // clang-format on + + // get number of moving averages + // with the number of columns + // NOTE: There is always one column (volume column) + const int n_ma = Rf_isNull(maSpec) ? 0 : LENGTH(maSpec); + const int n_cols = 1 + n_ma; + + // identify and extract missing values + // from the input + // + // see NA-handling.h for more details + int ta_bridge = (Rf_asLogical(na_bridge) == TRUE); + R_xlen_t ta_calc = ta_n; + unsigned char *ta_mask = NULL; + if (ta_bridge && ta_n > 0) { + + const double *ta_ins[] = {volume}; + ta_calc = build_presence_mask(ta_ins, 1, ta_n, &ta_mask); + if (ta_calc > 0) { + double *ta_dense = dense_array(ta_calc, 1); + volume = compact_array(ta_dense, volume, ta_mask, ta_n); + } + } + + // construct output matrix + // and copy data + SEXP out = PROTECT(Rf_allocMatrix(REALSXP, (int)ta_n, n_cols)); + protection_counter++; + double *out_ptr = REAL(out); + + memcpy(out_ptr, volume, (size_t)ta_calc * sizeof(double)); + + const char **colname = + (const char **)R_alloc((size_t)n_cols, sizeof(*colname)); + colname[0] = "VOLUME"; + + int lookback = 0; + for (int j = 0; j < n_ma; ++j) { + + 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; + } + + // moving average is written into column (j + 1) + double *ma = out_ptr + (size_t)(j + 1) * (size_t)ta_n; + + int begIdx = 0; + int nbElement = 0; + if (ta_calc > 0) { + // clang-format off + TA_RetCode return_value = TA_MA( + 0, + (int)ta_calc - 1, + volume, + period, + ma_type, + &begIdx, + &nbElement, + ma + ); + // clang-format on + ta_check(return_value, "TA_MA"); + } + + if (ta_bridge) { + scatter_array(ma, ta_n, ta_mask, ta_calc, begIdx, nbElement); + } else { + shift_array(ma, ta_n, begIdx, nbElement); + } + + char *buffer = (char *)R_alloc(32, sizeof(char)); + snprintf(buffer, 32, "%s%d", MATypeNames[ma_type], period); + colname[j + 1] = buffer; + } + + if (ta_bridge) { + scatter_array(out_ptr, ta_n, ta_mask, ta_calc, 0, (int)ta_calc); + } + + // set the column names and the (normalized, maximum) lookback attribute + // see names.h and attributes.h for more details + set_colnames(out, colname, n_cols); + set_attribute(out, LOOKBACK, Rf_ScalarInteger(lookback), &protection_counter); + + UNPROTECT(protection_counter); + return out; +} diff --git a/src/wrapper.h b/src/wrapper.h new file mode 100644 index 000000000..8a32a55a2 --- /dev/null +++ b/src/wrapper.h @@ -0,0 +1,256 @@ +// wrapper.h +// +// Description: +// This header file extracts and parses +// all arguments from each TA_INDICATOR located +// in TA-Lib.h using X-Macros +#ifndef WRAPPER_H +#define WRAPPER_H + +#include "NA-handling.h" +#include "attributes.h" +#include "names.h" +#include "normalize.h" +#include "preprocessor.h" +#include "shift.h" +#include "utils.h" + +// Extract nested expressions from each +// TA_INDICATOR(...) +#define TA_INPUT(...) (__VA_ARGS__) +#define TA_OPTIONS(...) (__VA_ARGS__) +#define TA_OUTPUT(...) (__VA_ARGS__) +#define TA_OUTPUT_NAME(...) (__VA_ARGS__) + +// Optional parameter(s) mapped to +// their R counterpart +#define OPTIONAL_INTEGER(n) (int, Rf_asInteger, n, ) +#define OPTIONAL_DOUBLE(n) (double, Rf_asReal, n, ) +#define OPTIONAL_MATYPE(n) (int, Rf_asInteger, n, (TA_MAType)) + +// output element type tag (TA_DOUBLE|TA_INTEGER) -> R type/accessor +#define TA_SXP(RT) TA_CAT(TA_SXP_, RT) +#define TA_SXP_TA_DOUBLE REALSXP +#define TA_SXP_TA_INTEGER INTSXP +#define TA_ACC(RT) TA_CAT(TA_ACC_, RT) +#define TA_ACC_TA_DOUBLE REAL +#define TA_ACC_TA_INTEGER INTEGER + +// per-input workers +// TA_IN_ARG / TA_OPT_ARG emit trailing-comma parameters; the fixed final +// s_na_bridge parameter absorbs the last comma, so no first-argument special +// case is needed (same trick as the TA_IN_PASS call list below). +#define TA_IN_ARG(name) SEXP s_##name, +#define TA_IN_COERCE(name) \ + const double *name = ta_real(s_##name, ta_n, &protection_counter, #name); +#define TA_IN_PASS(name) name, +// na.bridge workers: TA_IN_PTR builds the input-pointer array for mask +// construction; TA_IN_COMPACT gathers each input into its dense column and +// repoints the local pointer at it so the TA-Lib call below sees the dense +// series unchanged. +#define TA_IN_PTR(name) name, +#define TA_IN_COMPACT(name) \ + name = compact_array(ta_dense + ta_dcol * ta_calc, name, ta_mask, ta_n); \ + ta_dcol++; + +// per-opt workers (consume the tuple) +#define TA_OPT_ARG(t) TA_OPT_ARG_ t +#define TA_OPT_ARG_(c, r, n, k) SEXP s_##n, +#define TA_OPT_READ(t) TA_OPT_READ_ t +#define TA_OPT_READ_(c, r, n, k) c n = r(s_##n); +#define TA_OPT_PASS(t) TA_OPT_PASS_ t +#define TA_OPT_PASS_(c, r, n, k) k n, +// lookback-arg variant of TA_OPT_PASS: same casted value but WITHOUT a trailing +// comma, so TA_JOIN can build the TA__Lookback(...) call list. +#define TA_LB_PASS(t) TA_LB_PASS_ t +#define TA_LB_PASS_(c, r, n, k) k n + +// no-comma sibling of TA_OPT_ARG: one SEXP parameter per opt, comma-joined via +// TA_JOIN to form the impl_ta__lookback(...) signature. +#define TA_LB_ARG(t) TA_LB_ARG_ t +#define TA_LB_ARG_(c, r, n, k) SEXP s_##n + +// parameter list for impl_ta__lookback: (void) when the indicator takes +// no options (keeps -Wstrict-prototypes happy), otherwise the joined opts. +#define TA_LB_PARAMS(OPTS_) \ + TA_CAT(TA_LB_PARAMS_, TA_COUNT_ARGUMENTS OPTS_)(OPTS_) +#define TA_LB_PARAMS_0(OPTS_) void +#define TA_LB_PARAMS_1(OPTS_) TA_JOIN(TA_LB_ARG, OPTS_) +#define TA_LB_PARAMS_2(OPTS_) TA_JOIN(TA_LB_ARG, OPTS_) +#define TA_LB_PARAMS_3(OPTS_) TA_JOIN(TA_LB_ARG, OPTS_) +#define TA_LB_PARAMS_4(OPTS_) TA_JOIN(TA_LB_ARG, OPTS_) +#define TA_LB_PARAMS_5(OPTS_) TA_JOIN(TA_LB_ARG, OPTS_) +#define TA_LB_PARAMS_6(OPTS_) TA_JOIN(TA_LB_ARG, OPTS_) +#define TA_LB_PARAMS_7(OPTS_) TA_JOIN(TA_LB_ARG, OPTS_) +#define TA_LB_PARAMS_8(OPTS_) TA_JOIN(TA_LB_ARG, OPTS_) + +// +#define TA_ALLOC(RT, OUTS_) \ + Rf_allocMatrix(TA_SXP(RT), (int)ta_n, (TA_COUNT_ARGUMENTS OUTS_)) + +#define TA_OUT_PTRS(RT, OUTS_) \ + TA_CAT(TA_OUT_PTRS_, TA_COUNT_ARGUMENTS OUTS_)(RT) +#define TA_OUT_PTRS_1(RT) TA_ACC(RT)(out) +#define TA_OUT_PTRS_2(RT) TA_ACC(RT)(out) + 0 * ta_n, TA_ACC(RT)(out) + 1 * ta_n +#define TA_OUT_PTRS_3(RT) \ + TA_ACC(RT)(out) + 0 * ta_n, TA_ACC(RT)(out) + 1 * ta_n, \ + TA_ACC(RT)(out) + 2 * ta_n + +// One shift per output column; column count is a compile-time literal. +#define TA_OUT_PAD(RT, OUTS_) \ + for (int ta_col = 0; ta_col < (TA_COUNT_ARGUMENTS OUTS_); ta_col++) \ + shift_array(TA_ACC(RT)(out) + ta_col * ta_n, ta_n, begIdx, nbElement); + +// na.bridge counterpart of TA_OUT_PAD: expand each dense output column back +// to full length, scattering NA into dropped rows and lookback slots. +#define TA_OUT_SCATTER(RT, OUTS_) \ + for (int ta_col = 0; ta_col < (TA_COUNT_ARGUMENTS OUTS_); ta_col++) \ + scatter_array( \ + TA_ACC(RT)(out) + ta_col * ta_n, \ + ta_n, \ + ta_mask, \ + ta_calc, \ + begIdx, \ + nbElement); + +// colnames for the output matrix. Every indicator returns a matrix (single +// output included), so stringize every name into the array and label the +// matrix regardless of column count. +#define TA_OUT_COLNAME(a) #a, +#define TA_OUT_COLNAMES(NAMES_) \ + TA_CAT(TA_OUT_COLNAMES_, TA_COUNT_ARGUMENTS NAMES_)(NAMES_) +#define TA_OUT_COLNAMES_1(NAMES_) TA_OUT_COLNAMES_MANY(NAMES_) +#define TA_OUT_COLNAMES_2(NAMES_) TA_OUT_COLNAMES_MANY(NAMES_) +#define TA_OUT_COLNAMES_3(NAMES_) TA_OUT_COLNAMES_MANY(NAMES_) +#define TA_OUT_COLNAMES_MANY(NAMES_) \ + { \ + static const char *ta_cn[] = {TA_APPLY(TA_OUT_COLNAME, NAMES_)}; \ + set_colnames(out, ta_cn, TA_COUNT_ARGUMENTS NAMES_); \ + } + +// candlestick normalization seam +// Only CANDLESTICK indicators carry the extra SEXP s_normalize control arg. +// TA_NORM_ARG appends it to the signature; TA_NORM_APPLY divides the dense +// computed region by 100 (before padding, so NA slots are never touched); +// TA_NORM_ARITY bumps the registered .Call arity. NOT_CANDLESTICK -> nothing. +#define TA_NORM_ARG_CANDLESTICK , SEXP s_normalize +#define TA_NORM_ARG_NOT_CANDLESTICK + +#define TA_NORM_APPLY_CANDLESTICK(RT) \ + if (Rf_asLogical(s_normalize) == TRUE) \ + normalize(TA_ACC(RT)(out), nbElement, 100, 0); +#define TA_NORM_APPLY_NOT_CANDLESTICK(RT) + +#define TA_NORM_ARITY_CANDLESTICK 1 +#define TA_NORM_ARITY_NOT_CANDLESTICK 0 + +// TA-Lib wrapper +// +// Description +// This is the X-macro that writes the actual +// underlying C-code that ports TA-Lib to R. +// Before the migrating to X-Macros the code below +// were autogenerated via BASH which produced the ta_.c files +// clang-format off +#define TA_WRAPPER(NAME, RT, INS_, OPTS_, OUTS_, TA_OUTPUT_NAME_, KIND) \ + /* signature start */ \ + SEXP impl_ta_##NAME( \ + TA_APPLY(TA_IN_ARG, INS_) \ + TA_APPLY(TA_OPT_ARG, OPTS_) \ + SEXP s_na_bridge \ + TA_CAT(TA_NORM_ARG_, KIND) \ + ) \ + /* signature end*/ \ + /* logic start*/ \ + { \ + /* protection counter */ \ + int protection_counter = 0; \ + R_xlen_t ta_n = XLENGTH(TA_CAT(s_, TA_HEAD INS_)); \ + \ + if (ta_n > INT_MAX) { \ + Rf_error("TA_" #NAME ": series length exceeds INT_MAX"); \ + } \ + \ + /* convert input to type aware pointers */ \ + TA_APPLY(TA_IN_COERCE, INS_) \ + TA_APPLY(TA_OPT_READ, OPTS_) \ + \ + /* na.bridge: drop NA rows, compute on the dense series, scatter back. */ \ + int ta_bridge = (Rf_asLogical(s_na_bridge) == TRUE); \ + R_xlen_t ta_calc = ta_n; \ + unsigned char *ta_mask = NULL; \ + if (ta_bridge && ta_n > 0) { \ + \ + const double *ta_ins[] = {TA_APPLY(TA_IN_PTR, INS_)}; \ + \ + ta_calc = build_presence_mask( \ + ta_ins, \ + (int)(TA_COUNT_ARGUMENTS INS_), \ + ta_n, \ + &ta_mask \ + ); \ + \ + if (ta_calc > 0) { \ + double *ta_dense = dense_array( \ + ta_calc, \ + (int)(TA_COUNT_ARGUMENTS INS_) \ + ); \ + \ + int ta_dcol = 0; \ + \ + TA_APPLY(TA_IN_COMPACT, INS_) \ + } \ + } \ + SEXP out = PROTECT(TA_ALLOC(RT, OUTS_)); \ + protection_counter++; \ + int begIdx = 0, nbElement = 0; \ + if (ta_calc > 0) { \ + TA_RetCode return_value = TA_##NAME( \ + 0, \ + (int) ta_calc - 1, \ + TA_APPLY(TA_IN_PASS, INS_) TA_APPLY(TA_OPT_PASS, OPTS_) & begIdx, \ + &nbElement, \ + TA_OUT_PTRS(RT, OUTS_) \ + ); \ + \ + ta_check(return_value, "TA_" #NAME); \ + \ + TA_CAT(TA_NORM_APPLY_, KIND)(RT) \ + } \ + if (ta_bridge) { \ + TA_OUT_SCATTER(RT, OUTS_) \ + } else if (ta_calc > 0) { \ + TA_OUT_PAD(RT, OUTS_) \ + } \ + TA_OUT_COLNAMES(TA_OUTPUT_NAME_) \ + \ + /* lookback attributes */ \ + int lookback_value = TA_##NAME##_Lookback(TA_JOIN(TA_LB_PASS, OPTS_)); \ + \ + set_attribute( \ + out, \ + LOOKBACK, \ + Rf_ScalarInteger(lookback_value), \ + &protection_counter \ + ); \ + \ + UNPROTECT(protection_counter); \ + return out; \ + } \ + /* logic end*/ +// clang-format on + +// TA__Lookback wrapper +// Driven by the TA_LOOKBACK(NAME, TA_OPTIONS(...)) lines in TA-Lib.h. The +// R-callable impl_ta__lookback() reads the optional inputs from +// their SEXPs, calls the pure TA__Lookback(), and returns the +// (normalized) lookback - the same value set_attribute() attaches to the +// indicator output. +#define TA_LB_WRAPPER(NAME, OPTS_) \ + SEXP impl_ta_##NAME##_lookback(TA_LB_PARAMS(OPTS_)) { \ + TA_APPLY(TA_OPT_READ, OPTS_) \ + return Rf_ScalarInteger( \ + normalize_lookback(TA_##NAME##_Lookback(TA_JOIN(TA_LB_PASS, OPTS_)))); \ + } + +#endif /* WRAPPER_H */ diff --git a/tests/testthat/test-moving_average_spec.R b/tests/testthat/test-moving_average_spec.R deleted file mode 100644 index 3707b873d..000000000 --- a/tests/testthat/test-moving_average_spec.R +++ /dev/null @@ -1,319 +0,0 @@ -## Moving-Average specification mode -## -## When an MA function is called without 'x' it returns a named list -## ("spec") consumed by indicators that support multiple MA types -## (APO, PPO, BBANDS, MACDEXT, STOCH, STOCHF, STOCHRSI). -## -## Hand-written (not generated via codegen/) because the contract is -## cross-cutting across the nine MA functions and would otherwise -## require threading maType through generate_unit-tests.sh. - -## ---- expected spec per MA ------------------------------------------------- -## Each row: function, alias, maType code, default-field values. -## Simple MAs take n only; MAMA takes fast/slow; T3 takes n/vfactor. -.ma_specs <- list( - list( - name = "SMA", - fun = simple_moving_average, - alias = SMA, - maType = 0L, - n = 30L - ), - list( - name = "EMA", - fun = exponential_moving_average, - alias = EMA, - maType = 1L, - n = 30L - ), - list( - name = "WMA", - fun = weighted_moving_average, - alias = WMA, - maType = 2L, - n = 30L - ), - list( - name = "DEMA", - fun = double_exponential_moving_average, - alias = DEMA, - maType = 3L, - n = 30L - ), - list( - name = "TEMA", - fun = triple_exponential_moving_average, - alias = TEMA, - maType = 4L, - n = 30L - ), - list( - name = "TRIMA", - fun = triangular_moving_average, - alias = TRIMA, - maType = 5L, - n = 30L - ), - list( - name = "KAMA", - fun = kaufman_adaptive_moving_average, - alias = KAMA, - maType = 6L, - n = 30L - ) -) - -## ---- shape and default contract (simple n-only MAs) ------------------------ -for (.spec in .ma_specs) { - local({ - spec <- .spec - - testthat::test_that( - sprintf("%s() without x returns list(n, maType)", spec$name), - { - out <- spec$fun() - - testthat::expect_type(out, "list") - testthat::expect_named(out, c("n", "maType")) - testthat::expect_identical(out$maType, spec$maType) - testthat::expect_identical(out$n, spec$n) - } - ) - - testthat::test_that( - sprintf( - "%s() alias returns identical spec to long-form", - spec$name - ), - { - testthat::expect_identical(spec$alias(), spec$fun()) - testthat::expect_identical(spec$alias(n = 7), spec$fun(n = 7)) - } - ) - - testthat::test_that( - sprintf( - "%s() coerces n to integer and honours explicit value", - spec$name - ), - { - ## explicit integer round-trips - testthat::expect_identical(spec$fun(n = 14)$n, 14L) - ## double is truncated to integer (matches as.integer semantics) - testthat::expect_identical(spec$fun(n = 14.7)$n, 14L) - ## storage type is integer even when caller passes double - testthat::expect_identical(typeof(spec$fun(n = 5)$n), "integer") - } - ) - }) -} - -## ---- MAMA (n + fast / slow) ------------------------------------------------ -## MAMA carries 'n' as a spec-only field so downstream consumers -## (BBANDS, STOCH, MACDEXT, ...) can read ma$n uniformly even though -## MAMA's own standalone calculation is adaptive and does not use n. -testthat::test_that("MAMA() without x returns list(n, fast, slow, maType = 7L)", { - out <- mesa_adaptive_moving_average() - - testthat::expect_type(out, "list") - testthat::expect_named(out, c("n", "fast", "slow", "maType")) - testthat::expect_identical(out$maType, 7L) - testthat::expect_identical(out$n, 30L) - testthat::expect_identical(out$fast, 0.5) - testthat::expect_identical(out$slow, 0.05) -}) - -testthat::test_that("MAMA() alias matches long-form and coerces types", { - testthat::expect_identical(MAMA(), mesa_adaptive_moving_average()) - testthat::expect_identical( - MAMA(n = 14, fast = 0.3, slow = 0.1), - mesa_adaptive_moving_average(n = 14, fast = 0.3, slow = 0.1) - ) - - out <- MAMA(n = 14.7, fast = 1L, slow = 0L) - testthat::expect_identical(out$n, 14L) - testthat::expect_identical(typeof(out$n), "integer") - testthat::expect_identical(out$fast, 1) - testthat::expect_identical(out$slow, 0) - testthat::expect_identical(typeof(out$fast), "double") - testthat::expect_identical(typeof(out$slow), "double") -}) - -## 'n' is spec-only: MAMA's standalone output must NOT depend on it. -## Regression guard against someone wiring 'n' into the C call. -testthat::test_that("MAMA(x, n) ignores n in standalone calculation", { - default_out <- mesa_adaptive_moving_average(BTC) - n14_out <- mesa_adaptive_moving_average(BTC, n = 14) - n50_out <- mesa_adaptive_moving_average(BTC, n = 50) - - testthat::expect_equal(default_out, n14_out) - testthat::expect_equal(default_out, n50_out) -}) - -## ---- T3 (n + vfactor) ------------------------------------------------------ -testthat::test_that("T3() without x returns list(n, vfactor, maType = 8L)", { - out <- t3_exponential_moving_average() - - testthat::expect_type(out, "list") - testthat::expect_named(out, c("n", "vfactor", "maType")) - testthat::expect_identical(out$maType, 8L) - testthat::expect_identical(out$n, 5L) - testthat::expect_identical(out$vfactor, 0.7) -}) - -testthat::test_that("T3() alias matches long-form and coerces types", { - testthat::expect_identical(T3(), t3_exponential_moving_average()) - testthat::expect_identical( - T3(n = 10, vfactor = 0.5), - t3_exponential_moving_average(n = 10, vfactor = 0.5) - ) - - out <- T3(n = 9.9, vfactor = 1L) - testthat::expect_identical(out$n, 9L) - testthat::expect_identical(out$vfactor, 1) - testthat::expect_identical(typeof(out$n), "integer") - testthat::expect_identical(typeof(out$vfactor), "double") -}) - -## ---- downstream integration ------------------------------------------------ -## Every MA spec carries 'n' + 'maType' and must drive every consumer: -## APO / PPO (read maType only) and -## BBANDS / stochastic / STOCHF / STOCHRSI / MACDEXT (read both n and maType). - -.all_specs <- list( - SMA = SMA, - EMA = EMA, - WMA = WMA, - DEMA = DEMA, - TEMA = TEMA, - TRIMA = TRIMA, - KAMA = KAMA, - MAMA = MAMA, - T3 = T3 -) - -for (.nm in names(.all_specs)) { - local({ - nm <- .nm - mk <- .all_specs[[nm]] - - testthat::test_that( - sprintf("APO() accepts %s() spec", nm), - { - out <- absolute_price_oscillator(BTC, ma = mk()) - testthat::expect_s3_class(out, "data.frame") - testthat::expect_equal(nrow(out), nrow(BTC)) - testthat::expect_true(any(is.finite(out[[1]]))) - } - ) - - testthat::test_that( - sprintf("PPO() accepts %s() spec", nm), - { - out <- percentage_price_oscillator(BTC, ma = mk()) - testthat::expect_s3_class(out, "data.frame") - testthat::expect_equal(nrow(out), nrow(BTC)) - testthat::expect_true(any(is.finite(out[[1]]))) - } - ) - - testthat::test_that( - sprintf("BBANDS() accepts %s() spec with explicit n", nm), - { - out <- bollinger_bands(BTC, ma = mk(n = 10)) - testthat::expect_s3_class(out, "data.frame") - testthat::expect_equal(nrow(out), nrow(BTC)) - testthat::expect_true(any(is.finite(out[[1]]))) - } - ) - - testthat::test_that( - sprintf("stochastic() accepts %s() spec for slowk/slowd", nm), - { - out <- stochastic(BTC, slowk = mk(n = 3), slowd = mk(n = 3)) - testthat::expect_s3_class(out, "data.frame") - testthat::expect_equal(nrow(out), nrow(BTC)) - testthat::expect_true(any(is.finite(out[[1]]))) - } - ) - - testthat::test_that( - sprintf("STOCHF() accepts %s() spec for fastd", nm), - { - out <- STOCHF(BTC, fastd = mk(n = 3)) - testthat::expect_s3_class(out, "data.frame") - testthat::expect_equal(nrow(out), nrow(BTC)) - testthat::expect_true(any(is.finite(out[[1]]))) - } - ) - - testthat::test_that( - sprintf("STOCHRSI() accepts %s() spec for fastd", nm), - { - out <- STOCHRSI(BTC, fastd = mk(n = 3)) - testthat::expect_s3_class(out, "data.frame") - testthat::expect_equal(nrow(out), nrow(BTC)) - testthat::expect_true(any(is.finite(out[[1]]))) - } - ) - - testthat::test_that( - sprintf("MACDEXT() accepts %s() spec for fast/slow/signal", nm), - { - out <- extended_moving_average_convergence_divergence( - BTC, - fast = mk(n = 5), - slow = mk(n = 10), - signal = mk(n = 3) - ) - testthat::expect_s3_class(out, "data.frame") - testthat::expect_equal(nrow(out), nrow(BTC)) - testthat::expect_true(any(is.finite(out[[1]]))) - } - ) - }) -} - -## ---- maType drives the consumer's output ----------------------------------- -## Swap EMA for SMA in APO: output must differ. Protects against consumers -## silently ignoring the spec (the bug shape that shape tests alone miss). -testthat::test_that("APO output depends on the MA spec (EMA != SMA)", { - out_sma <- absolute_price_oscillator(BTC, ma = SMA(n = 9)) - out_ema <- absolute_price_oscillator(BTC, ma = EMA(n = 9)) - - testthat::expect_equal(dim(out_sma), dim(out_ema)) - ## require an actual numerical difference somewhere in the overlap - testthat::expect_false( - isTRUE(all.equal(out_sma[[1]], out_ema[[1]])) - ) -}) - -testthat::test_that("BBANDS output depends on the MA spec (WMA != SMA)", { - out_sma <- bollinger_bands(BTC, ma = SMA(n = 10)) - out_wma <- bollinger_bands(BTC, ma = WMA(n = 10)) - - testthat::expect_equal(dim(out_sma), dim(out_wma)) - testthat::expect_false( - isTRUE(all.equal(out_sma[[1]], out_wma[[1]])) - ) -}) - -## 'n' must drive the consumer's window. If a future change drops ma$n -## lookup in favour of a hard-coded default, these tests catch it. -testthat::test_that("BBANDS consumes ma$n (different n => different output)", { - out_10 <- bollinger_bands(BTC, ma = SMA(n = 10)) - out_30 <- bollinger_bands(BTC, ma = SMA(n = 30)) - - testthat::expect_false( - isTRUE(all.equal(out_10[[1]], out_30[[1]])) - ) -}) - -testthat::test_that("stochastic() consumes slowk$n (different n => different output)", { - out_3 <- stochastic(BTC, slowk = SMA(n = 3), slowd = SMA(n = 3)) - out_7 <- stochastic(BTC, slowk = SMA(n = 7), slowd = SMA(n = 7)) - - testthat::expect_false( - isTRUE(all.equal(out_3[[1]], out_7[[1]])) - ) -}) diff --git a/tests/testthat/test-ta_ACCBANDS.R b/tests/testthat/test-ta_ACCBANDS.R index 2bce7be98..308ca6dba 100644 --- a/tests/testthat/test-ta_ACCBANDS.R +++ b/tests/testthat/test-ta_ACCBANDS.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- accelerationBands(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = acceleration_bands, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = accelerationBands_lookback, + expected = acceleration_bands_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_AD.R b/tests/testthat/test-ta_AD.R index 28d61d694..7e213ac2c 100644 --- a/tests/testthat/test-ta_AD.R +++ b/tests/testthat/test-ta_AD.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- chaikinAccumulationDistributionLine(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,29 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback( + FUN = chaikin_accumulation_distribution_line, + x = SPY + ) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = chaikinAccumulationDistributionLine_lookback, + expected = chaikin_accumulation_distribution_line_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_ADOSC.R b/tests/testthat/test-ta_ADOSC.R index 9ed88a8d0..c2695c102 100644 --- a/tests/testthat/test-ta_ADOSC.R +++ b/tests/testthat/test-ta_ADOSC.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- chaikinAccumulationDistributionOscillator(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -147,6 +158,29 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback( + FUN = chaikin_accumulation_distribution_oscillator, + x = SPY + ) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = chaikinAccumulationDistributionOscillator_lookback, + expected = chaikin_accumulation_distribution_oscillator_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_ADX.R b/tests/testthat/test-ta_ADX.R index aa0e9f651..7d90debc8 100644 --- a/tests/testthat/test-ta_ADX.R +++ b/tests/testthat/test-ta_ADX.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- averageDirectionalMovementIndex(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = average_directional_movement_index, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = averageDirectionalMovementIndex_lookback, + expected = average_directional_movement_index_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_ADXR.R b/tests/testthat/test-ta_ADXR.R index ce5f58cbd..56247175a 100644 --- a/tests/testthat/test-ta_ADXR.R +++ b/tests/testthat/test-ta_ADXR.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- averageDirectionalMovementIndexRating(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -147,6 +158,29 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback( + FUN = average_directional_movement_index_rating, + x = SPY + ) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = averageDirectionalMovementIndexRating_lookback, + expected = average_directional_movement_index_rating_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_APO.R b/tests/testthat/test-ta_APO.R index 1b3387c0a..0afc08570 100644 --- a/tests/testthat/test-ta_APO.R +++ b/tests/testthat/test-ta_APO.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- absolutePriceOscillator(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = absolute_price_oscillator, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = absolutePriceOscillator_lookback, + expected = absolute_price_oscillator_lookback + ) +}) ## -method checks for ## and @@ -240,18 +271,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..74086f794 100644 --- a/tests/testthat/test-ta_AROON.R +++ b/tests/testthat/test-ta_AROON.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -144,6 +144,19 @@ 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(x = 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..5fe654904 100644 --- a/tests/testthat/test-ta_AROONOSC.R +++ b/tests/testthat/test-ta_AROONOSC.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- aroonOscillator(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = aroon_oscillator, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = aroonOscillator_lookback, + expected = aroon_oscillator_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_ATR.R b/tests/testthat/test-ta_ATR.R index 4745c6a89..74cde10ba 100644 --- a/tests/testthat/test-ta_ATR.R +++ b/tests/testthat/test-ta_ATR.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- averageTrueRange(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = average_true_range, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = averageTrueRange_lookback, + expected = average_true_range_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_AVGDEV.R b/tests/testthat/test-ta_AVGDEV.R new file mode 100644 index 000000000..11e34acaf --- /dev/null +++ b/tests/testthat/test-ta_AVGDEV.R @@ -0,0 +1,198 @@ +## autogenerated unit-test +## from codegen/ +## the file will be overwritten in the next iteration +## +## author: Serkan Korkmaz + +## alias and function similarity +## checks this ensures that +## average_deviation and AVGDEV produces the same results +testthat::test_that(desc = 'Alias and function similarity', code = { + ## 1) test that the alias and + ## function returns the same values + output <- average_deviation(SPY) + alias <- AVGDEV(SPY) + + ## 1.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = alias + ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- averageDeviation(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) +}) + +## type-checks for data.frames and +## matrices +## +## object +testthat::test_that(desc = 'Class in, class out ()', code = { + ## 1) check that the output class + ## matches the input class + testthat::expect_true( + inherits(average_deviation(SPY), class(SPY)) + ) +}) + +## object +testthat::test_that(desc = 'Class in, class out ()', code = { + ## 1) check that the output class + ## matches the input class + testthat::expect_true( + inherits(average_deviation(BTC), class(BTC)) + ) +}) + +## check that the default calls +## matches that of the constructed call +## with default values. +## +## NOTE: This test is more of a test of the internal +## series() function +testthat::test_that(desc = 'Default calls', code = { + testthat::expect_equal( + object = average_deviation( + BTC + ), + expected = average_deviation( + BTC, + cols = ~close + ) + ) +}) + +## check that the length of the input +## matches the output length with na.bridge = TRUE +## +## object +testthat::test_that(desc = 'Equal length of input and output for with na.bridge = TRUE', code = { + testthat::expect_equal( + object = nrow(average_deviation( + ATOM, + na.bridge = TRUE + )), + expected = nrow(ATOM) + ) +}) + +## check that the rownames are being +## respected for with na.bridge = TRUE +testthat::test_that(desc = 'Row names are respected for , na.bridge = TRUE', code = { + ## extract row names + x_names <- row.names(ATOM) + + ## calculate indicator + indicator <- average_deviation(ATOM, na.bridge = TRUE) + + testthat::expect_equal( + object = x_names, + expected = rownames(indicator) + ) +}) + +## check that the length of the input +## matches the output length +## +## object +testthat::test_that(desc = 'Equal length of input and output for ', code = { + testthat::expect_equal( + object = nrow(average_deviation( + BTC + )), + expected = nrow(BTC) + ) +}) + +## check that the rownames are being +## respected for +testthat::test_that(desc = 'Row names are respected for ', code = { + ## extract row names + x_names <- row.names(BTC) + + ## calculate indicator + indicator <- average_deviation(BTC) + + testthat::expect_equal( + object = x_names, + expected = rownames(indicator) + ) +}) + +## object +testthat::test_that(desc = 'Equal length of input and output for ', code = { + testthat::expect_equal( + object = nrow(average_deviation( + SPY + )), + expected = nrow(SPY) + ) +}) + +## check that the rownames are being +## respected for +testthat::test_that(desc = 'Row names are respected for ', code = { + ## extract row names + ## NOTE: by default the SPY has no + ## rownames + rownames(SPY) <- paste0("row", 1:nrow(SPY)) + + ## calculate indicator + indicator <- average_deviation(SPY) + + testthat::expect_equal( + object = paste0("row", 1:nrow(SPY)), + expected = rownames(indicator) + ) +}) + +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + average_deviation(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = average_deviation, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = averageDeviation_lookback, + expected = average_deviation_lookback + ) +}) + +## check that methods runs without +## issues and returns proper lengths +testthat::test_that(desc = ' methods', code = { + ## check that the method + ## runs + x <- testthat::expect_no_condition( + average_deviation(BTC[[1]]) + ) + + target_length <- length(BTC[[1]]) + + 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(is.matrix(x)) + testthat::expect_equal(nrow(x), target_length) + } +}) diff --git a/tests/testthat/test-ta_AVGPRICE.R b/tests/testthat/test-ta_AVGPRICE.R index a6ae729b2..3b53ca41c 100644 --- a/tests/testthat/test-ta_AVGPRICE.R +++ b/tests/testthat/test-ta_AVGPRICE.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- averagePrice(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -143,3 +154,24 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = average_price, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = averagePrice_lookback, + expected = average_price_lookback + ) +}) diff --git a/tests/testthat/test-ta_BBANDS.R b/tests/testthat/test-ta_BBANDS.R index 3690e5e93..3e6597f2d 100644 --- a/tests/testthat/test-ta_BBANDS.R +++ b/tests/testthat/test-ta_BBANDS.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- bollingerBands(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = bollinger_bands, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = bollingerBands_lookback, + expected = bollinger_bands_lookback + ) +}) ## -method checks for ## and @@ -240,18 +271,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..fa89c86c5 100644 --- a/tests/testthat/test-ta_BETA.R +++ b/tests/testthat/test-ta_BETA.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -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]) ) }) diff --git a/tests/testthat/test-ta_BOP.R b/tests/testthat/test-ta_BOP.R index 55707da8f..5c403ff07 100644 --- a/tests/testthat/test-ta_BOP.R +++ b/tests/testthat/test-ta_BOP.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- balanceOfPower(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = balance_of_power, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = balanceOfPower_lookback, + expected = balance_of_power_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_CCI.R b/tests/testthat/test-ta_CCI.R index 00ae8c3d0..628ad43ab 100644 --- a/tests/testthat/test-ta_CCI.R +++ b/tests/testthat/test-ta_CCI.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- commodityChannelIndex(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = commodity_channel_index, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = commodityChannelIndex_lookback, + expected = commodity_channel_index_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_CDL2CROWS.R b/tests/testthat/test-ta_CDL2CROWS.R index be0fcce24..19c2807e4 100644 --- a/tests/testthat/test-ta_CDL2CROWS.R +++ b/tests/testthat/test-ta_CDL2CROWS.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- twoCrows(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = two_crows, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = twoCrows_lookback, + expected = two_crows_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_CDL3BLACKCROWS.R b/tests/testthat/test-ta_CDL3BLACKCROWS.R index 3ffbd29c2..80f9fd02b 100644 --- a/tests/testthat/test-ta_CDL3BLACKCROWS.R +++ b/tests/testthat/test-ta_CDL3BLACKCROWS.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- threeBlackCrows(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = three_black_crows, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = threeBlackCrows_lookback, + expected = three_black_crows_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_CDL3INSIDE.R b/tests/testthat/test-ta_CDL3INSIDE.R index 904d06ff1..8a0467228 100644 --- a/tests/testthat/test-ta_CDL3INSIDE.R +++ b/tests/testthat/test-ta_CDL3INSIDE.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- threeInside(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = three_inside, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = threeInside_lookback, + expected = three_inside_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_CDL3LINESTRIKE.R b/tests/testthat/test-ta_CDL3LINESTRIKE.R index 52f5f28ae..47e3e5ecf 100644 --- a/tests/testthat/test-ta_CDL3LINESTRIKE.R +++ b/tests/testthat/test-ta_CDL3LINESTRIKE.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- threeLineStrike(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = three_line_strike, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = threeLineStrike_lookback, + expected = three_line_strike_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_CDL3OUTSIDE.R b/tests/testthat/test-ta_CDL3OUTSIDE.R index 1e0d888a8..c475587ca 100644 --- a/tests/testthat/test-ta_CDL3OUTSIDE.R +++ b/tests/testthat/test-ta_CDL3OUTSIDE.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- threeOutside(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = three_outside, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = threeOutside_lookback, + expected = three_outside_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_CDL3STARSINSOUTH.R b/tests/testthat/test-ta_CDL3STARSINSOUTH.R index 4949a6f17..1ffc00750 100644 --- a/tests/testthat/test-ta_CDL3STARSINSOUTH.R +++ b/tests/testthat/test-ta_CDL3STARSINSOUTH.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- threeStarsInTheSouth(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = three_stars_in_the_south, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = threeStarsInTheSouth_lookback, + expected = three_stars_in_the_south_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_CDL3WHITESOLDIERS.R b/tests/testthat/test-ta_CDL3WHITESOLDIERS.R index 2fead055e..e797561a7 100644 --- a/tests/testthat/test-ta_CDL3WHITESOLDIERS.R +++ b/tests/testthat/test-ta_CDL3WHITESOLDIERS.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- threeWhiteSoldiers(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = three_white_soldiers, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = threeWhiteSoldiers_lookback, + expected = three_white_soldiers_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_CDLABANDONEDBABY.R b/tests/testthat/test-ta_CDLABANDONEDBABY.R index 8af4d3e6a..45ec30d53 100644 --- a/tests/testthat/test-ta_CDLABANDONEDBABY.R +++ b/tests/testthat/test-ta_CDLABANDONEDBABY.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- abandonedBaby(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = abandoned_baby, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = abandonedBaby_lookback, + expected = abandoned_baby_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_CDLADVANCEBLOCK.R b/tests/testthat/test-ta_CDLADVANCEBLOCK.R index 99841b11a..c227abe68 100644 --- a/tests/testthat/test-ta_CDLADVANCEBLOCK.R +++ b/tests/testthat/test-ta_CDLADVANCEBLOCK.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- advanceBlock(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = advance_block, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = advanceBlock_lookback, + expected = advance_block_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_CDLBELTHOLD.R b/tests/testthat/test-ta_CDLBELTHOLD.R index cf98c69c9..900066356 100644 --- a/tests/testthat/test-ta_CDLBELTHOLD.R +++ b/tests/testthat/test-ta_CDLBELTHOLD.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- beltHold(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = belt_hold, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = beltHold_lookback, + expected = belt_hold_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_CDLBREAKAWAY.R b/tests/testthat/test-ta_CDLBREAKAWAY.R index bc510b1bf..7929ed752 100644 --- a/tests/testthat/test-ta_CDLBREAKAWAY.R +++ b/tests/testthat/test-ta_CDLBREAKAWAY.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- breakAway(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = break_away, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = breakAway_lookback, + expected = break_away_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_CDLCLOSINGMARUBOZU.R b/tests/testthat/test-ta_CDLCLOSINGMARUBOZU.R index d3e9fc72a..51c46d9cc 100644 --- a/tests/testthat/test-ta_CDLCLOSINGMARUBOZU.R +++ b/tests/testthat/test-ta_CDLCLOSINGMARUBOZU.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- closingMarubozu(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = closing_marubozu, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = closingMarubozu_lookback, + expected = closing_marubozu_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_CDLCONCEALBABYSWALL.R b/tests/testthat/test-ta_CDLCONCEALBABYSWALL.R index 6e5bbf613..251b4f2ce 100644 --- a/tests/testthat/test-ta_CDLCONCEALBABYSWALL.R +++ b/tests/testthat/test-ta_CDLCONCEALBABYSWALL.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- concealingBabySwallow(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = concealing_baby_swallow, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = concealingBabySwallow_lookback, + expected = concealing_baby_swallow_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_CDLCOUNTERATTACK.R b/tests/testthat/test-ta_CDLCOUNTERATTACK.R index 2de3e4319..fdb6310b0 100644 --- a/tests/testthat/test-ta_CDLCOUNTERATTACK.R +++ b/tests/testthat/test-ta_CDLCOUNTERATTACK.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- counterAttack(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = counter_attack, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = counterAttack_lookback, + expected = counter_attack_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_CDLDARKCLOUDCOVER.R b/tests/testthat/test-ta_CDLDARKCLOUDCOVER.R index df221cf64..d1cc2d240 100644 --- a/tests/testthat/test-ta_CDLDARKCLOUDCOVER.R +++ b/tests/testthat/test-ta_CDLDARKCLOUDCOVER.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- darkCloudCover(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = dark_cloud_cover, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = darkCloudCover_lookback, + expected = dark_cloud_cover_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_CDLDOJI.R b/tests/testthat/test-ta_CDLDOJI.R index 67e041f02..3c448493e 100644 --- a/tests/testthat/test-ta_CDLDOJI.R +++ b/tests/testthat/test-ta_CDLDOJI.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -144,6 +144,19 @@ 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(x = 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..7a6f8ec25 100644 --- a/tests/testthat/test-ta_CDLDOJISTAR.R +++ b/tests/testthat/test-ta_CDLDOJISTAR.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- dojiStar(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = doji_star, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = dojiStar_lookback, + expected = doji_star_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_CDLDRAGONFLYDOJI.R b/tests/testthat/test-ta_CDLDRAGONFLYDOJI.R index 098c48167..4e05f5327 100644 --- a/tests/testthat/test-ta_CDLDRAGONFLYDOJI.R +++ b/tests/testthat/test-ta_CDLDRAGONFLYDOJI.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- dragonflyDoji(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = dragonfly_doji, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = dragonflyDoji_lookback, + expected = dragonfly_doji_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_CDLENGULFING.R b/tests/testthat/test-ta_CDLENGULFING.R index fa7e4c09b..fe3e34aa7 100644 --- a/tests/testthat/test-ta_CDLENGULFING.R +++ b/tests/testthat/test-ta_CDLENGULFING.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -144,6 +144,19 @@ 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(x = 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..eb609b7eb 100644 --- a/tests/testthat/test-ta_CDLEVENINGDOJISTAR.R +++ b/tests/testthat/test-ta_CDLEVENINGDOJISTAR.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- eveningDojiStar(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = evening_doji_star, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = eveningDojiStar_lookback, + expected = evening_doji_star_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_CDLEVENINGSTAR.R b/tests/testthat/test-ta_CDLEVENINGSTAR.R index a8a232d0a..2ec4d9af4 100644 --- a/tests/testthat/test-ta_CDLEVENINGSTAR.R +++ b/tests/testthat/test-ta_CDLEVENINGSTAR.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- eveningStar(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = evening_star, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = eveningStar_lookback, + expected = evening_star_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_CDLGAPSIDESIDEWHITE.R b/tests/testthat/test-ta_CDLGAPSIDESIDEWHITE.R index 10e7f8a07..0ec6abfa4 100644 --- a/tests/testthat/test-ta_CDLGAPSIDESIDEWHITE.R +++ b/tests/testthat/test-ta_CDLGAPSIDESIDEWHITE.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- gapsSideWhite(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = gaps_side_white, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = gapsSideWhite_lookback, + expected = gaps_side_white_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_CDLGRAVESTONEDOJI.R b/tests/testthat/test-ta_CDLGRAVESTONEDOJI.R index 160936539..d1bc22eb1 100644 --- a/tests/testthat/test-ta_CDLGRAVESTONEDOJI.R +++ b/tests/testthat/test-ta_CDLGRAVESTONEDOJI.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- gravestoneDoji(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = gravestone_doji, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = gravestoneDoji_lookback, + expected = gravestone_doji_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_CDLHAMMER.R b/tests/testthat/test-ta_CDLHAMMER.R index 047e42d2e..7d9407e32 100644 --- a/tests/testthat/test-ta_CDLHAMMER.R +++ b/tests/testthat/test-ta_CDLHAMMER.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -144,6 +144,19 @@ 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(x = 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..6676e75df 100644 --- a/tests/testthat/test-ta_CDLHANGINGMAN.R +++ b/tests/testthat/test-ta_CDLHANGINGMAN.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- hangingMan(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = hanging_man, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = hangingMan_lookback, + expected = hanging_man_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_CDLHARAMI.R b/tests/testthat/test-ta_CDLHARAMI.R index 7ee501a58..4180a6b23 100644 --- a/tests/testthat/test-ta_CDLHARAMI.R +++ b/tests/testthat/test-ta_CDLHARAMI.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -144,6 +144,19 @@ 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(x = 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..22e33aee8 100644 --- a/tests/testthat/test-ta_CDLHARAMICROSS.R +++ b/tests/testthat/test-ta_CDLHARAMICROSS.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- haramiCross(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = harami_cross, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = haramiCross_lookback, + expected = harami_cross_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_CDLHIGHWAVE.R b/tests/testthat/test-ta_CDLHIGHWAVE.R index d928d8fc6..2db4ab2ac 100644 --- a/tests/testthat/test-ta_CDLHIGHWAVE.R +++ b/tests/testthat/test-ta_CDLHIGHWAVE.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- highWave(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = high_wave, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = highWave_lookback, + expected = high_wave_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_CDLHIKKAKE.R b/tests/testthat/test-ta_CDLHIKKAKE.R index a1639124e..4d7547392 100644 --- a/tests/testthat/test-ta_CDLHIKKAKE.R +++ b/tests/testthat/test-ta_CDLHIKKAKE.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -144,6 +144,19 @@ 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(x = 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..5d598d585 100644 --- a/tests/testthat/test-ta_CDLHIKKAKEMOD.R +++ b/tests/testthat/test-ta_CDLHIKKAKEMOD.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- hikakkeMod(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = hikakke_mod, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = hikakkeMod_lookback, + expected = hikakke_mod_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_CDLHOMINGPIGEON.R b/tests/testthat/test-ta_CDLHOMINGPIGEON.R index c2ea37eca..c24bffaf4 100644 --- a/tests/testthat/test-ta_CDLHOMINGPIGEON.R +++ b/tests/testthat/test-ta_CDLHOMINGPIGEON.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- homingPigeon(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = homing_pigeon, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = homingPigeon_lookback, + expected = homing_pigeon_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_CDLIDENTICAL3CROWS.R b/tests/testthat/test-ta_CDLIDENTICAL3CROWS.R index c001ea8f4..7976fe6c9 100644 --- a/tests/testthat/test-ta_CDLIDENTICAL3CROWS.R +++ b/tests/testthat/test-ta_CDLIDENTICAL3CROWS.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- threeIdenticalCrows(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = three_identical_crows, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = threeIdenticalCrows_lookback, + expected = three_identical_crows_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_CDLINNECK.R b/tests/testthat/test-ta_CDLINNECK.R index 17b847b8e..00786c55b 100644 --- a/tests/testthat/test-ta_CDLINNECK.R +++ b/tests/testthat/test-ta_CDLINNECK.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- inNeck(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = in_neck, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = inNeck_lookback, + expected = in_neck_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_CDLINVERTEDHAMMER.R b/tests/testthat/test-ta_CDLINVERTEDHAMMER.R index 5a72d69e9..91736f76d 100644 --- a/tests/testthat/test-ta_CDLINVERTEDHAMMER.R +++ b/tests/testthat/test-ta_CDLINVERTEDHAMMER.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- invertedHammer(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = inverted_hammer, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = invertedHammer_lookback, + expected = inverted_hammer_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_CDLKICKING.R b/tests/testthat/test-ta_CDLKICKING.R index 54e26ba44..5a8fd173d 100644 --- a/tests/testthat/test-ta_CDLKICKING.R +++ b/tests/testthat/test-ta_CDLKICKING.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -144,6 +144,19 @@ 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(x = 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..8f4aa7b4f 100644 --- a/tests/testthat/test-ta_CDLKICKINGBYLENGTH.R +++ b/tests/testthat/test-ta_CDLKICKINGBYLENGTH.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- kickingBabyLength(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = kicking_baby_length, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = kickingBabyLength_lookback, + expected = kicking_baby_length_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_CDLLADDERBOTTOM.R b/tests/testthat/test-ta_CDLLADDERBOTTOM.R index 75d5b4bc9..0bc5eddfb 100644 --- a/tests/testthat/test-ta_CDLLADDERBOTTOM.R +++ b/tests/testthat/test-ta_CDLLADDERBOTTOM.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- ladderBottom(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = ladder_bottom, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = ladderBottom_lookback, + expected = ladder_bottom_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_CDLLONGLEGGEDDOJI.R b/tests/testthat/test-ta_CDLLONGLEGGEDDOJI.R index 353ca3b28..0f206eec4 100644 --- a/tests/testthat/test-ta_CDLLONGLEGGEDDOJI.R +++ b/tests/testthat/test-ta_CDLLONGLEGGEDDOJI.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- longLeggedDoji(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = long_legged_doji, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = longLeggedDoji_lookback, + expected = long_legged_doji_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_CDLLONGLINE.R b/tests/testthat/test-ta_CDLLONGLINE.R index 8982d3e8e..5738cb65e 100644 --- a/tests/testthat/test-ta_CDLLONGLINE.R +++ b/tests/testthat/test-ta_CDLLONGLINE.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- longLine(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = long_line, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = longLine_lookback, + expected = long_line_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_CDLMARUBOZU.R b/tests/testthat/test-ta_CDLMARUBOZU.R index 2aa85275b..20cc3f005 100644 --- a/tests/testthat/test-ta_CDLMARUBOZU.R +++ b/tests/testthat/test-ta_CDLMARUBOZU.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -144,6 +144,19 @@ 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(x = 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..5e48bedc4 100644 --- a/tests/testthat/test-ta_CDLMATCHINGLOW.R +++ b/tests/testthat/test-ta_CDLMATCHINGLOW.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- matchingLow(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = matching_low, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = matchingLow_lookback, + expected = matching_low_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_CDLMATHOLD.R b/tests/testthat/test-ta_CDLMATHOLD.R index 3061c6f99..60ba87730 100644 --- a/tests/testthat/test-ta_CDLMATHOLD.R +++ b/tests/testthat/test-ta_CDLMATHOLD.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- matHold(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = mat_hold, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = matHold_lookback, + expected = mat_hold_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_CDLMORNINGDOJISTAR.R b/tests/testthat/test-ta_CDLMORNINGDOJISTAR.R index 4e9d131eb..19e9194e8 100644 --- a/tests/testthat/test-ta_CDLMORNINGDOJISTAR.R +++ b/tests/testthat/test-ta_CDLMORNINGDOJISTAR.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- morningDojiStar(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = morning_doji_star, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = morningDojiStar_lookback, + expected = morning_doji_star_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_CDLMORNINGSTAR.R b/tests/testthat/test-ta_CDLMORNINGSTAR.R index fb04a8d47..6073fe73f 100644 --- a/tests/testthat/test-ta_CDLMORNINGSTAR.R +++ b/tests/testthat/test-ta_CDLMORNINGSTAR.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- morningStar(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = morning_star, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = morningStar_lookback, + expected = morning_star_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_CDLONNECK.R b/tests/testthat/test-ta_CDLONNECK.R index a18cf4f92..372497f18 100644 --- a/tests/testthat/test-ta_CDLONNECK.R +++ b/tests/testthat/test-ta_CDLONNECK.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- onNeck(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = on_neck, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = onNeck_lookback, + expected = on_neck_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_CDLPIERCING.R b/tests/testthat/test-ta_CDLPIERCING.R index 118b1041a..035b20694 100644 --- a/tests/testthat/test-ta_CDLPIERCING.R +++ b/tests/testthat/test-ta_CDLPIERCING.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -144,6 +144,19 @@ 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(x = 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..da0fb5026 100644 --- a/tests/testthat/test-ta_CDLRICKSHAWMAN.R +++ b/tests/testthat/test-ta_CDLRICKSHAWMAN.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- rickshawMan(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = rickshaw_man, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = rickshawMan_lookback, + expected = rickshaw_man_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_CDLRISEFALL3METHODS.R b/tests/testthat/test-ta_CDLRISEFALL3METHODS.R index 4a9f7fe73..eb82b9560 100644 --- a/tests/testthat/test-ta_CDLRISEFALL3METHODS.R +++ b/tests/testthat/test-ta_CDLRISEFALL3METHODS.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- riseFall3Methods(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = rise_fall_3_methods, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = riseFall3Methods_lookback, + expected = rise_fall_3_methods_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_CDLSEPARATINGLINES.R b/tests/testthat/test-ta_CDLSEPARATINGLINES.R index 7756e474b..98635fc50 100644 --- a/tests/testthat/test-ta_CDLSEPARATINGLINES.R +++ b/tests/testthat/test-ta_CDLSEPARATINGLINES.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- separatingLines(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = separating_lines, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = separatingLines_lookback, + expected = separating_lines_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_CDLSHOOTINGSTAR.R b/tests/testthat/test-ta_CDLSHOOTINGSTAR.R index 7af511f6d..93739a5ac 100644 --- a/tests/testthat/test-ta_CDLSHOOTINGSTAR.R +++ b/tests/testthat/test-ta_CDLSHOOTINGSTAR.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- shootingStar(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = shooting_star, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = shootingStar_lookback, + expected = shooting_star_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_CDLSHORTLINE.R b/tests/testthat/test-ta_CDLSHORTLINE.R index b98f773be..07f1f8305 100644 --- a/tests/testthat/test-ta_CDLSHORTLINE.R +++ b/tests/testthat/test-ta_CDLSHORTLINE.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- shortLine(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = short_line, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = shortLine_lookback, + expected = short_line_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_CDLSPINNINGTOP.R b/tests/testthat/test-ta_CDLSPINNINGTOP.R index 6bd2ec372..0a32c4408 100644 --- a/tests/testthat/test-ta_CDLSPINNINGTOP.R +++ b/tests/testthat/test-ta_CDLSPINNINGTOP.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- spinningTop(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = spinning_top, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = spinningTop_lookback, + expected = spinning_top_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_CDLSTALLEDPATTERN.R b/tests/testthat/test-ta_CDLSTALLEDPATTERN.R index 7e2bdff9f..e5c9c393f 100644 --- a/tests/testthat/test-ta_CDLSTALLEDPATTERN.R +++ b/tests/testthat/test-ta_CDLSTALLEDPATTERN.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- stalledPattern(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = stalled_pattern, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = stalledPattern_lookback, + expected = stalled_pattern_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_CDLSTICKSANDWICH.R b/tests/testthat/test-ta_CDLSTICKSANDWICH.R index a083b6598..afd8436ae 100644 --- a/tests/testthat/test-ta_CDLSTICKSANDWICH.R +++ b/tests/testthat/test-ta_CDLSTICKSANDWICH.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- stickSandwich(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = stick_sandwich, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = stickSandwich_lookback, + expected = stick_sandwich_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_CDLTAKURI.R b/tests/testthat/test-ta_CDLTAKURI.R index ca4ddf6c1..eac53b76d 100644 --- a/tests/testthat/test-ta_CDLTAKURI.R +++ b/tests/testthat/test-ta_CDLTAKURI.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -144,6 +144,19 @@ 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(x = 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..a6a9c01c0 100644 --- a/tests/testthat/test-ta_CDLTASUKIGAP.R +++ b/tests/testthat/test-ta_CDLTASUKIGAP.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- tasukiGap(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = tasuki_gap, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = tasukiGap_lookback, + expected = tasuki_gap_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_CDLTHRUSTING.R b/tests/testthat/test-ta_CDLTHRUSTING.R index 775b2c9fa..abf172840 100644 --- a/tests/testthat/test-ta_CDLTHRUSTING.R +++ b/tests/testthat/test-ta_CDLTHRUSTING.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -144,6 +144,19 @@ 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(x = 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..111ae2979 100644 --- a/tests/testthat/test-ta_CDLTRISTAR.R +++ b/tests/testthat/test-ta_CDLTRISTAR.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -144,6 +144,19 @@ 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(x = 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..060e0bdf3 100644 --- a/tests/testthat/test-ta_CDLUNIQUE3RIVER.R +++ b/tests/testthat/test-ta_CDLUNIQUE3RIVER.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- unique3River(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = unique_3_river, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = unique3River_lookback, + expected = unique_3_river_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_CDLUPSIDEGAP2CROWS.R b/tests/testthat/test-ta_CDLUPSIDEGAP2CROWS.R index cb8d12ad3..3b9064fab 100644 --- a/tests/testthat/test-ta_CDLUPSIDEGAP2CROWS.R +++ b/tests/testthat/test-ta_CDLUPSIDEGAP2CROWS.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- upsideGap2Crows(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = upside_gap_2_crows, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = upsideGap2Crows_lookback, + expected = upside_gap_2_crows_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_CDLXSIDEGAP3METHODS.R b/tests/testthat/test-ta_CDLXSIDEGAP3METHODS.R index f4b20b9e0..560702e9d 100644 --- a/tests/testthat/test-ta_CDLXSIDEGAP3METHODS.R +++ b/tests/testthat/test-ta_CDLXSIDEGAP3METHODS.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- xsideGap3Methods(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = xside_gap_3_methods, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = xsideGap3Methods_lookback, + expected = xside_gap_3_methods_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_CMO.R b/tests/testthat/test-ta_CMO.R index 41d42161d..60309aaf8 100644 --- a/tests/testthat/test-ta_CMO.R +++ b/tests/testthat/test-ta_CMO.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- chandeMomentumOscillator(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = chande_momentum_oscillator, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = chandeMomentumOscillator_lookback, + expected = chande_momentum_oscillator_lookback + ) +}) ## -method checks for ## and @@ -240,18 +271,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..1eac60c59 100644 --- a/tests/testthat/test-ta_CORREL.R +++ b/tests/testthat/test-ta_CORREL.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -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_correlation(x = SPY[, 1], y = SPY[, 2]), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = rolling_correlation, x = SPY[, 1]) ) }) diff --git a/tests/testthat/test-ta_DEMA.R b/tests/testthat/test-ta_DEMA.R index 9ee69bfc8..8fd321bb1 100644 --- a/tests/testthat/test-ta_DEMA.R +++ b/tests/testthat/test-ta_DEMA.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- doubleExponentialMovingAverage(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = double_exponential_moving_average, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = doubleExponentialMovingAverage_lookback, + expected = double_exponential_moving_average_lookback + ) +}) ## -method checks for ## and @@ -240,18 +271,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..9948141cb 100644 --- a/tests/testthat/test-ta_DX.R +++ b/tests/testthat/test-ta_DX.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- directionalMovementIndex(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = directional_movement_index, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = directionalMovementIndex_lookback, + expected = directional_movement_index_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_EMA.R b/tests/testthat/test-ta_EMA.R index 4803a1540..50f493f8d 100644 --- a/tests/testthat/test-ta_EMA.R +++ b/tests/testthat/test-ta_EMA.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- exponentialMovingAverage(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = exponential_moving_average, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = exponentialMovingAverage_lookback, + expected = exponential_moving_average_lookback + ) +}) ## -method checks for ## and @@ -240,18 +271,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..4cd8490f4 100644 --- a/tests/testthat/test-ta_HT_DCPERIOD.R +++ b/tests/testthat/test-ta_HT_DCPERIOD.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- dominantCyclePeriod(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = dominant_cycle_period, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = dominantCyclePeriod_lookback, + expected = dominant_cycle_period_lookback + ) +}) ## -method checks for ## and @@ -240,18 +271,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..06680bd3b 100644 --- a/tests/testthat/test-ta_HT_DCPHASE.R +++ b/tests/testthat/test-ta_HT_DCPHASE.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- dominantCyclePhase(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = dominant_cycle_phase, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = dominantCyclePhase_lookback, + expected = dominant_cycle_phase_lookback + ) +}) ## -method checks for ## and @@ -240,18 +271,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..d68729c49 100644 --- a/tests/testthat/test-ta_HT_PHASOR.R +++ b/tests/testthat/test-ta_HT_PHASOR.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- phasorComponents(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = phasor_components, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = phasorComponents_lookback, + expected = phasor_components_lookback + ) +}) ## -method checks for ## and @@ -240,18 +271,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..9aeb09ada 100644 --- a/tests/testthat/test-ta_HT_SINE.R +++ b/tests/testthat/test-ta_HT_SINE.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- sineWave(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = sine_wave, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = sineWave_lookback, + expected = sine_wave_lookback + ) +}) ## -method checks for ## and @@ -240,18 +271,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..6d6c694e0 100644 --- a/tests/testthat/test-ta_HT_TRENDLINE.R +++ b/tests/testthat/test-ta_HT_TRENDLINE.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -144,6 +144,19 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = trendline, x = SPY) + ) +}) ## -method checks for ## and @@ -240,18 +253,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..7606d6f7e 100644 --- a/tests/testthat/test-ta_HT_TRENDMODE.R +++ b/tests/testthat/test-ta_HT_TRENDMODE.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- trendCycleMode(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = trend_cycle_mode, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = trendCycleMode_lookback, + expected = trend_cycle_mode_lookback + ) +}) ## -method checks for ## and @@ -240,18 +271,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..bc1f760e7 100644 --- a/tests/testthat/test-ta_IMI.R +++ b/tests/testthat/test-ta_IMI.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- intradayMovementIndex(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = intraday_movement_index, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = intradayMovementIndex_lookback, + expected = intraday_movement_index_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_KAMA.R b/tests/testthat/test-ta_KAMA.R index f93fb9efb..802cc02b1 100644 --- a/tests/testthat/test-ta_KAMA.R +++ b/tests/testthat/test-ta_KAMA.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- kaufmanAdaptiveMovingAverage(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = kaufman_adaptive_moving_average, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = kaufmanAdaptiveMovingAverage_lookback, + expected = kaufman_adaptive_moving_average_lookback + ) +}) ## -method checks for ## and @@ -240,18 +271,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..461f9d724 100644 --- a/tests/testthat/test-ta_MACD.R +++ b/tests/testthat/test-ta_MACD.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- movingAverageConvergenceDivergence(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,29 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback( + FUN = moving_average_convergence_divergence, + x = SPY + ) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = movingAverageConvergenceDivergence_lookback, + expected = moving_average_convergence_divergence_lookback + ) +}) ## -method checks for ## and @@ -240,18 +274,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..ee5bf6b7c 100644 --- a/tests/testthat/test-ta_MACDEXT.R +++ b/tests/testthat/test-ta_MACDEXT.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- extendedMovingAverageConvergenceDivergence(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -153,6 +164,29 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback( + FUN = extended_moving_average_convergence_divergence, + x = SPY + ) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = extendedMovingAverageConvergenceDivergence_lookback, + expected = extended_moving_average_convergence_divergence_lookback + ) +}) ## -method checks for ## and @@ -249,18 +283,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..962c1ff8e 100644 --- a/tests/testthat/test-ta_MACDFIX.R +++ b/tests/testthat/test-ta_MACDFIX.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- fixedMovingAverageConvergenceDivergence(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -147,6 +158,29 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback( + FUN = fixed_moving_average_convergence_divergence, + x = SPY + ) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = fixedMovingAverageConvergenceDivergence_lookback, + expected = fixed_moving_average_convergence_divergence_lookback + ) +}) ## -method checks for ## and @@ -243,18 +277,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..45b82b846 100644 --- a/tests/testthat/test-ta_MAMA.R +++ b/tests/testthat/test-ta_MAMA.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- mesaAdaptiveMovingAverage(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = mesa_adaptive_moving_average, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = mesaAdaptiveMovingAverage_lookback, + expected = mesa_adaptive_moving_average_lookback + ) +}) ## -method checks for ## and @@ -240,18 +271,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/codegen/generate_unit-tests.sh b/tests/testthat/test-ta_MAVP.R old mode 100755 new mode 100644 similarity index 58% rename from codegen/generate_unit-tests.sh rename to tests/testthat/test-ta_MAVP.R index 07e5dd983..fdea4cadb --- a/codegen/generate_unit-tests.sh +++ b/tests/testthat/test-ta_MAVP.R @@ -1,111 +1,35 @@ -#!/usr/bin/env bash -set -euo pipefail - -## 1) environment variables -## to determine unit-tests -FUN=${FUN:?} -TA_FUN=${TA_FUN:?} -ALIAS=${ALIAS:-$TA_FUN} -FORMULA=${FORMULA:-"~close"} -PLOTLY=${PLOTLY:-0} -NUMERIC=${NUMERIC:-1} -OUTPUTFILE=${OUTPUTFILE:-"tests/testthat/test-ta_${TA_FUN}.R"} -ROLLING=${ROLLING:-0} - -## 2) fast-track exiting of the -## program for rolling statistics -if [[ $ROLLING -eq 1 ]]; then - -## 2.2) check if the signature includes -## a 'y' and set it to SPY[[2]] -ADDITIONAL='' - for a in "$@"; do - case "$a" in - y|y=*) ADDITIONAL=',y=SPY[,2]'; break ;; - esac -done - -cat > ${OUTPUTFILE} << EOF ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration -## -## author: Serkan Korkmaz - -## test that the function runs without -## any conditions -testthat::test_that(desc = 'Runs without *any* conditions', code = { - - output <- testthat::expect_no_condition( - { - ${FUN}( - x = SPY[,1]${ADDITIONAL} - ) - } - ) -}) - -## test that the length of the input -## matches the output -testthat::test_that(desc = 'Length in, length out', code = { - testthat::expect_equal( - object = length( - ${FUN}( - x = SPY[,1]${ADDITIONAL} - ) - ), - expected = length(SPY[,1]) - ) -}) - -## test that the output is a vector -testthat::test_that(desc = 'Output type', code = { - -output <- ${FUN}( - x = SPY[,1]${ADDITIONAL} - ) - -testthat::expect_true( - typeof(output) == "double" - ) - - testthat::expect_true( - is.vector(output) - ) - -}) - -EOF - -exit 0; -fi - -## 1) populate test file -## with standard stuff -cat > ${OUTPUTFILE} < object @@ -126,7 +52,10 @@ testthat::test_that(desc = 'Class in, class out ()', code = { ## 1) check that the output class ## matches the input class testthat::expect_true( - inherits(${FUN}(BTC), class(BTC)) + inherits( + variable_moving_average_period(BTC, periods = rep(5, nrow(BTC))), + class(BTC) + ) ) }) @@ -137,13 +66,15 @@ testthat::test_that(desc = 'Class in, class out ()', code = { ## NOTE: This test is more of a test of the internal ## series() function testthat::test_that(desc = 'Default calls', code = { - testthat::expect_equal( - object = ${FUN}( - BTC + testthat::expect_equal( + object = variable_moving_average_period( + BTC, + periods = rep(5, nrow(BTC)) ), - expected = ${FUN}( + expected = variable_moving_average_period( BTC, - cols = ${FORMULA} + cols = ~close, + periods = rep(5, nrow(BTC)) ) ) }) @@ -153,9 +84,10 @@ testthat::test_that(desc = 'Default calls', code = { ## ## object testthat::test_that(desc = 'Equal length of input and output for with na.bridge = TRUE', code = { - testthat::expect_equal( - object = nrow(${FUN}( + testthat::expect_equal( + object = nrow(variable_moving_average_period( ATOM, + periods = rep(5, nrow(ATOM)), na.bridge = TRUE )), expected = nrow(ATOM) @@ -169,9 +101,13 @@ testthat::test_that(desc = 'Row names are respected for , na.bridge x_names <- row.names(ATOM) ## calculate indicator - indicator <- ${FUN}(ATOM, na.bridge = TRUE) + indicator <- variable_moving_average_period( + ATOM, + periods = rep(5, nrow(ATOM)), + na.bridge = TRUE + ) - testthat::expect_equal( + testthat::expect_equal( object = x_names, expected = rownames(indicator) ) @@ -182,9 +118,10 @@ testthat::test_that(desc = 'Row names are respected for , na.bridge ## ## object testthat::test_that(desc = 'Equal length of input and output for ', code = { - testthat::expect_equal( - object = nrow(${FUN}( - BTC + testthat::expect_equal( + object = nrow(variable_moving_average_period( + BTC, + periods = rep(5, nrow(BTC)) )), expected = nrow(BTC) ) @@ -197,9 +134,12 @@ testthat::test_that(desc = 'Row names are respected for ', code = { x_names <- row.names(BTC) ## calculate indicator - indicator <- ${FUN}(BTC) + indicator <- variable_moving_average_period( + BTC, + periods = rep(5, nrow(BTC)) + ) - testthat::expect_equal( + testthat::expect_equal( object = x_names, expected = rownames(indicator) ) @@ -207,9 +147,10 @@ testthat::test_that(desc = 'Row names are respected for ', code = { ## object testthat::test_that(desc = 'Equal length of input and output for ', code = { - testthat::expect_equal( - object = nrow(${FUN}( - SPY + testthat::expect_equal( + object = nrow(variable_moving_average_period( + SPY, + periods = rep(5, nrow(SPY)) )), expected = nrow(SPY) ) @@ -221,34 +162,59 @@ testthat::test_that(desc = 'Row names are respected for ', code = { ## extract row names ## NOTE: by default the SPY has no ## rownames - rownames(SPY) <- paste0("row",1:nrow(SPY)) + rownames(SPY) <- paste0("row", 1:nrow(SPY)) ## calculate indicator - indicator <- ${FUN}(SPY) + indicator <- variable_moving_average_period( + SPY, + periods = rep(5, nrow(SPY)) + ) - testthat::expect_equal( - object = paste0("row",1:nrow(SPY)), + testthat::expect_equal( + object = paste0("row", 1:nrow(SPY)), expected = rownames(indicator) ) }) -EOF +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + variable_moving_average_period(x = SPY, periods = rep(5, nrow(SPY))), + "lookback" + ) -## Add plotly methods -if [[ $PLOTLY -eq 1 ]]; then - cat >> ${OUTPUTFILE} <-method checks for ## and -## +## ## checks testthat::test_that(desc = '-methods for ', code = { - ## check that ${FUN} can + ## check that variable_moving_average_period can ## use without any issues output <- testthat::expect_no_error( { chart(BTC) - indicator(${FUN}) + indicator( + variable_moving_average_period, + periods = rep(5, nrow(BTC)) + ) } ) @@ -261,12 +227,15 @@ testthat::test_that(desc = '-methods for ', code = { ## checks testthat::test_that(desc = '-methods for ', code = { - ## check that ${FUN} can + ## check that variable_moving_average_period can ## use without any issues output <- testthat::expect_no_error( { chart(SPY) - indicator(${FUN}) + indicator( + variable_moving_average_period, + periods = rep(5, nrow(SPY)) + ) } ) @@ -276,12 +245,6 @@ testthat::test_that(desc = '-methods for ', code = { inherits(output, "plotly") ) }) -EOF -fi - -## Add ggplot2 methods -if [[ $PLOTLY -eq 1 ]]; then - cat >> ${OUTPUTFILE} <-method checks for ## and @@ -290,14 +253,17 @@ if [[ $PLOTLY -eq 1 ]]; then testthat::test_that(desc = '-methods for ', code = { testthat::skip_if_not_installed("ggplot2") - ## check that ${FUN} can + ## check that variable_moving_average_period can ## use without any issues output <- testthat::expect_no_error( { options(talib.chart.backend = "ggplot2") on.exit(options(talib.chart.backend = "plotly")) chart(BTC) - indicator(${FUN}) + indicator( + variable_moving_average_period, + periods = rep(5, nrow(BTC)) + ) } ) @@ -312,14 +278,17 @@ testthat::test_that(desc = '-methods for ', code = { testthat::test_that(desc = '-methods for ', code = { testthat::skip_if_not_installed("ggplot2") - ## check that ${FUN} can + ## check that variable_moving_average_period can ## use without any issues output <- testthat::expect_no_error( { options(talib.chart.backend = "ggplot2") on.exit(options(talib.chart.backend = "plotly")) chart(SPY) - indicator(${FUN}) + indicator( + variable_moving_average_period, + periods = rep(5, nrow(SPY)) + ) } ) @@ -329,12 +298,6 @@ testthat::test_that(desc = '-methods for ', code = { inherits(output, "gg") || inherits(output, "talib_chart") ) }) -EOF -fi - -## add methods -if [[ $NUMERIC -eq 1 ]]; then - cat >> ${OUTPUTFILE} < methods runs without ## issues and returns proper lengths @@ -342,23 +305,17 @@ testthat::test_that(desc = ' methods', code = { ## check that the method ## runs x <- testthat::expect_no_condition( - ${FUN}(BTC[[1]]) + variable_moving_average_period(BTC[[1]], periods = rep(5, nrow(BTC))) ) - ## 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 diff --git a/tests/testthat/test-ta_MAX.R b/tests/testthat/test-ta_MAX.R index 73163c431..4e502374c 100644 --- a/tests/testthat/test-ta_MAX.R +++ b/tests/testthat/test-ta_MAX.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -9,7 +9,7 @@ testthat::test_that(desc = 'Runs without *any* conditions', code = { output <- testthat::expect_no_condition( { - rolling_max( + rolling_maximum( x = SPY[, 1] ) } @@ -21,7 +21,7 @@ testthat::test_that(desc = 'Runs without *any* conditions', code = { testthat::test_that(desc = 'Length in, length out', code = { testthat::expect_equal( object = length( - rolling_max( + rolling_maximum( x = SPY[, 1] ) ), @@ -31,15 +31,29 @@ testthat::test_that(desc = 'Length in, length out', code = { ## test that the output is a vector testthat::test_that(desc = 'Output type', code = { - output <- rolling_max( + output <- rolling_maximum( x = SPY[, 1] ) 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_maximum(x = SPY[, 1]), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = rolling_maximum, x = SPY[, 1]) ) }) diff --git a/tests/testthat/test-ta_MEDPRICE.R b/tests/testthat/test-ta_MEDPRICE.R index a3268f1ec..3feef755a 100644 --- a/tests/testthat/test-ta_MEDPRICE.R +++ b/tests/testthat/test-ta_MEDPRICE.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- medianPrice(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -143,3 +154,24 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = median_price, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = medianPrice_lookback, + expected = median_price_lookback + ) +}) diff --git a/tests/testthat/test-ta_MFI.R b/tests/testthat/test-ta_MFI.R index b6f832c39..984f257e2 100644 --- a/tests/testthat/test-ta_MFI.R +++ b/tests/testthat/test-ta_MFI.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- moneyFlowIndex(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = money_flow_index, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = moneyFlowIndex_lookback, + expected = money_flow_index_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_ROC.R b/tests/testthat/test-ta_MIDPOINT.R similarity index 74% rename from tests/testthat/test-ta_ROC.R rename to tests/testthat/test-ta_MIDPOINT.R index b17ac22a3..2431486bc 100644 --- a/tests/testthat/test-ta_ROC.R +++ b/tests/testthat/test-ta_MIDPOINT.R @@ -1,17 +1,17 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz ## alias and function similarity ## checks this ensures that -## rate_of_change and ROC produces the same results +## midpoint_period and MIDPOINT produces the same results testthat::test_that(desc = 'Alias and function similarity', code = { ## 1) test that the alias and ## function returns the same values - output <- rate_of_change(SPY) - alias <- ROC(SPY) + output <- midpoint_period(SPY) + alias <- MIDPOINT(SPY) ## 1.1) check if the values ## are equal @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- midpointPeriod(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -29,7 +40,7 @@ testthat::test_that(desc = 'Class in, class out ()', code = { ## 1) check that the output class ## matches the input class testthat::expect_true( - inherits(rate_of_change(SPY), class(SPY)) + inherits(midpoint_period(SPY), class(SPY)) ) }) @@ -38,7 +49,7 @@ testthat::test_that(desc = 'Class in, class out ()', code = { ## 1) check that the output class ## matches the input class testthat::expect_true( - inherits(rate_of_change(BTC), class(BTC)) + inherits(midpoint_period(BTC), class(BTC)) ) }) @@ -50,10 +61,10 @@ testthat::test_that(desc = 'Class in, class out ()', code = { ## series() function testthat::test_that(desc = 'Default calls', code = { testthat::expect_equal( - object = rate_of_change( + object = midpoint_period( BTC ), - expected = rate_of_change( + expected = midpoint_period( BTC, cols = ~close ) @@ -66,7 +77,7 @@ testthat::test_that(desc = 'Default calls', code = { ## object testthat::test_that(desc = 'Equal length of input and output for with na.bridge = TRUE', code = { testthat::expect_equal( - object = nrow(rate_of_change( + object = nrow(midpoint_period( ATOM, na.bridge = TRUE )), @@ -81,7 +92,7 @@ testthat::test_that(desc = 'Row names are respected for , na.bridge x_names <- row.names(ATOM) ## calculate indicator - indicator <- rate_of_change(ATOM, na.bridge = TRUE) + indicator <- midpoint_period(ATOM, na.bridge = TRUE) testthat::expect_equal( object = x_names, @@ -95,7 +106,7 @@ testthat::test_that(desc = 'Row names are respected for , na.bridge ## object testthat::test_that(desc = 'Equal length of input and output for ', code = { testthat::expect_equal( - object = nrow(rate_of_change( + object = nrow(midpoint_period( BTC )), expected = nrow(BTC) @@ -109,7 +120,7 @@ testthat::test_that(desc = 'Row names are respected for ', code = { x_names <- row.names(BTC) ## calculate indicator - indicator <- rate_of_change(BTC) + indicator <- midpoint_period(BTC) testthat::expect_equal( object = x_names, @@ -120,7 +131,7 @@ testthat::test_that(desc = 'Row names are respected for ', code = { ## object testthat::test_that(desc = 'Equal length of input and output for ', code = { testthat::expect_equal( - object = nrow(rate_of_change( + object = nrow(midpoint_period( SPY )), expected = nrow(SPY) @@ -136,7 +147,7 @@ testthat::test_that(desc = 'Row names are respected for ', code = { rownames(SPY) <- paste0("row", 1:nrow(SPY)) ## calculate indicator - indicator <- rate_of_change(SPY) + indicator <- midpoint_period(SPY) testthat::expect_equal( object = paste0("row", 1:nrow(SPY)), @@ -144,18 +155,38 @@ 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( + midpoint_period(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = midpoint_period, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = midpointPeriod_lookback, + expected = midpoint_period_lookback + ) +}) ## -method checks for ## and ## ## checks testthat::test_that(desc = '-methods for ', code = { - ## check that rate_of_change can + ## check that midpoint_period can ## use without any issues output <- testthat::expect_no_error( { chart(BTC) - indicator(rate_of_change) + indicator(midpoint_period) } ) @@ -168,12 +199,12 @@ testthat::test_that(desc = '-methods for ', code = { ## checks testthat::test_that(desc = '-methods for ', code = { - ## check that rate_of_change can + ## check that midpoint_period can ## use without any issues output <- testthat::expect_no_error( { chart(SPY) - indicator(rate_of_change) + indicator(midpoint_period) } ) @@ -191,14 +222,14 @@ testthat::test_that(desc = '-methods for ', code = { testthat::test_that(desc = '-methods for ', code = { testthat::skip_if_not_installed("ggplot2") - ## check that rate_of_change can + ## check that midpoint_period can ## use without any issues output <- testthat::expect_no_error( { options(talib.chart.backend = "ggplot2") on.exit(options(talib.chart.backend = "plotly")) chart(BTC) - indicator(rate_of_change) + indicator(midpoint_period) } ) @@ -213,14 +244,14 @@ testthat::test_that(desc = '-methods for ', code = { testthat::test_that(desc = '-methods for ', code = { testthat::skip_if_not_installed("ggplot2") - ## check that rate_of_change can + ## check that midpoint_period can ## use without any issues output <- testthat::expect_no_error( { options(talib.chart.backend = "ggplot2") on.exit(options(talib.chart.backend = "plotly")) chart(SPY) - indicator(rate_of_change) + indicator(midpoint_period) } ) @@ -237,21 +268,17 @@ testthat::test_that(desc = ' methods', code = { ## check that the method ## runs x <- testthat::expect_no_condition( - rate_of_change(BTC[[1]]) + midpoint_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_MIDPRICE.R b/tests/testthat/test-ta_MIDPRICE.R index 3b0ff3d34..d7427f7b4 100644 --- a/tests/testthat/test-ta_MIDPRICE.R +++ b/tests/testthat/test-ta_MIDPRICE.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- midpointPrice(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -143,3 +154,110 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = midpoint_price, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = midpointPrice_lookback, + expected = midpoint_price_lookback + ) +}) + +## -method checks for +## and +## +## checks +testthat::test_that(desc = '-methods for ', code = { + ## check that midpoint_price can + ## use without any issues + output <- testthat::expect_no_error( + { + chart(BTC) + indicator(midpoint_price) + } + ) + + ## check that the output + ## is a -object + testthat::expect_true( + inherits(output, "plotly") + ) +}) + +## checks +testthat::test_that(desc = '-methods for ', code = { + ## check that midpoint_price can + ## use without any issues + output <- testthat::expect_no_error( + { + chart(SPY) + indicator(midpoint_price) + } + ) + + ## check that the output + ## is a -object + testthat::expect_true( + inherits(output, "plotly") + ) +}) + +## -method checks for +## and +## +## checks +testthat::test_that(desc = '-methods for ', code = { + testthat::skip_if_not_installed("ggplot2") + + ## check that midpoint_price can + ## use without any issues + output <- testthat::expect_no_error( + { + options(talib.chart.backend = "ggplot2") + on.exit(options(talib.chart.backend = "plotly")) + chart(BTC) + indicator(midpoint_price) + } + ) + + ## check that the output + ## is a -object or + testthat::expect_true( + inherits(output, "gg") || inherits(output, "talib_chart") + ) +}) + +## checks +testthat::test_that(desc = '-methods for ', code = { + testthat::skip_if_not_installed("ggplot2") + + ## check that midpoint_price can + ## use without any issues + output <- testthat::expect_no_error( + { + options(talib.chart.backend = "ggplot2") + on.exit(options(talib.chart.backend = "plotly")) + chart(SPY) + indicator(midpoint_price) + } + ) + + ## check that the output + ## is a -object or + testthat::expect_true( + inherits(output, "gg") || inherits(output, "talib_chart") + ) +}) diff --git a/tests/testthat/test-ta_MIN.R b/tests/testthat/test-ta_MIN.R index 2a412137f..e1f5194fb 100644 --- a/tests/testthat/test-ta_MIN.R +++ b/tests/testthat/test-ta_MIN.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -9,7 +9,7 @@ testthat::test_that(desc = 'Runs without *any* conditions', code = { output <- testthat::expect_no_condition( { - rolling_min( + rolling_minimum( x = SPY[, 1] ) } @@ -21,7 +21,7 @@ testthat::test_that(desc = 'Runs without *any* conditions', code = { testthat::test_that(desc = 'Length in, length out', code = { testthat::expect_equal( object = length( - rolling_min( + rolling_minimum( x = SPY[, 1] ) ), @@ -31,15 +31,29 @@ testthat::test_that(desc = 'Length in, length out', code = { ## test that the output is a vector testthat::test_that(desc = 'Output type', code = { - output <- rolling_min( + output <- rolling_minimum( x = SPY[, 1] ) 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_minimum(x = SPY[, 1]), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = rolling_minimum, x = SPY[, 1]) ) }) diff --git a/tests/testthat/test-ta_MINUS_DI.R b/tests/testthat/test-ta_MINUS_DI.R index a2d444dd9..0783afded 100644 --- a/tests/testthat/test-ta_MINUS_DI.R +++ b/tests/testthat/test-ta_MINUS_DI.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- minusDirectionalIndicator(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = minus_directional_indicator, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = minusDirectionalIndicator_lookback, + expected = minus_directional_indicator_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_MINUS_DM.R b/tests/testthat/test-ta_MINUS_DM.R index bd13137d1..12057c895 100644 --- a/tests/testthat/test-ta_MINUS_DM.R +++ b/tests/testthat/test-ta_MINUS_DM.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- minusDirectionalMovement(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = minus_directional_movement, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = minusDirectionalMovement_lookback, + expected = minus_directional_movement_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_MOM.R b/tests/testthat/test-ta_MOM.R index 7fa114c4f..f58f4781e 100644 --- a/tests/testthat/test-ta_MOM.R +++ b/tests/testthat/test-ta_MOM.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -144,6 +144,19 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = momentum, x = SPY) + ) +}) ## -method checks for ## and @@ -240,18 +253,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..7be93951c 100644 --- a/tests/testthat/test-ta_NATR.R +++ b/tests/testthat/test-ta_NATR.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- normalizedAverageTrueRange(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = normalized_average_true_range, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = normalizedAverageTrueRange_lookback, + expected = normalized_average_true_range_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_OBV.R b/tests/testthat/test-ta_OBV.R index e15438b2b..bb3efc449 100644 --- a/tests/testthat/test-ta_OBV.R +++ b/tests/testthat/test-ta_OBV.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- onBalanceVolume(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = on_balance_volume, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = onBalanceVolume_lookback, + expected = on_balance_volume_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_PLUS_DI.R b/tests/testthat/test-ta_PLUS_DI.R index 252e91b89..fb69803dd 100644 --- a/tests/testthat/test-ta_PLUS_DI.R +++ b/tests/testthat/test-ta_PLUS_DI.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- plusDirectionalIndicator(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = plus_directional_indicator, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = plusDirectionalIndicator_lookback, + expected = plus_directional_indicator_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_PLUS_DM.R b/tests/testthat/test-ta_PLUS_DM.R index 2e960ee99..08a95c80f 100644 --- a/tests/testthat/test-ta_PLUS_DM.R +++ b/tests/testthat/test-ta_PLUS_DM.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- plusDirectionalMovement(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = plus_directional_movement, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = plusDirectionalMovement_lookback, + expected = plus_directional_movement_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_PPO.R b/tests/testthat/test-ta_PPO.R index 7157bfeb2..baaaefdb1 100644 --- a/tests/testthat/test-ta_PPO.R +++ b/tests/testthat/test-ta_PPO.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- percentagePriceOscillator(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = percentage_price_oscillator, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = percentagePriceOscillator_lookback, + expected = percentage_price_oscillator_lookback + ) +}) ## -method checks for ## and @@ -240,18 +271,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_ROCR.R b/tests/testthat/test-ta_ROCR.R index 54d1c43d0..158b85d8d 100644 --- a/tests/testthat/test-ta_ROCR.R +++ b/tests/testthat/test-ta_ROCR.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- ratioOfChange(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = ratio_of_change, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = ratioOfChange_lookback, + expected = ratio_of_change_lookback + ) +}) ## -method checks for ## and @@ -240,18 +271,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..efedda617 100644 --- a/tests/testthat/test-ta_RSI.R +++ b/tests/testthat/test-ta_RSI.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- relativeStrengthIndex(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = relative_strength_index, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = relativeStrengthIndex_lookback, + expected = relative_strength_index_lookback + ) +}) ## -method checks for ## and @@ -240,18 +271,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..28cea0b41 100644 --- a/tests/testthat/test-ta_SAR.R +++ b/tests/testthat/test-ta_SAR.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- parabolicStopAndReverse(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = parabolic_stop_and_reverse, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = parabolicStopAndReverse_lookback, + expected = parabolic_stop_and_reverse_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_SAREXT.R b/tests/testthat/test-ta_SAREXT.R index 3489c4c7f..99fcea294 100644 --- a/tests/testthat/test-ta_SAREXT.R +++ b/tests/testthat/test-ta_SAREXT.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- extendedParabolicStopAndReverse(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = extended_parabolic_stop_and_reverse, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = extendedParabolicStopAndReverse_lookback, + expected = extended_parabolic_stop_and_reverse_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_SMA.R b/tests/testthat/test-ta_SMA.R index abfaeb274..6356c86e4 100644 --- a/tests/testthat/test-ta_SMA.R +++ b/tests/testthat/test-ta_SMA.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- simpleMovingAverage(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = simple_moving_average, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = simpleMovingAverage_lookback, + expected = simple_moving_average_lookback + ) +}) ## -method checks for ## and @@ -240,18 +271,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..8b80c8c90 100644 --- a/tests/testthat/test-ta_STDDEV.R +++ b/tests/testthat/test-ta_STDDEV.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -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..cbc6ef9e7 100644 --- a/tests/testthat/test-ta_STOCH.R +++ b/tests/testthat/test-ta_STOCH.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -144,6 +144,19 @@ 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(x = 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..dd1fa7d74 100644 --- a/tests/testthat/test-ta_STOCHF.R +++ b/tests/testthat/test-ta_STOCHF.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- fastStochastic(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = fast_stochastic, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = fastStochastic_lookback, + expected = fast_stochastic_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_STOCHRSI.R b/tests/testthat/test-ta_STOCHRSI.R index 76ffb2cf8..d06027462 100644 --- a/tests/testthat/test-ta_STOCHRSI.R +++ b/tests/testthat/test-ta_STOCHRSI.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- stochasticRelativeStrengthIndex(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = stochastic_relative_strength_index, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = stochasticRelativeStrengthIndex_lookback, + expected = stochastic_relative_strength_index_lookback + ) +}) ## -method checks for ## and @@ -240,18 +271,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..de8da4cd8 100644 --- a/tests/testthat/test-ta_SUM.R +++ b/tests/testthat/test-ta_SUM.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -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..a895f4cc2 100644 --- a/tests/testthat/test-ta_T3.R +++ b/tests/testthat/test-ta_T3.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- t3ExponentialMovingAverage(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = t3_exponential_moving_average, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = t3ExponentialMovingAverage_lookback, + expected = t3_exponential_moving_average_lookback + ) +}) ## -method checks for ## and @@ -240,18 +271,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..2673c4212 100644 --- a/tests/testthat/test-ta_TEMA.R +++ b/tests/testthat/test-ta_TEMA.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- tripleExponentialMovingAverage(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = triple_exponential_moving_average, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = tripleExponentialMovingAverage_lookback, + expected = triple_exponential_moving_average_lookback + ) +}) ## -method checks for ## and @@ -240,18 +271,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..c08da3233 100644 --- a/tests/testthat/test-ta_TRANGE.R +++ b/tests/testthat/test-ta_TRANGE.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- trueRange(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = true_range, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = trueRange_lookback, + expected = true_range_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_TRIMA.R b/tests/testthat/test-ta_TRIMA.R index 4dfb628ed..999d10407 100644 --- a/tests/testthat/test-ta_TRIMA.R +++ b/tests/testthat/test-ta_TRIMA.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- triangularMovingAverage(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = triangular_moving_average, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = triangularMovingAverage_lookback, + expected = triangular_moving_average_lookback + ) +}) ## -method checks for ## and @@ -240,18 +271,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..f4558b8ab 100644 --- a/tests/testthat/test-ta_TRIX.R +++ b/tests/testthat/test-ta_TRIX.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- tripleExponentialAverage(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = triple_exponential_average, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = tripleExponentialAverage_lookback, + expected = triple_exponential_average_lookback + ) +}) ## -method checks for ## and @@ -240,18 +271,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..3563eadce 100644 --- a/tests/testthat/test-ta_TYPPRICE.R +++ b/tests/testthat/test-ta_TYPPRICE.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- typicalPrice(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -143,3 +154,24 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = typical_price, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = typicalPrice_lookback, + expected = typical_price_lookback + ) +}) diff --git a/tests/testthat/test-ta_ULTOSC.R b/tests/testthat/test-ta_ULTOSC.R index 3ddd6650c..364a34a53 100644 --- a/tests/testthat/test-ta_ULTOSC.R +++ b/tests/testthat/test-ta_ULTOSC.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- ultimateOscillator(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = ultimate_oscillator, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = ultimateOscillator_lookback, + expected = ultimate_oscillator_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_VAR.R b/tests/testthat/test-ta_VAR.R index 1fe3a18cf..5bb9ca692 100644 --- a/tests/testthat/test-ta_VAR.R +++ b/tests/testthat/test-ta_VAR.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -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_WCLPRICE.R b/tests/testthat/test-ta_WCLPRICE.R index ab6ad34e9..2da136640 100644 --- a/tests/testthat/test-ta_WCLPRICE.R +++ b/tests/testthat/test-ta_WCLPRICE.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- weightedClosePrice(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -143,3 +154,24 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = weighted_close_price, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = weightedClosePrice_lookback, + expected = weighted_close_price_lookback + ) +}) diff --git a/tests/testthat/test-ta_WILLR.R b/tests/testthat/test-ta_WILLR.R index a7e15e63b..94c622b69 100644 --- a/tests/testthat/test-ta_WILLR.R +++ b/tests/testthat/test-ta_WILLR.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- williamsOscillator(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = williams_oscillator, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = williamsOscillator_lookback, + expected = williams_oscillator_lookback + ) +}) ## -method checks for ## and diff --git a/tests/testthat/test-ta_WMA.R b/tests/testthat/test-ta_WMA.R index 0a0b08c94..1f04deb4a 100644 --- a/tests/testthat/test-ta_WMA.R +++ b/tests/testthat/test-ta_WMA.R @@ -1,5 +1,5 @@ ## autogenerated unit-test -## from codegen/generate_unit-tests.sh +## from codegen/ ## the file will be overwritten in the next iteration ## ## author: Serkan Korkmaz @@ -19,6 +19,17 @@ testthat::test_that(desc = 'Alias and function similarity', code = { object = output, expected = alias ) + + ## 2) test that the camelCase alias + ## returns the same values + camel <- weightedMovingAverage(SPY) + + ## 2.1) check if the values + ## are equal + testthat::expect_equal( + object = output, + expected = camel + ) }) ## type-checks for data.frames and @@ -144,6 +155,26 @@ 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(x = SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = weighted_moving_average, x = SPY) + ) + + ## the camelCase lookback alias + ## is the function itself + testthat::expect_identical( + object = weightedMovingAverage_lookback, + expected = weighted_moving_average_lookback + ) +}) ## -method checks for ## and @@ -240,18 +271,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) } }) diff --git a/vignettes/articles/tidyverse.Rmd b/vignettes/articles/tidyverse.Rmd deleted file mode 100644 index 7fbe52085..000000000 --- a/vignettes/articles/tidyverse.Rmd +++ /dev/null @@ -1,184 +0,0 @@ ---- -title: "Tidyverse Workflows" -author: Serkan Korkmaz ---- - -```{r, include = FALSE} -options(talib.chart.dark = FALSE) - -knitr::opts_chunk$set( - collapse = TRUE, - comment = "#>", - out.width = "100%", - fig.align = "center" -) -``` - -`{talib}` indicators accept a `data.frame` and return a `data.frame`---but the returned data frame contains **only the indicator columns**, not the original data. This is by design: it keeps the core API minimal and composable. In a tidyverse pipeline, however, you usually want the indicator columns attached to your existing data so you can keep piping. - -This article builds a thin wrapper called `tidy_ta()` that bridges that gap, then puts it to work in increasingly realistic scenarios. - -```{r} -library(talib) -library(dplyr) -library(tidyr) -``` - -## The gap - -Piping into a `{talib}` indicator works---`x` is the first argument: - -```{r} -BTC %>% - RSI(n = 14) %>% - tail() -``` - -The result is a one-column data frame with just the RSI values. The original price data is gone. To keep both, you need to bind the indicator output back to the input. - -## Building `tidy_ta()` - -The simplest version takes a data frame, passes it to an indicator, and column-binds the result: - -```{r} -tidy_ta <- function(.data, .f, ...) { - dplyr::bind_cols(.data, .f(.data, ...)) -} -``` - -Three lines, and every indicator in `{talib}` is now pipe-friendly: - -```{r} -BTC %>% - tidy_ta(RSI, n = 14) %>% - tail() -``` - -Multi-column indicators work the same way---Bollinger Bands returns three columns, and all three get bound: - -```{r} -BTC %>% - tidy_ta(bollinger_bands) %>% - tail() -``` - -Chaining multiple indicators composes naturally: - -```{r} -BTC %>% - tidy_ta(RSI, n = 14) %>% - tidy_ta(bollinger_bands) %>% - tidy_ta(MACD) %>% - tail() -``` - -### Handling column-name collisions - -If you add two SMAs with different periods, both return a column named `SMA` and `bind_cols()` disambiguates with ugly suffixes like `SMA...6`. A `.suffix` parameter fixes this: - -```{r} -tidy_ta <- function(.data, .f, ..., .suffix = NULL) { - result <- .f(.data, ...) - - if (!is.null(.suffix)) { - colnames(result) <- paste(colnames(result), .suffix, sep = "_") - } - - dplyr::bind_cols(.data, result) -} -``` - -Now each indicator gets a clear name: - -```{r} -BTC %>% - tidy_ta(SMA, n = 10, .suffix = "10") %>% - tidy_ta(SMA, n = 20, .suffix = "20") %>% - tail() -``` - -The `cols` argument is forwarded through `...`, so column remapping still works: - -```{r} -BTC %>% - tidy_ta(RSI, cols = ~high, n = 14) %>% - tail() -``` - -This is the complete wrapper. The rest of the article uses it as-is. - -## Grouped operations across assets - -A common task is computing the same indicator across multiple tickers. Stack the data, `nest()` by ticker, apply `tidy_ta()` inside each group, and `unnest()`: - -```{r} -assets <- bind_rows( - BTC %>% as_tibble(rownames = "date") %>% mutate(ticker = "BTC"), - SPY %>% as_tibble(rownames = "date") %>% mutate(ticker = "SPY"), - NVDA %>% as_tibble(rownames = "date") %>% mutate(ticker = "NVDA") -) - -assets %>% - nest(.by = ticker) %>% - mutate(data = lapply(data, tidy_ta, RSI, n = 14)) %>% - unnest(data) %>% - select(ticker, date, close, RSI) %>% - filter(!is.na(RSI)) %>% - slice_tail(n = 3, by = ticker) -``` - -Because `tidy_ta()` returns the full enriched data frame, `unnest()` restores everything in one step. This scales to multiple indicators by chaining inside the `lapply()`: - -```{r} -assets %>% - nest(.by = ticker) %>% - mutate(data = lapply(data, function(d) { - d %>% - tidy_ta(RSI, n = 14) %>% - tidy_ta(bollinger_bands) - })) %>% - unnest(data) %>% - select(ticker, date, close, RSI, UpperBand, MiddleBand, LowerBand) %>% - filter(!is.na(RSI)) %>% - slice_tail(n = 3, by = ticker) -``` - -## Putting it all together - -A complete pipeline: enrich a multi-asset dataset, flag RSI signals, and find the most recent event per asset. - -```{r} -assets %>% - nest(.by = ticker) %>% - mutate(data = lapply(data, tidy_ta, RSI, n = 14)) %>% - unnest(data) %>% - filter(!is.na(RSI)) %>% - mutate( - signal = case_when( - RSI > 70 ~ "overbought", - RSI < 30 ~ "oversold" - ) - ) %>% - filter(!is.na(signal)) %>% - slice_tail(n = 1, by = c(ticker, signal)) %>% - select(ticker, date, close, RSI, signal) %>% - arrange(ticker, signal) -``` - -## Summary - -The entire wrapper is six lines: - -```r -tidy_ta <- function(.data, .f, ..., .suffix = NULL) { - result <- .f(.data, ...) - if (!is.null(.suffix)) { - colnames(result) <- paste(colnames(result), .suffix, sep = "_") - } - dplyr::bind_cols(.data, result) -} -``` - -It works because `{talib}` indicators already follow the key convention: data frame in, data frame out, with row counts and row names preserved. `tidy_ta()` just bridges the last mile---binding the result back to the input so the pipeline keeps flowing. - -The pattern is not specific to `{talib}`. Any function that takes a data frame and returns a same-length data frame can be wrapped the same way. diff --git a/vignettes/candlestick.Rmd b/vignettes/candlestick.Rmd index 0e4c630c1..62ea19932 100644 --- a/vignettes/candlestick.Rmd +++ b/vignettes/candlestick.Rmd @@ -184,13 +184,13 @@ table(talib::engulfing(talib::BTC)) options(talib.normalize = TRUE) ``` -### The `eps` parameter +### The `penetration` parameter -Seven patterns accept an `eps` (penetration) parameter that controls how far one candle must intrude into the body of another. These are `morning_star()`, `evening_star()`, `morning_doji_star()`, `evening_doji_star()`, `abandoned_baby()`, `dark_cloud_cover()`, and `mat_hold()`. The default is `eps = 0` for all of them. +Seven patterns accept an `penetration` (penetration) parameter that controls how far one candle must intrude into the body of another. These are `morning_star()`, `evening_star()`, `morning_doji_star()`, `evening_doji_star()`, `abandoned_baby()`, `dark_cloud_cover()`, and `mat_hold()`. The default is `penetration = 0` for all of them. ```{r} ## Evening Star with 30% penetration -x <- talib::evening_star(talib::BTC, eps = 0.3) +x <- talib::evening_star(talib::BTC, penetration = 0.3) sum(abs(x), na.rm = TRUE) ``` diff --git a/vignettes/charting.Rmd b/vignettes/charting.Rmd index 28e771232..06d3aad2b 100644 --- a/vignettes/charting.Rmd +++ b/vignettes/charting.Rmd @@ -57,8 +57,8 @@ Use `indicator()` to attach technical indicators to the most recent `chart()`. I ```{r} { talib::chart(talib::BTC) - talib::indicator(talib::SMA, n = 7) - talib::indicator(talib::SMA, n = 14) + talib::indicator(talib::SMA, timePeriod = 7) + talib::indicator(talib::SMA, timePeriod = 14) talib::indicator(talib::RSI) } ``` @@ -82,9 +82,9 @@ By default, each sub-panel indicator (RSI, MACD, etc.) gets its own panel. To me { talib::chart(talib::BTC) talib::indicator( - talib::RSI(n = 10), - talib::RSI(n = 14), - talib::RSI(n = 21) + talib::RSI(timePeriod = 10), + talib::RSI(timePeriod = 14), + talib::RSI(timePeriod = 21) ) } ``` @@ -95,7 +95,7 @@ Each indicator keeps its own arguments and receives a distinct color from the ac { talib::chart(talib::BTC) talib::indicator( - talib::RSI(n = 14), + talib::RSI(timePeriod = 14), talib::MACD() ) } @@ -108,15 +108,15 @@ Combined panels and regular panels can be freely mixed in the same chart: talib::chart(talib::BTC) talib::indicator(talib::BBANDS) talib::indicator( - talib::RSI(n = 10), - talib::RSI(n = 14), - talib::RSI(n = 21) + talib::RSI(timePeriod = 10), + talib::RSI(timePeriod = 14), + talib::RSI(timePeriod = 21) ) talib::indicator(talib::MACD) } ``` -> **Note:** the syntax matters. `indicator(RSI, n = 14)` passes a function and arguments separately (single indicator). `indicator(RSI(n = 14), RSI(n = 21))` passes _calls_ (combined panel). A single call like `indicator(RSI(n = 14))` also works and is equivalent to the single-indicator form. +> **Note:** the syntax matters. `indicator(RSI, timePeriod = 14)` passes a function and arguments separately (single indicator). `indicator(RSI(timePeriod = 14), RSI(timePeriod = 21))` passes _calls_ (combined panel). A single call like `indicator(RSI(timePeriod = 14))` also works and is equivalent to the single-indicator form. ### Standalone indicators @@ -221,10 +221,10 @@ The default theme uses a dark background with cyan and blue candles. ```{r} { talib::chart(talib::BTC) - talib::indicator(talib::SMA, n = 7) - talib::indicator(talib::SMA, n = 14) - talib::indicator(talib::SMA, n = 21) - talib::indicator(talib::SMA, n = 28) + talib::indicator(talib::SMA, timePeriod = 7) + talib::indicator(talib::SMA, timePeriod = 14) + talib::indicator(talib::SMA, timePeriod = 21) + talib::indicator(talib::SMA, timePeriod = 28) talib::indicator(talib::MACD) talib::indicator(talib::trading_volume) } @@ -238,10 +238,10 @@ A light theme with neutral grays. { talib::set_theme$hawks_and_doves talib::chart(talib::BTC) - talib::indicator(talib::SMA, n = 7) - talib::indicator(talib::SMA, n = 14) - talib::indicator(talib::SMA, n = 21) - talib::indicator(talib::SMA, n = 28) + talib::indicator(talib::SMA, timePeriod = 7) + talib::indicator(talib::SMA, timePeriod = 14) + talib::indicator(talib::SMA, timePeriod = 21) + talib::indicator(talib::SMA, timePeriod = 28) talib::indicator(talib::MACD) talib::indicator(talib::trading_volume) } @@ -255,10 +255,10 @@ A dark theme with teal and orange accents. { talib::set_theme$payout talib::chart(talib::BTC) - talib::indicator(talib::SMA, n = 7) - talib::indicator(talib::SMA, n = 14) - talib::indicator(talib::SMA, n = 21) - talib::indicator(talib::SMA, n = 28) + talib::indicator(talib::SMA, timePeriod = 7) + talib::indicator(talib::SMA, timePeriod = 14) + talib::indicator(talib::SMA, timePeriod = 21) + talib::indicator(talib::SMA, timePeriod = 28) talib::indicator(talib::MACD) talib::indicator(talib::trading_volume) } @@ -272,10 +272,10 @@ A bright theme with teal and red candles on a light background. { talib::set_theme$tp_slapped talib::chart(talib::BTC) - talib::indicator(talib::SMA, n = 7) - talib::indicator(talib::SMA, n = 14) - talib::indicator(talib::SMA, n = 21) - talib::indicator(talib::SMA, n = 28) + talib::indicator(talib::SMA, timePeriod = 7) + talib::indicator(talib::SMA, timePeriod = 14) + talib::indicator(talib::SMA, timePeriod = 21) + talib::indicator(talib::SMA, timePeriod = 28) talib::indicator(talib::MACD) talib::indicator(talib::trading_volume) } @@ -289,10 +289,10 @@ A light, muted theme with earthy tones. { talib::set_theme$trust_the_process talib::chart(talib::BTC) - talib::indicator(talib::SMA, n = 7) - talib::indicator(talib::SMA, n = 14) - talib::indicator(talib::SMA, n = 21) - talib::indicator(talib::SMA, n = 28) + talib::indicator(talib::SMA, timePeriod = 7) + talib::indicator(talib::SMA, timePeriod = 14) + talib::indicator(talib::SMA, timePeriod = 21) + talib::indicator(talib::SMA, timePeriod = 28) talib::indicator(talib::MACD) talib::indicator(talib::trading_volume) } @@ -306,10 +306,10 @@ A dark theme inspired by the Bloomberg Terminal interface. Orange bullish candle { talib::set_theme$bloomberg_terminal talib::chart(talib::BTC) - talib::indicator(talib::SMA, n = 7) - talib::indicator(talib::SMA, n = 14) - talib::indicator(talib::SMA, n = 21) - talib::indicator(talib::SMA, n = 28) + talib::indicator(talib::SMA, timePeriod = 7) + talib::indicator(talib::SMA, timePeriod = 14) + talib::indicator(talib::SMA, timePeriod = 21) + talib::indicator(talib::SMA, timePeriod = 28) talib::indicator(talib::MACD) talib::indicator(talib::trading_volume) } @@ -323,10 +323,10 @@ A dark monochrome theme that encodes direction with luminance only. Light-gray b { talib::set_theme$limit_up talib::chart(talib::BTC) - talib::indicator(talib::SMA, n = 7) - talib::indicator(talib::SMA, n = 14) - talib::indicator(talib::SMA, n = 21) - talib::indicator(talib::SMA, n = 28) + talib::indicator(talib::SMA, timePeriod = 7) + talib::indicator(talib::SMA, timePeriod = 14) + talib::indicator(talib::SMA, timePeriod = 21) + talib::indicator(talib::SMA, timePeriod = 28) talib::indicator(talib::MACD) talib::indicator(talib::trading_volume) } @@ -340,10 +340,10 @@ A light theme with the classic blue-vs-red trading pair. Steel-blue bullish and { talib::set_theme$bid_n_ask talib::chart(talib::BTC) - talib::indicator(talib::SMA, n = 7) - talib::indicator(talib::SMA, n = 14) - talib::indicator(talib::SMA, n = 21) - talib::indicator(talib::SMA, n = 28) + talib::indicator(talib::SMA, timePeriod = 7) + talib::indicator(talib::SMA, timePeriod = 14) + talib::indicator(talib::SMA, timePeriod = 21) + talib::indicator(talib::SMA, timePeriod = 28) talib::indicator(talib::MACD) talib::indicator(talib::trading_volume) } @@ -416,7 +416,7 @@ Set `talib.chart.backend` to `"ggplot2"` for static charts. This requires the ** talib::set_theme$hawks_and_doves talib::chart(talib::BTC) - talib::indicator(talib::SMA, n = 14) + talib::indicator(talib::SMA, timePeriod = 14) talib::indicator(talib::RSI) } ``` diff --git a/vignettes/talib.Rmd b/vignettes/talib.Rmd index 0a1a8eb83..9de1503eb 100644 --- a/vignettes/talib.Rmd +++ b/vignettes/talib.Rmd @@ -16,7 +16,7 @@ knitr::opts_chunk$set( comment = "#>", out.width = "100%", out.height = "680", - fig.align = "center" + fig.aligtimePeriod = "center" ) ``` @@ -99,8 +99,8 @@ Every indicator has a descriptive snake_case name and an uppercase alias that mi ```{r} ## these are equivalent identical( - talib::relative_strength_index(talib::BTC, n = 14), - talib::RSI(talib::BTC, n = 14) + talib::relative_strength_index(talib::BTC, timePeriod = 14), + talib::RSI(talib::BTC, timePeriod = 14) ) ``` @@ -109,17 +109,17 @@ identical( Most indicators require a minimum number of observations before they can produce a value. This is called the **lookback period**. The first `lookback` rows of the result will be `NA`: ```{r} -## SMA with n = 5 has a lookback of 4 +## SMA with timePeriod = 5 has a lookback of 4 head( - talib::SMA(talib::BTC, n = 5), - n = 7 + talib::SMA(talib::BTC, timePeriod = 5), + timePeriod = 7 ) ``` The lookback is stored as an attribute on the result: ```{r} -x <- talib::SMA(talib::BTC, n = 20) +x <- talib::SMA(talib::BTC, timePeriod = 20) attr(x, "lookback") ``` @@ -209,7 +209,7 @@ Several indicators accept a **Moving Average specification** for their smoothing ```{r} ## SMA as a specification str( - talib::SMA(n = 20) + talib::SMA(timePeriod = 20) ) ``` @@ -220,7 +220,8 @@ This specification can be passed to indicators like `bollinger_bands()` or `stoc tail( talib::bollinger_bands( talib::BTC, - ma = talib::EMA(n = 20) + timePeriod = 20, + maType = talib::EMA() ) ) ``` @@ -230,8 +231,10 @@ tail( tail( talib::stochastic( talib::BTC, - slowk = talib::WMA(n = 5), - slowd = talib::EMA(n = 3) + slowKPeriod = 5, + slowKMa = talib::EMA(), + slowDPeriod = 5, + slowDMa = talib::EMA() ) ) ```