feat(r): getting-started vignette + sample_ohlcv dataset (#262)
Fills the two empty r-universe tabs (**Articles**, **Datasets**) for the R package and gives R users a runnable onboarding path. ## What - **`vignettes/getting-started.Rmd`** — Articles tab. Walks through batch vs streaming (and that they're equivalent), multi-output MACD, candle ATR, and `reset()`, all over the bundled sample series. Built strictly from the already-proven README quick-start + golden-test API (`Sma`/`Ema`/`Rsi`/`Atr`/`MacdIndicator`, `batch`/`update`/`reset`) — no new indicator logic. - **`data/sample_ohlcv.rda`** (+ `data-raw/sample_ohlcv.R` generator) — Datasets tab. A deterministic, seeded synthetic daily OHLCV series (250 rows × `date/open/high/low/close/volume`); documented via `R/data.R` + `man/sample_ohlcv.Rd`. `LazyData: true` → available right after `library(wickra)`. - **`DESCRIPTION`** — `Suggests: knitr, rmarkdown`, `VignetteBuilder: knitr`, `LazyData: true`. - **`ci.yml`** — the R job now knits the vignette (executes its R chunks, no pandoc needed) so a broken example is caught **in CI** before r-universe / CRAN `R CMD check`. The main job otherwise only `R CMD INSTALL`s. ## Verified locally (R 4.6.0 + Rtools45) - Package installs with the dev C-ABI override; dataset moves to the lazyload DB. - Vignette **knits cleanly** — every chunk runs, `batch == streaming` holds, MACD/ATR/RSI produce sensible values. ## Notes - No version bump — metadata/docs only; rides the next release. Merging triggers an r-universe rebuild → Articles + Datasets populate **and** (now that `support@wickra.org` is verified) the maintainer avatar resolves. - `data-raw/` is `.Rbuildignore`d (generator, not shipped). The `.rda` is XZ-compressed (~3 KB). Not merging — for review.
This commit is contained in:
@@ -926,6 +926,16 @@ jobs:
|
||||
R CMD INSTALL bindings/r
|
||||
Rscript -e 'library(testthat); library(wickra); test_dir("bindings/r/tests/testthat", stop_on_failure = TRUE)'
|
||||
|
||||
- name: Build the vignette code
|
||||
shell: bash
|
||||
# The getting-started vignette runs at R CMD check time on r-universe /
|
||||
# CRAN (with pandoc); this job only INSTALLs, so execute the vignette's R
|
||||
# chunks here (knit, no pandoc needed) to catch a broken example before it
|
||||
# reaches the published build.
|
||||
run: |
|
||||
Rscript -e 'install.packages("knitr", repos = Sys.getenv("RSPM", unset = "https://cloud.r-project.org"))'
|
||||
Rscript -e 'knitr::knit("bindings/r/vignettes/getting-started.Rmd", output = tempfile(fileext = ".md"), quiet = TRUE); cat("vignette code OK\n")'
|
||||
|
||||
- name: Run the offline R examples
|
||||
shell: bash
|
||||
# No loader-path exports: the installed package is self-contained (bundled
|
||||
|
||||
@@ -6,6 +6,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [Unreleased]
|
||||
### Added
|
||||
- R binding: a *Getting started* vignette and a synthetic `sample_ohlcv` example
|
||||
dataset, giving new users a runnable, self-contained walkthrough and populating
|
||||
the R-universe Articles and Datasets tabs. The vignette's code is exercised in
|
||||
CI so a broken example is caught before the published build.
|
||||
|
||||
## [0.8.6] - 2026-06-11
|
||||
### Changed
|
||||
|
||||
@@ -11,3 +11,4 @@
|
||||
^src/wickra-c$
|
||||
^src/Makevars$
|
||||
^\.gitignore$
|
||||
^data-raw$
|
||||
|
||||
@@ -21,6 +21,8 @@ SystemRequirements: the Wickra C ABI shared library, downloaded automatically at
|
||||
Set WICKRA_INCLUDE_DIR and WICKRA_LIB_DIR to build against a locally built C
|
||||
ABI instead (e.g. after `cargo build -p wickra-c --release`).
|
||||
Roxygen: list(markdown = TRUE)
|
||||
Suggests: testthat (>= 3.0.0)
|
||||
Suggests: testthat (>= 3.0.0), knitr, rmarkdown
|
||||
VignetteBuilder: knitr
|
||||
LazyData: true
|
||||
Config/testthat/edition: 3
|
||||
Config/roxygen2/version: 8.0.0
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
#' Synthetic daily OHLCV sample series
|
||||
#'
|
||||
#' A deterministic, synthetic daily OHLCV (open / high / low / close / volume)
|
||||
#' price series for use in the examples, the *Getting started* vignette, and
|
||||
#' tests. It is a seeded random walk, **not** real market data. Regenerate with
|
||||
#' `data-raw/sample_ohlcv.R`.
|
||||
#'
|
||||
#' @format A data frame with 250 rows and 6 columns:
|
||||
#' \describe{
|
||||
#' \item{date}{Trading date (`Date`).}
|
||||
#' \item{open}{Opening price.}
|
||||
#' \item{high}{Session high.}
|
||||
#' \item{low}{Session low.}
|
||||
#' \item{close}{Closing price.}
|
||||
#' \item{volume}{Traded volume.}
|
||||
#' }
|
||||
"sample_ohlcv"
|
||||
@@ -0,0 +1,31 @@
|
||||
# Generates data/sample_ohlcv.rda — a deterministic, synthetic daily OHLCV
|
||||
# series used by the examples, the getting-started vignette, and tests. It is a
|
||||
# seeded random walk, NOT real market data.
|
||||
#
|
||||
# Regenerate (run from the R package root, bindings/r):
|
||||
# Rscript data-raw/sample_ohlcv.R
|
||||
|
||||
set.seed(42)
|
||||
n <- 250L
|
||||
dates <- seq(as.Date("2023-01-02"), by = "day", length.out = n)
|
||||
|
||||
# Random-walk close with a mild upward drift; derive OHLC around it.
|
||||
returns <- rnorm(n, mean = 0.0004, sd = 0.012)
|
||||
close <- round(100 * cumprod(1 + returns), 2)
|
||||
open <- round(c(100, head(close, -1)) * (1 + rnorm(n, 0, 0.003)), 2)
|
||||
high <- round(pmax(open, close) * (1 + abs(rnorm(n, 0, 0.004))), 2)
|
||||
low <- round(pmin(open, close) * (1 - abs(rnorm(n, 0, 0.004))), 2)
|
||||
volume <- round(1e6 * exp(rnorm(n, 0, 0.3)))
|
||||
|
||||
sample_ohlcv <- data.frame(
|
||||
date = dates,
|
||||
open = open,
|
||||
high = high,
|
||||
low = low,
|
||||
close = close,
|
||||
volume = volume
|
||||
)
|
||||
|
||||
save(sample_ohlcv, file = "data/sample_ohlcv.rda", compress = "xz", version = 2)
|
||||
cat(sprintf("wrote data/sample_ohlcv.rda: %d rows x %d cols\n",
|
||||
nrow(sample_ohlcv), ncol(sample_ohlcv)))
|
||||
Binary file not shown.
@@ -0,0 +1,27 @@
|
||||
% Generated by roxygen2: do not edit by hand
|
||||
% Please edit documentation in R/data.R
|
||||
\docType{data}
|
||||
\name{sample_ohlcv}
|
||||
\alias{sample_ohlcv}
|
||||
\title{Synthetic daily OHLCV sample series}
|
||||
\format{
|
||||
A data frame with 250 rows and 6 columns:
|
||||
\describe{
|
||||
\item{date}{Trading date (\code{Date}).}
|
||||
\item{open}{Opening price.}
|
||||
\item{high}{Session high.}
|
||||
\item{low}{Session low.}
|
||||
\item{close}{Closing price.}
|
||||
\item{volume}{Traded volume.}
|
||||
}
|
||||
}
|
||||
\usage{
|
||||
sample_ohlcv
|
||||
}
|
||||
\description{
|
||||
A deterministic, synthetic daily OHLCV (open / high / low / close / volume)
|
||||
price series for use in the examples, the \emph{Getting started} vignette, and
|
||||
tests. It is a seeded random walk, \strong{not} real market data. Regenerate with
|
||||
\code{data-raw/sample_ohlcv.R}.
|
||||
}
|
||||
\keyword{datasets}
|
||||
@@ -0,0 +1,113 @@
|
||||
---
|
||||
title: "Getting started with wickra"
|
||||
output: rmarkdown::html_vignette
|
||||
vignette: >
|
||||
%\VignetteIndexEntry{Getting started with wickra}
|
||||
%\VignetteEngine{knitr::rmarkdown}
|
||||
%\VignetteEncoding{UTF-8}
|
||||
---
|
||||
|
||||
```{r setup, include = FALSE}
|
||||
knitr::opts_chunk$set(collapse = TRUE, comment = "#>")
|
||||
```
|
||||
|
||||
`wickra` exposes the Wickra technical-analysis library in R over its C ABI hub.
|
||||
Every indicator is a constructor returning a `wickra_indicator`; you feed it data
|
||||
one observation at a time with `update()` (an O(1) streaming step) or run a whole
|
||||
series at once with `batch()`. Both paths share the exact same Rust core, so a
|
||||
live feed and a historical backtest compute identical values.
|
||||
|
||||
```{r}
|
||||
library(wickra)
|
||||
```
|
||||
|
||||
## A sample series
|
||||
|
||||
The package ships a small synthetic OHLCV series, `sample_ohlcv`, for examples
|
||||
(a seeded random walk — not real market data).
|
||||
|
||||
```{r}
|
||||
head(sample_ohlcv)
|
||||
```
|
||||
|
||||
## Batch: a whole series at once
|
||||
|
||||
Scalar indicators run over a vector with `batch()`. Warmup positions are `NA`.
|
||||
|
||||
```{r}
|
||||
sma <- Sma(20)
|
||||
sma_values <- batch(sma, sample_ohlcv$close)
|
||||
tail(sma_values)
|
||||
```
|
||||
|
||||
## Streaming: one observation at a time
|
||||
|
||||
The same indicator fed tick-by-tick with `update()` returns the identical
|
||||
values — an equivalence the test suite enforces for every indicator.
|
||||
|
||||
```{r}
|
||||
sma_stream <- Sma(20)
|
||||
streamed <- vapply(sample_ohlcv$close, function(p) update(sma_stream, p), numeric(1))
|
||||
|
||||
same_warmup <- all(is.na(streamed) == is.na(sma_values))
|
||||
same_values <- all(streamed == sma_values, na.rm = TRUE)
|
||||
c(batch_equals_streaming = same_warmup && same_values)
|
||||
```
|
||||
|
||||
A typical streaming loop reacts to each value as it arrives:
|
||||
|
||||
```{r}
|
||||
rsi <- Rsi(14)
|
||||
overbought_days <- 0L
|
||||
for (price in sample_ohlcv$close) {
|
||||
v <- update(rsi, price) # NA during warmup
|
||||
if (!is.na(v) && v > 70) overbought_days <- overbought_days + 1L
|
||||
}
|
||||
overbought_days
|
||||
```
|
||||
|
||||
## Multi-output indicators
|
||||
|
||||
Indicators with several outputs return a *named* numeric vector (`NA` while
|
||||
warming up). MACD is the classic example — line, signal, and histogram:
|
||||
|
||||
```{r}
|
||||
macd <- MacdIndicator(12, 26, 9)
|
||||
last_macd <- c(macd = NA, signal = NA, histogram = NA)
|
||||
for (price in sample_ohlcv$close) last_macd <- update(macd, price)
|
||||
last_macd
|
||||
```
|
||||
|
||||
## Candle indicators
|
||||
|
||||
Indicators that need the whole bar take the OHLCV fields plus a timestamp:
|
||||
|
||||
```{r}
|
||||
atr <- Atr(14)
|
||||
last_atr <- NA_real_
|
||||
for (i in seq_len(nrow(sample_ohlcv))) {
|
||||
last_atr <- update(
|
||||
atr,
|
||||
sample_ohlcv$open[i], sample_ohlcv$high[i], sample_ohlcv$low[i],
|
||||
sample_ohlcv$close[i], sample_ohlcv$volume[i], i - 1
|
||||
)
|
||||
}
|
||||
last_atr
|
||||
```
|
||||
|
||||
## Resetting state
|
||||
|
||||
`reset()` returns an indicator to its warmup state so the same object can be
|
||||
reused on a fresh series:
|
||||
|
||||
```{r}
|
||||
reset(sma)
|
||||
update(sma, 100) # NaN — warming up again
|
||||
```
|
||||
|
||||
## Next steps
|
||||
|
||||
- Full indicator catalogue, guides, and per-indicator reference:
|
||||
<https://docs.wickra.org>.
|
||||
- Every constructor (`Sma()`, `Rsi()`, `MacdIndicator()`, `Atr()`, …) is listed
|
||||
in this package's help index.
|
||||
Reference in New Issue
Block a user