fd9f4c8bc6
* feat(bindings): expose name() on every indicator in Node, WASM, and Python Surface the core Indicator::name() / BarBuilder::name() accessor through the three native bindings so every indicator reports its canonical name at runtime, matching the existing reset/isReady/warmupPeriod surface. - Node (napi): name(): string on all 514 classes (regenerated index.d.ts) - WASM (wasm-bindgen): name(): string on all 514 classes - Python (pyo3): name() -> str on all classes * feat(bindings): expose name() across the C ABI and C/C++/Go/C#/Java/R Regenerate the C ABI and the four generated language bindings from the updated ScriptHelpers generators so every indicator and bar builder reports its canonical name at runtime, completing name() coverage across all 10 languages. - C ABI (bindings/c): wickra_<ind>_name() -> *const c_char for all 514, cached in a per-function OnceLock<CString> with ind.name() as the source of truth; cbindgen header regenerated and vendored into bindings/go/include. - Go: Name() string; C#: string Name(); Java: String name(); R: name() S3 generic over the wk_<ind>_name C glue (methods.R + NAMESPACE). The Java regeneration also restores two fixes that had drifted out of the generator (bool* arrays via boolSegment; uint8_t ctor args cast to byte) and C# re-emits '#nullable enable'; these are no-op vs the previous committed output apart from the new name() accessors. * test(golden): pin canonical name() across all 10 language bindings Add a cross-language name() consistency check: every indicator must report the exact core Indicator::name() (which can differ from the registered class name, e.g. ChaikinMoneyFlow -> "CMF", Donchian -> "DonchianChannels"). The 514 core names are committed as testdata/golden/names.json (keyed by Rust canonical) and asserted by each binding's golden replay, which already reconstructs the whole catalogue: - node / wasm: assert against names.json in the existing golden test - python: new test_golden_names.py over the shared node manifest - go / csharp / java / c+c++ / r: the golden-test generators load names.json and emit a name assertion per indicator (regenerated test artifacts committed) All 10 bindings return identical names by construction (each delegates to core), so this pins that contract and guards against a future binding breaking the passthrough. * docs(changelog): record name() across all 10 bindings under Unreleased * fix(r): restore bool* flag marshalling in the regenerated C glue The name() regeneration had reverted the cross-section bool fix: the R glue emitted (bool *)REAL(x) for const bool* inputs, reinterpreting 8-byte doubles as 1-byte bools so every flag read as false (PercentAboveMa, NewHighsNewLows, HighLowIndex, BullishPercentIndex returned 0 instead of the breadth value). The wk_bool_vec() helper is restored in the generator and the glue routes bool arrays through it again.
141 lines
4.2 KiB
R
141 lines
4.2 KiB
R
#' wickra: streaming-first technical indicators
|
|
#'
|
|
#' R bindings for the Wickra technical-analysis library over its C ABI hub. Each
|
|
#' indicator is a constructor (for example [Sma()], [Rsi()], [MacdIndicator()])
|
|
#' returning a `wickra_indicator` object; feed it one observation at a time with
|
|
#' [update()], run a whole series in one call with [batch()], and clear its
|
|
#' state with [reset()]. The native handle is freed automatically when the object
|
|
#' is garbage-collected.
|
|
#'
|
|
#' @keywords internal
|
|
#' @importFrom stats update
|
|
"_PACKAGE"
|
|
|
|
#' Update an indicator with one observation
|
|
#'
|
|
#' @param object A `wickra_indicator` created by an indicator constructor.
|
|
#' @param ... The observation: a single value for scalar indicators, the OHLCV
|
|
#' fields plus a timestamp for candle indicators, or two values for pairwise
|
|
#' indicators.
|
|
#' @return The indicator value: a numeric scalar; a named numeric vector for
|
|
#' multi-output indicators (`NA` during warmup); a matrix of completed bars for
|
|
#' bar builders; or a list / numeric vector for profile indicators
|
|
#' (`NULL` during warmup).
|
|
#' @examples
|
|
#' sma <- Sma(3)
|
|
#' for (x in c(1, 2, 3, 4, 5)) v <- update(sma, x)
|
|
#' v # 4
|
|
#' @export
|
|
update.wickra_indicator <- function(object, ...) {
|
|
args <- list(object$ptr, ...)
|
|
if (!is.na(object$values_cap)) {
|
|
args <- c(args, object$values_cap)
|
|
}
|
|
do.call(".Call", c(list(paste0("wk_", object$prefix, "_update")), args,
|
|
list(PACKAGE = "wickra")))
|
|
}
|
|
|
|
#' Run an indicator over a whole series in one call
|
|
#'
|
|
#' Available for scalar indicators. The result is identical to feeding the same
|
|
#' inputs through [update()] one at a time, with `NA` at warmup positions.
|
|
#'
|
|
#' @param object A `wickra_indicator`.
|
|
#' @param ... The input vector(s).
|
|
#' @return A numeric vector the same length as the input.
|
|
#' @examples
|
|
#' batch(Sma(3), c(1, 2, 3, 4, 5)) # NA NA 2 3 4
|
|
#' @export
|
|
batch <- function(object, ...) {
|
|
UseMethod("batch")
|
|
}
|
|
|
|
#' @rdname batch
|
|
#' @export
|
|
batch.wickra_indicator <- function(object, ...) {
|
|
do.call(".Call", c(list(paste0("wk_", object$prefix, "_batch"), object$ptr),
|
|
list(...), list(PACKAGE = "wickra")))
|
|
}
|
|
|
|
#' Reset an indicator to its warmup state
|
|
#'
|
|
#' @param object A `wickra_indicator`.
|
|
#' @return The indicator, invisibly.
|
|
#' @examples
|
|
#' sma <- Sma(3)
|
|
#' update(sma, 1)
|
|
#' reset(sma)
|
|
#' @export
|
|
reset <- function(object) {
|
|
UseMethod("reset")
|
|
}
|
|
|
|
#' @rdname reset
|
|
#' @export
|
|
reset.wickra_indicator <- function(object) {
|
|
.Call(paste0("wk_", object$prefix, "_reset"), object$ptr, PACKAGE = "wickra")
|
|
invisible(object)
|
|
}
|
|
|
|
#' Number of updates an indicator needs before it produces a value
|
|
#'
|
|
#' Not available for the alt-chart bar builders ([RenkoBars()], [KagiBars()],
|
|
#' [PointAndFigureBars()], …), which have no warmup.
|
|
#'
|
|
#' @param object A `wickra_indicator`.
|
|
#' @return A single integer: the warmup period.
|
|
#' @examples
|
|
#' warmup_period(Sma(14)) # 14
|
|
#' @export
|
|
warmup_period <- function(object) {
|
|
UseMethod("warmup_period")
|
|
}
|
|
|
|
#' @rdname warmup_period
|
|
#' @export
|
|
warmup_period.wickra_indicator <- function(object) {
|
|
.Call(paste0("wk_", object$prefix, "_warmup_period"), object$ptr, PACKAGE = "wickra")
|
|
}
|
|
|
|
#' Whether an indicator has consumed enough input to emit a value
|
|
#'
|
|
#' Not available for the alt-chart bar builders, which have no warmup.
|
|
#'
|
|
#' @param object A `wickra_indicator`.
|
|
#' @return A single logical.
|
|
#' @examples
|
|
#' sma <- Sma(3)
|
|
#' is_ready(sma) # FALSE
|
|
#' for (x in c(1, 2, 3)) update(sma, x)
|
|
#' is_ready(sma) # TRUE
|
|
#' @export
|
|
is_ready <- function(object) {
|
|
UseMethod("is_ready")
|
|
}
|
|
|
|
#' @rdname is_ready
|
|
#' @export
|
|
is_ready.wickra_indicator <- function(object) {
|
|
.Call(paste0("wk_", object$prefix, "_is_ready"), object$ptr, PACKAGE = "wickra")
|
|
}
|
|
|
|
#' Canonical name of an indicator
|
|
#'
|
|
#' Returns the stable, human-readable name of the indicator (the same name
|
|
#' reported by every other Wickra binding), e.g. `"SMA"` for [Sma()].
|
|
#'
|
|
#' @param object A `wickra_indicator`.
|
|
#' @return A single character string.
|
|
#' @examples
|
|
#' name(Sma(14)) # "SMA"
|
|
#' @export
|
|
name <- function(object) {
|
|
UseMethod("name")
|
|
}
|
|
|
|
#' @rdname name
|
|
#' @export
|
|
name.wickra_indicator <- function(object) {
|
|
.Call(paste0("wk_", object$prefix, "_name"), object$ptr, PACKAGE = "wickra")
|
|
}
|