Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
ec04cbd
:fire: Initial Rust-based code generator
serkor1 Jul 9, 2026
1daa678
:bug:-fix: Parser were using old type macros
serkor1 Jul 10, 2026
34c1002
:hammer: Lookback parsing + descriptive fn naming
serkor1 Jul 13, 2026
4b806bd
:hammer: Candlestick/Non-candlestick specific identifiers
serkor1 Jul 14, 2026
420fba9
:wastebasket: Removed lookback functions
serkor1 Jul 14, 2026
4410628
:hammer: X-Macros (#78)
serkor1 Jul 14, 2026
749e242
:hammer: Added cargo commands and removed obsolete scripts
serkor1 Jul 14, 2026
0010b89
:broom: Formatted .rs-files
serkor1 Jul 14, 2026
0769baf
:fire: Refactored R codegen
serkor1 Jul 26, 2026
f650702
:hammer: Added optional parameter documentation
serkor1 Jul 26, 2026
5a10826
:books: n --> timePeriod and eps --> penetration
serkor1 Jul 26, 2026
5fd6205
:hammer: Regenerated R-code with documentation
serkor1 Jul 26, 2026
36c5156
:books: Updated README in response to (d7a2e979d8948fefd4b0d4338b572e…
serkor1 Jul 26, 2026
05444ce
:hammer: Mine <Name> instead of <Type>
serkor1 Jul 26, 2026
826535e
:bug:-fix: Bivariate indicators emitted one 'x'
serkor1 Jul 26, 2026
fac3fa6
:hammer: (Proper) function naming of residual indicators
serkor1 Jul 26, 2026
7750b71
:hammer: Map maType to characters
serkor1 Jul 26, 2026
6e04b56
:hammer: Added charting methods for MAVP
serkor1 Jul 26, 2026
3c54189
:hammer: ma --> maType and n --> timePeriod
serkor1 Jul 26, 2026
105692a
:books: Add periods column to template generation
serkor1 Jul 26, 2026
beed6f6
:books: Documented maType (ma before)
serkor1 Jul 26, 2026
e58e9d1
:hammer: [INSERT_WHATEVER_AI_AGENT].md ignored
serkor1 Jul 26, 2026
243eeff
:hammer: Added charting methods for ta_MIDPRICE/ta_MIDPOINT
serkor1 Jul 26, 2026
0560e34
:wastebasket: Removed maType-tests
serkor1 Jul 26, 2026
df37984
:wastebasket: Remove TSF
serkor1 Jul 26, 2026
da875ea
:books: Updated NAMESPACE
serkor1 Jul 26, 2026
1c5892d
🗑 Remove TSF (C)
serkor1 Jul 26, 2026
246d6a2
:hammer: Small maType-helper in S3
serkor1 Jul 26, 2026
891db5b
:hammer: Added as.maType for maType args
serkor1 Jul 26, 2026
80072f6
:books: Adapted vignettes to new interface
serkor1 Jul 26, 2026
357f64a
:wastebasket: Deleted AI-slop
serkor1 Jul 26, 2026
7f0b051
:books: Removed TSF, and added as.maType
serkor1 Jul 26, 2026
10e0500
:fire: Custom examples tags
serkor1 Jul 26, 2026
cc2a2c9
:books: Added custom example flag
serkor1 Jul 26, 2026
e364548
:hammer: Unexport generic / Export dispatches
serkor1 Jul 26, 2026
ee8de83
:hammer: data-helper for unit-tests
serkor1 Jul 26, 2026
4d67476
:hammer: Pass NULL
serkor1 Jul 26, 2026
c830602
:hammer: Enable (rolling) math operators
serkor1 Jul 27, 2026
42d1068
:hammer: Coerce family tags to 'Rolling Statistics'
serkor1 Jul 27, 2026
6a57fe7
:bug:-fix: Mispelled stuff fixed...
serkor1 Jul 27, 2026
c91bdba
:fire: Allow for passthrough arguments
serkor1 Jul 27, 2026
91ee5e3
:hammer: Reworked MAVP and downstream effects
serkor1 Jul 27, 2026
7260546
:hammer: Readded ROCR (Incorrectly excluded)
serkor1 Jul 28, 2026
e42e573
:hammer: Lookback functions and tests
serkor1 Jul 28, 2026
ce44396
:books: Initial NEWS update
serkor1 Jul 27, 2026
65f5255
:books: Added bug-fixes and finished new features
serkor1 Jul 28, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
4 changes: 4 additions & 0 deletions .Rbuildignore
Original file line number Diff line number Diff line change
Expand Up @@ -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
20 changes: 9 additions & 11 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -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: cleanfmt → 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
Expand All @@ -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:<name>:start` / `## splice:<name>: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.
Expand Down Expand Up @@ -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

Expand Down
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ document: ## Build R documentation
@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
@$(MAKE) document
@R CMD build . --no-build-vignettes && R CMD INSTALL $(tarball_location)
@rm -rf README.md
Expand Down Expand Up @@ -69,6 +68,7 @@ fmt: ## Format code
@air format R
@air format tests/testthat
@rm -rf ./.clang-format
@cargo fmt --manifest-path codegen/Cargo.toml

pkgdown-build: ## Build {pkgdown} documentation
@$(MAKE) document
Expand Down Expand Up @@ -133,5 +133,6 @@ parity-clean: ## Remove parity build artifacts and the generated test file
@rm -rf tests/parity/snapshot

gen-code: ## Generate R wrappers and unit-tests
@cargo run --manifest-path codegen/Cargo.toml
@Rscript --verbose ./codegen/gen_code/generate.R
$(MAKE) fmt
47 changes: 33 additions & 14 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -664,6 +679,7 @@ export(APO)
export(AROON)
export(AROONOSC)
export(ATR)
export(AVGDEV)
export(AVGPRICE)
export(BBANDS)
export(BETA)
Expand Down Expand Up @@ -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)
Expand All @@ -760,7 +778,6 @@ export(OBV)
export(PLUS_DI)
export(PLUS_DM)
export(PPO)
export(ROC)
export(ROCR)
export(RSI)
export(SAR)
Expand Down Expand Up @@ -789,6 +806,7 @@ export(acceleration_bands)
export(advance_block)
export(aroon)
export(aroon_oscillator)
export(average_deviation)
export(average_directional_movement_index)
export(average_directional_movement_index_rating)
export(average_price)
Expand Down Expand Up @@ -847,6 +865,7 @@ export(mat_hold)
export(matching_low)
export(median_price)
export(mesa_adaptive_moving_average)
export(midpoint_period)
export(midpoint_price)
export(minus_directional_indicator)
export(minus_directional_movement)
Expand All @@ -864,15 +883,14 @@ export(phasor_components)
export(piercing)
export(plus_directional_indicator)
export(plus_directional_movement)
export(rate_of_change)
export(ratio_of_change)
export(relative_strength_index)
export(rickshaw_man)
export(rise_fall_3_methods)
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)
Expand Down Expand Up @@ -911,6 +929,7 @@ export(typical_price)
export(ultimate_oscillator)
export(unique_3_river)
export(upside_gap_2_crows)
export(variable_moving_average_period)
export(weighted_close_price)
export(weighted_moving_average)
export(williams_oscillator)
Expand Down
106 changes: 106 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# 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:
Expand All @@ -15,8 +19,110 @@ talib::lookback(
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
```

## 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 \<class\>_—Indicators that returns a one-dimensional indicator (MA, RSI, etc.) were returning a \<matrix\> or \<data.frame\> instead of \<numeric\>.

# version 0.9-2

## improvements
Expand Down
Loading
Loading