docs: add ARCHITECTURE, ROADMAP, CITATION, FUNDING, editorconfig (#62)
Five governance + onboarding files that collectively close the "no high-level documentation outside of README" gap. - ARCHITECTURE.md: workspace layout, Indicator trait contract, per-indicator file conventions, numerical-stability notes, cross-crate flow diagram, navigation cheatsheet, deliberate non-goals, performance characteristics, stability commitments. - ROADMAP.md: north star, 0.3 / 0.4 / 0.5 release windows, indicator-wishlist intake rules, explicit non-goals, versioning policy. - CITATION.cff: GitHub-renders as "Cite this repository" button; enables academic adoption. - .github/FUNDING.yml: surfaces Sponsor button on the repo page. - .editorconfig: normalises indent/EOL across IDEs (Rust/Python 4 spaces, JS/TS/JSON/YAML/MD 2 spaces, Makefile tabs). Touches no Rust source, no CI workflows, no behaviour. Additive only. URLs in ROADMAP/CITATION already reference the post-transfer `wickra-lib/wickra` org so the files stay valid once the org migration in PR #59 lands; merge this PR only after #59 to keep main consistent.
This commit is contained in:
@@ -0,0 +1,34 @@
|
|||||||
|
# EditorConfig: https://editorconfig.org
|
||||||
|
# Keeps indentation and line-endings consistent across IDEs.
|
||||||
|
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
indent_style = space
|
||||||
|
|
||||||
|
# Rust + Python + most config files use 4-space indents.
|
||||||
|
[*.{rs,py,toml}]
|
||||||
|
indent_size = 4
|
||||||
|
|
||||||
|
# JS / TS / JSON / YAML / Markdown use 2-space indents per ecosystem conventions.
|
||||||
|
[*.{js,ts,jsx,tsx,json,yml,yaml,md}]
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
# Markdown allows trailing whitespace as a hard line break — keep it intact.
|
||||||
|
[*.md]
|
||||||
|
trim_trailing_whitespace = false
|
||||||
|
|
||||||
|
# Makefiles must use tabs.
|
||||||
|
[Makefile]
|
||||||
|
indent_style = tab
|
||||||
|
|
||||||
|
# Generated files are not authored by humans; leave them alone.
|
||||||
|
[bindings/node/index.{js,d.ts}]
|
||||||
|
indent_style = unset
|
||||||
|
indent_size = unset
|
||||||
|
trim_trailing_whitespace = unset
|
||||||
|
insert_final_newline = unset
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
# Funding sources surfaced on the repository "Sponsor" button.
|
||||||
|
# Each platform's value is the username/handle on that platform.
|
||||||
|
# Leave a key empty (e.g. patreon:) to skip a platform.
|
||||||
|
|
||||||
|
github: [kingchenc]
|
||||||
|
custom: ["https://wickra.org/sponsor"]
|
||||||
+321
@@ -0,0 +1,321 @@
|
|||||||
|
# Architecture
|
||||||
|
|
||||||
|
A walkthrough of how Wickra is organised internally — written for new
|
||||||
|
contributors who want to know **where the code lives, why it's split that
|
||||||
|
way, and which invariants they must not break**. Pair it with [`CONTRIBUTING.md`](CONTRIBUTING.md)
|
||||||
|
for the day-to-day workflow.
|
||||||
|
|
||||||
|
## Workspace layout
|
||||||
|
|
||||||
|
Wickra is a Cargo workspace of three Rust crates plus three binding crates.
|
||||||
|
The split is deliberate: every concern that one user might want to disable
|
||||||
|
or replace lives behind a separate crate boundary.
|
||||||
|
|
||||||
|
```
|
||||||
|
┌────────────────────────────────────────────────────────────────────┐
|
||||||
|
│ wickra (facade) │
|
||||||
|
│ re-exports wickra-core::* + wickra-data::* │
|
||||||
|
└──────────────┬──────────────────────────────────┬──────────────────┘
|
||||||
|
│ │
|
||||||
|
┌───────────▼──────────┐ ┌──────────▼─────────┐
|
||||||
|
│ wickra-core │ │ wickra-data │
|
||||||
|
│ indicator engine │ │ i/o + aggregation │
|
||||||
|
│ • 214 indicators │ │ • CSV reader │
|
||||||
|
│ • Indicator trait │ │ • Tick aggregator │
|
||||||
|
│ • BatchExt impl │ │ • Resampler │
|
||||||
|
│ • OHLCV / Candle │ │ • Live feeds │
|
||||||
|
│ no I/O, no deps │ │ optional features │
|
||||||
|
└──────────────────────┘ └────────────────────┘
|
||||||
|
▲
|
||||||
|
│ (every binding wraps the same core)
|
||||||
|
│
|
||||||
|
┌────────────┴───────────┬─────────────────────┐
|
||||||
|
│ │ │
|
||||||
|
┌──▼──────┐ ┌───────▼──────┐ ┌───────▼────────┐
|
||||||
|
│ Python │ │ Node │ │ WASM │
|
||||||
|
│ (PyO3) │ │ (napi-rs) │ │ (wasm-bindgen) │
|
||||||
|
└─────────┘ └──────────────┘ └────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
| Crate | Path | What it owns | Public deps |
|
||||||
|
|---|---|---|---|
|
||||||
|
| `wickra-core` | `crates/wickra-core` | every indicator, the `Indicator` trait, `BatchExt`, `Candle`/`Tick` types, `Error` | `thiserror`, `rayon` (parallel batch) |
|
||||||
|
| `wickra` | `crates/wickra` | thin facade — re-exports everything user-facing from `wickra-core` and `wickra-data` | both internal crates |
|
||||||
|
| `wickra-data` | `crates/wickra-data` | CSV reader, tick aggregator, resampler, live exchange feeds (feature-gated) | `tokio`, `tokio-tungstenite` (live), `serde_json` |
|
||||||
|
| `wickra-python` | `bindings/python` | `_wickra` PyO3 module + Python package | `pyo3`, `numpy`, depends on `wickra-core` |
|
||||||
|
| `wickra-node` | `bindings/node` | NAPI-RS native binding | `napi`, depends on `wickra-core` |
|
||||||
|
| `wickra-wasm` | `bindings/wasm` | WebAssembly binding | `wasm-bindgen`, depends on `wickra-core` |
|
||||||
|
| `wickra-examples` | `examples/rust` | runnable binary examples | depends on `wickra`, `wickra-data` |
|
||||||
|
|
||||||
|
The `fuzz/` directory is **excluded** from the workspace (it has its own
|
||||||
|
`Cargo.toml`) because the libfuzzer-sys harness requires a nightly
|
||||||
|
toolchain, which would otherwise infect the stable workspace lints.
|
||||||
|
|
||||||
|
## The `Indicator` trait
|
||||||
|
|
||||||
|
Every indicator in Wickra implements one trait, defined in
|
||||||
|
`crates/wickra-core/src/traits.rs`:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
pub trait Indicator {
|
||||||
|
type Input;
|
||||||
|
type Output;
|
||||||
|
|
||||||
|
fn update(&mut self, input: Self::Input) -> Option<Self::Output>;
|
||||||
|
fn reset(&mut self);
|
||||||
|
fn warmup_period(&self) -> usize;
|
||||||
|
fn is_ready(&self) -> bool;
|
||||||
|
fn name(&self) -> &'static str;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Four design choices that are non-negotiable:
|
||||||
|
|
||||||
|
1. **Streaming-first.** `update` is the only computation entry point. Each
|
||||||
|
call must be O(1) amortised — no replays over history, no `clone`s of
|
||||||
|
the input window unless absolutely necessary.
|
||||||
|
2. **`Option<Output>` warmup.** A new indicator returns `None` until it has
|
||||||
|
ingested `warmup_period()` inputs. After that it returns `Some(value)`
|
||||||
|
on every call. The `None` → `Some` transition happens exactly once per
|
||||||
|
`reset()`.
|
||||||
|
3. **Reset is mandatory.** Calling `reset()` returns the indicator to the
|
||||||
|
state of a newly constructed one. Tests verify this for every indicator.
|
||||||
|
4. **No interior mutability across `update` calls.** Indicators may hold
|
||||||
|
`VecDeque` / array state, but no `Cell`/`RefCell`/`Mutex` should be
|
||||||
|
needed — `&mut self` is the only mutation channel.
|
||||||
|
|
||||||
|
### Batch is free
|
||||||
|
|
||||||
|
`BatchExt` is a blanket impl over `Indicator`:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
impl<I: Indicator> BatchExt for I {
|
||||||
|
fn batch<'a>(&mut self, input: &'a [I::Input]) -> Vec<Option<I::Output>>
|
||||||
|
where I::Input: Copy
|
||||||
|
{
|
||||||
|
input.iter().map(|x| self.update(*x)).collect()
|
||||||
|
}
|
||||||
|
fn batch_parallel(...) // rayon-based for multi-asset processing
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Consequence: **every indicator gets batch and parallel-batch for free** as
|
||||||
|
soon as `Indicator` is implemented. Tests verify `batch == streaming`
|
||||||
|
equivalence on every indicator — this is the `batch_equals_streaming` test
|
||||||
|
that appears in every indicator module.
|
||||||
|
|
||||||
|
## Indicator-module convention
|
||||||
|
|
||||||
|
Each indicator lives in its own file under
|
||||||
|
`crates/wickra-core/src/indicators/`. Naming: snake-case of the struct,
|
||||||
|
e.g. `Sma` → `sma.rs`, `MacdIndicator` → `macd.rs`.
|
||||||
|
|
||||||
|
Layout inside an indicator file is uniform:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
//! Doc-comment with the formula and one-line summary.
|
||||||
|
|
||||||
|
use std::collections::VecDeque;
|
||||||
|
use crate::error::{Error, Result};
|
||||||
|
use crate::traits::Indicator;
|
||||||
|
|
||||||
|
/// Public struct + rustdoc with mathematical definition + a runnable example.
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Foo { /* state fields */ }
|
||||||
|
|
||||||
|
impl Foo {
|
||||||
|
/// Constructor with parameter validation.
|
||||||
|
pub fn new(period: usize, ...) -> Result<Self> { ... }
|
||||||
|
/// Const accessors for configured params.
|
||||||
|
pub const fn period(&self) -> usize { ... }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Indicator for Foo {
|
||||||
|
type Input = f64; // or (f64, f64), or Candle
|
||||||
|
type Output = f64; // or FooOutput { ... }
|
||||||
|
fn update(...) -> ... { ... }
|
||||||
|
fn reset(...) { ... }
|
||||||
|
fn warmup_period(...) -> usize { ... }
|
||||||
|
fn is_ready(...) -> bool { ... }
|
||||||
|
fn name(...) -> &'static str { "Foo" }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
// mandatory tests (every indicator):
|
||||||
|
// - rejects_invalid_params
|
||||||
|
// - accessors_and_metadata
|
||||||
|
// - reference_value (vs TA-Lib / pandas-ta / hand-calculated)
|
||||||
|
// - ignores_non_finite_input
|
||||||
|
// - reset_clears_state
|
||||||
|
// - batch_equals_streaming
|
||||||
|
// plus indicator-specific edge cases
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `FAMILIES` constant in `mod.rs` (introduced in PR #60) is the
|
||||||
|
machine-readable index of which family every indicator belongs to. It is
|
||||||
|
the canonical taxonomy; README and Wiki tables should be derived from it.
|
||||||
|
|
||||||
|
## Input types
|
||||||
|
|
||||||
|
| Input | Used for | Examples |
|
||||||
|
|---|---|---|
|
||||||
|
| `f64` | Scalar inputs — usually a price or a return | SMA, EMA, RSI, ROC |
|
||||||
|
| `Candle` | OHLCV bar — `{open, high, low, close, volume, timestamp}` | ATR, Bollinger, Ichimoku, all candlestick patterns |
|
||||||
|
| `(f64, f64)` | Two-series indicators — `(asset, benchmark)` or `(x, y)` | PearsonCorrelation, Beta, Alpha, TreynorRatio |
|
||||||
|
|
||||||
|
The `Candle` type lives in `wickra-core::ohlcv` and is the binding
|
||||||
|
contract across bindings — Python's `Candle` namedtuple, Node's
|
||||||
|
`Candle` object, and WASM's `Candle` JS class all map 1:1.
|
||||||
|
|
||||||
|
## Output types
|
||||||
|
|
||||||
|
Most indicators emit `f64`. Multi-output indicators emit a dedicated
|
||||||
|
struct in the same module, named `FooOutput`:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
pub struct BollingerOutput {
|
||||||
|
pub upper: f64,
|
||||||
|
pub middle: f64,
|
||||||
|
pub lower: f64,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Bindings flatten these into matrix outputs (NumPy 2-D array for Python,
|
||||||
|
typed object arrays for Node/WASM).
|
||||||
|
|
||||||
|
## Numerical-stability notes
|
||||||
|
|
||||||
|
A handful of indicators need care beyond naive accumulation:
|
||||||
|
|
||||||
|
- **Welford's online variance** is used in `StdDev`, `Variance`, `ZScore`,
|
||||||
|
`BollingerBands`, and several others. Standard sum-of-squares is
|
||||||
|
catastrophically lossy for low-variance inputs; Welford's recurrence
|
||||||
|
keeps O(eps) error.
|
||||||
|
- **Kahan summation** is used wherever rolling sums could span > 1e6
|
||||||
|
elements without resetting — currently only Hurst-exponent's R/S
|
||||||
|
chunks. Most rolling sums are bounded by the window size and don't need
|
||||||
|
it.
|
||||||
|
- **Logarithm bases** matter for some indicators (Hurst, MFI). Wickra
|
||||||
|
uses natural log everywhere unless the reference math explicitly
|
||||||
|
requires `log10` or `log2` — and then it documents the choice in the
|
||||||
|
rustdoc.
|
||||||
|
- **NaN / infinity guards.** Every indicator's `update` rejects
|
||||||
|
non-finite input early (returns `None` without state mutation). Tests
|
||||||
|
cover this with `ignores_non_finite_input`.
|
||||||
|
|
||||||
|
## Cross-crate flow
|
||||||
|
|
||||||
|
A typical full-stack call sequence for a Python live-trading example:
|
||||||
|
|
||||||
|
```
|
||||||
|
[ Python: live_trading.py ]
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
[ binance.AsyncClient WebSocket ] ──── wickra_data live feed ───┐
|
||||||
|
│
|
||||||
|
┌──────────────────┘
|
||||||
|
▼
|
||||||
|
[ Candle struct conversion ]
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
[ PyRsi.update(close) ]
|
||||||
|
│
|
||||||
|
wraps │
|
||||||
|
▼
|
||||||
|
[ wickra_core::Rsi::update(f64) ] <-- the only place math runs
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
[ Option<f64> -> Py<PyFloat> ]
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
[ Python user code ]
|
||||||
|
```
|
||||||
|
|
||||||
|
The same call sequence happens identically for Node (via NAPI),
|
||||||
|
WASM (via wasm-bindgen → JS), and Rust (no FFI overhead, just direct
|
||||||
|
calls).
|
||||||
|
|
||||||
|
## What lives where — the navigation cheat sheet
|
||||||
|
|
||||||
|
| You want to … | Look in |
|
||||||
|
|---|---|
|
||||||
|
| add a new indicator | `crates/wickra-core/src/indicators/<name>.rs` + add to `mod.rs` + add to `FAMILIES` + re-export in `lib.rs` |
|
||||||
|
| change the `Indicator` trait surface | `crates/wickra-core/src/traits.rs` — this affects every indicator, treat as breaking |
|
||||||
|
| add a new Candle field | `crates/wickra-core/src/ohlcv.rs` — also propagates to every binding's `Candle` mapping |
|
||||||
|
| add a new exchange / data source | `crates/wickra-data/src/live/<exchange>.rs`, feature-gated under `live-<exchange>` |
|
||||||
|
| expose a new binding | new crate under `bindings/` + macro-driven boilerplate in `bindings/<lang>/src/lib.rs` |
|
||||||
|
| change benchmark coverage | `crates/wickra/benches/indicators.rs` |
|
||||||
|
| add a new fuzz target | `fuzz/fuzz_targets/<name>.rs` + register in `fuzz/Cargo.toml` |
|
||||||
|
| change CI matrix | `.github/workflows/ci.yml` |
|
||||||
|
| change release pipeline | `.github/workflows/release.yml` (irreversible on `v*` tag — test on a throwaway tag first) |
|
||||||
|
|
||||||
|
## What is **deliberately** not in this repo
|
||||||
|
|
||||||
|
- **Backtest framework.** Wickra is an indicator library, not a backtester.
|
||||||
|
Strategy + PnL + fills logic is for the user (see `examples/` for
|
||||||
|
illustrative scripts).
|
||||||
|
- **Multi-exchange aggregation.** Binance is the demo feed; full
|
||||||
|
exchange-agnostic aggregation is `ccxt`'s job. Wickra's
|
||||||
|
`wickra-data::live` is intentionally minimal.
|
||||||
|
- **Order-book / L2 data.** Wickra works on OHLCV bars and ticks, not
|
||||||
|
full depth. Tick-data variants (cumulative delta, single print) are on
|
||||||
|
the roadmap but require new input types.
|
||||||
|
- **Charting / visualization.** Out of scope for the Rust core. The
|
||||||
|
WASM examples include a `lightweight-charts` integration as a
|
||||||
|
starting point, but no charting code lives in the published packages.
|
||||||
|
- **GPU / SIMD optimisation.** Indicators are O(1) per update — the
|
||||||
|
bottleneck is not vector throughput. SIMD would only help large-batch
|
||||||
|
workloads, which already saturate memory bandwidth via the cache-
|
||||||
|
friendly `VecDeque` window.
|
||||||
|
|
||||||
|
## Performance characteristics
|
||||||
|
|
||||||
|
Every indicator is amortised O(1) per `update`. The constant factor
|
||||||
|
varies:
|
||||||
|
|
||||||
|
| Class | Indicators | Per-`update` cost (approx) |
|
||||||
|
|---|---|---|
|
||||||
|
| Simple rolling | SMA, EMA, WMA, Mom | 1-2 floating-point ops |
|
||||||
|
| Recursive smoothers | KAMA, FRAMA, VIDYA, JMA | 5-15 ops |
|
||||||
|
| Window-sort | OmegaRatio, percentile-based VaR | O(period · log period) per update |
|
||||||
|
| Multi-buffer DSP | MAMA, HilbertDominantCycle, EmpiricalModeDecomposition | 30-80 ops |
|
||||||
|
| Multi-component | MacdIndicator, TtmSqueeze, Alligator | sum of components |
|
||||||
|
|
||||||
|
Benchmarks against real BTCUSDT 1-minute data live in
|
||||||
|
`crates/wickra/benches/indicators.rs`. Cross-library comparison vs
|
||||||
|
TA-Lib / pandas-ta / talipp / finta lives in
|
||||||
|
`bindings/python/benchmarks/compare_libraries.py`.
|
||||||
|
|
||||||
|
## Stability commitments
|
||||||
|
|
||||||
|
- **MSRV.** Workspace: Rust 1.86. Node binding: 1.88 (NAPI-RS pins it).
|
||||||
|
- **`Indicator` trait surface.** Breaking changes here are major-version
|
||||||
|
events. Adding a new method with a default impl is minor.
|
||||||
|
- **Indicator removal.** Once an indicator ships in a release, it stays
|
||||||
|
callable. Renames go through a deprecation period of at least one
|
||||||
|
minor version.
|
||||||
|
- **Output structs.** Adding a field to a `FooOutput` is non-breaking
|
||||||
|
because the binding contracts go through serde and accept extra keys.
|
||||||
|
|
||||||
|
## Open questions / known sharp edges
|
||||||
|
|
||||||
|
These are documented for contributors so you don't waste time
|
||||||
|
re-discovering them.
|
||||||
|
|
||||||
|
- **`Rvi`** (Relative Vigor Index) and `RviVolatility` (Relative
|
||||||
|
Volatility Index) are different indicators with the same short
|
||||||
|
acronym — make sure you import the right one.
|
||||||
|
- **Fuzz coverage of pair indicators** uses `indicator_update_pair.rs`,
|
||||||
|
which is small because pair indicators are simpler — but coverage
|
||||||
|
should grow as more pair indicators land.
|
||||||
|
- **`FAMILIES` (from PR #60) is hand-maintained.** Adding a new
|
||||||
|
indicator requires a separate entry in `FAMILIES`. The
|
||||||
|
`total_count_matches_expected` test will fail if you forget.
|
||||||
|
- **WASM does not have automated tests yet.** Smoke-validated only
|
||||||
|
through the manual examples. Adding `wasm-bindgen-test` coverage is
|
||||||
|
on the roadmap.
|
||||||
|
|
||||||
|
For the high-level project goals see [`ROADMAP.md`](ROADMAP.md); for
|
||||||
|
day-to-day contribution mechanics see [`CONTRIBUTING.md`](CONTRIBUTING.md).
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
cff-version: 1.2.0
|
||||||
|
title: Wickra
|
||||||
|
message: >-
|
||||||
|
If you use Wickra in academic work, please cite it using the metadata
|
||||||
|
below.
|
||||||
|
type: software
|
||||||
|
authors:
|
||||||
|
- alias: kingchenc
|
||||||
|
email: wickra.lib@gmail.com
|
||||||
|
repository-code: "https://github.com/wickra-lib/wickra"
|
||||||
|
url: "https://wickra.org"
|
||||||
|
abstract: >-
|
||||||
|
Wickra is a streaming-first technical-analysis library implemented in
|
||||||
|
Rust with bindings for Python, Node.js and WebAssembly. Each indicator
|
||||||
|
is a state machine that updates in constant time per new input, so
|
||||||
|
identical code paths serve live-trading workloads and historical
|
||||||
|
back-testing. The library covers 214 indicators across 16 families
|
||||||
|
(moving averages, momentum, volatility, volume, statistics, Ehlers
|
||||||
|
digital-signal-processing cycles, pivots, DeMark, Ichimoku, candlestick
|
||||||
|
patterns, market profile, and risk/performance metrics).
|
||||||
|
keywords:
|
||||||
|
- technical-analysis
|
||||||
|
- technical-indicators
|
||||||
|
- streaming
|
||||||
|
- algorithmic-trading
|
||||||
|
- quantitative-finance
|
||||||
|
- rust
|
||||||
|
- time-series
|
||||||
|
license: PolyForm-Noncommercial-1.0.0
|
||||||
+203
@@ -0,0 +1,203 @@
|
|||||||
|
# Roadmap
|
||||||
|
|
||||||
|
What Wickra is heading toward, what is explicitly out of scope, and what
|
||||||
|
contributors can expect across the next 0.x versions. Roadmap items are
|
||||||
|
**aspirations, not commitments** — order may shift based on real
|
||||||
|
user-feedback and bug-priority.
|
||||||
|
|
||||||
|
For "what shipped already" see [`CHANGELOG.md`](CHANGELOG.md). For the
|
||||||
|
internal structure that the roadmap items will plug into, see
|
||||||
|
[`ARCHITECTURE.md`](ARCHITECTURE.md).
|
||||||
|
|
||||||
|
## North star
|
||||||
|
|
||||||
|
> A streaming-first technical-analysis core that is the obvious default
|
||||||
|
> for anyone writing a Rust, Python, Node or browser-based trading
|
||||||
|
> system — drop-in fast, drop-in correct, drop-in tested.
|
||||||
|
|
||||||
|
Three measurable proxies for "obvious default":
|
||||||
|
|
||||||
|
1. **Coverage.** Every textbook indicator from TA-Lib, pandas-ta and
|
||||||
|
talipp is in Wickra and produces matching reference values.
|
||||||
|
2. **Performance.** Streaming `update` is the fastest published number
|
||||||
|
across Rust / Python / Node / WASM for any technical indicator.
|
||||||
|
3. **Trust.** Releases are reproducible, signed, SBOM-attached, with a
|
||||||
|
public 100% test/branch coverage badge.
|
||||||
|
|
||||||
|
## 0.3.0 — target window: Q3 2026
|
||||||
|
|
||||||
|
The first release after the org migration to `wickra-lib` lands and the
|
||||||
|
project portal at `wickra.org` is live.
|
||||||
|
|
||||||
|
### Headline goals
|
||||||
|
|
||||||
|
- **WASM has automated tests.** `wasm-bindgen-test` job in CI exercising
|
||||||
|
a representative subset (~30 indicators across all families). Today
|
||||||
|
WASM is only smoke-validated through manual examples.
|
||||||
|
- **Release-pipeline trust.** SBOM (CycloneDX) generated per release,
|
||||||
|
Sigstore cosign signatures attached to every published artifact,
|
||||||
|
npm `--provenance` flag enabled, PyPI Trusted Publishers configured.
|
||||||
|
- **Hosted documentation portal.** `wickra.org` (Cloudflare Pages,
|
||||||
|
VitePress) replaces the GitHub Wiki as the canonical doc surface.
|
||||||
|
Per-indicator deep-dives, quickstarts, FAQ, search.
|
||||||
|
- **End-to-end strategy examples.** 3 runnable examples that wire
|
||||||
|
Wickra indicators into a full mean-reversion / trend-following /
|
||||||
|
breakout strategy with PnL and equity-curve output.
|
||||||
|
- **`ARCHITECTURE.md` + `ROADMAP.md` + `CITATION.cff`** governance
|
||||||
|
baseline (this is it).
|
||||||
|
|
||||||
|
### Stretch goals (might slip to 0.4.0)
|
||||||
|
|
||||||
|
- **Per-binding hosted API reference.** TypeDoc for Node/WASM,
|
||||||
|
Sphinx for Python, both hosted on `wickra.org/api/*`. Rust stays on
|
||||||
|
`docs.rs`.
|
||||||
|
- **Property-tests (`proptest`) for mathematical invariants.** Bound
|
||||||
|
checks on RSI ∈ [0, 100], Bollinger ordering, batch-streaming
|
||||||
|
equivalence on random inputs.
|
||||||
|
- **Nightly long-fuzz workflow.** Each fuzz target gets ~1h overnight,
|
||||||
|
findings auto-converted to issues.
|
||||||
|
|
||||||
|
## 0.4.0 — target window: Q4 2026
|
||||||
|
|
||||||
|
### Indicator catalogue expansion
|
||||||
|
|
||||||
|
The current 214 indicators cover the textbook canon. The next wave is
|
||||||
|
the "stuff people actually ask for but skip because it's painful in
|
||||||
|
other libs":
|
||||||
|
|
||||||
|
- **Anchored indicators.** AnchoredVwap is already in, but anchored
|
||||||
|
variants of common indicators (AnchoredATR, AnchoredVolatility) are
|
||||||
|
on the wishlist for explicit session-based analysis.
|
||||||
|
- **Multi-timeframe (MTF) chaining helpers.** A `Mtf<Indicator>` wrapper
|
||||||
|
that runs an indicator on a different timeframe of the same input
|
||||||
|
stream — solves the most common reason people drop down to ad-hoc
|
||||||
|
buffering code.
|
||||||
|
- **Order-flow primitives** (gated on tick-data ingestion landing in
|
||||||
|
`wickra-data`): CumulativeDelta, BidAskImbalance, VolumeAtPrice.
|
||||||
|
- **Pivot-confirmation patterns.** WilliamsFractals is already in;
|
||||||
|
ZigZag is in. Next: PivotHigh/PivotLow with configurable
|
||||||
|
left/right-bar confirmation, used as a feature for higher-level
|
||||||
|
pattern detectors.
|
||||||
|
- **Harmonic-chart patterns** (Gartley, Bat, Butterfly, Crab, Shark).
|
||||||
|
These need the pivot-detector + ratio-matcher framework first; the
|
||||||
|
candlestick-pattern family from 0.2.8 is the precedent.
|
||||||
|
|
||||||
|
### Live-data layer
|
||||||
|
|
||||||
|
- **Tick-data ingestion.** Extend `wickra-data` from OHLCV-only to
|
||||||
|
also accept raw ticks; the existing `Aggregator` already aggregates
|
||||||
|
ticks into bars but isn't exposed in the public live-feed API yet.
|
||||||
|
- **Generic exchange trait.** `LiveFeed { fn subscribe(...) -> impl
|
||||||
|
Stream<Item = Candle> }` so the Binance adapter is one implementor
|
||||||
|
among many. **Note**: Wickra will not aggregate exchanges itself
|
||||||
|
(use `ccxt` if you need that) — the trait exists so user code can
|
||||||
|
swap feeds without touching indicator code.
|
||||||
|
|
||||||
|
### Performance & reliability
|
||||||
|
|
||||||
|
- **Performance-regression tracking.** `bench.yml` outputs deployed to
|
||||||
|
a `gh-pages` branch, `github-action-benchmark` plot over time,
|
||||||
|
threshold-based alerts on regression.
|
||||||
|
- **Indicator parity test suite.** Every indicator that has a TA-Lib
|
||||||
|
/ pandas-ta / talipp equivalent must pass a golden-value test
|
||||||
|
against that reference. Currently most do but the test names are
|
||||||
|
scattered — consolidate into one `parity_tests` module.
|
||||||
|
|
||||||
|
## 0.5.0 — target window: 2027 H1
|
||||||
|
|
||||||
|
### Possible new bindings
|
||||||
|
|
||||||
|
Open questions, prioritised by demand signals (≈ GitHub stars + issue
|
||||||
|
requests + community polls):
|
||||||
|
|
||||||
|
- **Java / Kotlin** binding via UniFFI — interest from Android-side
|
||||||
|
trading-app developers and the JVM-quant community.
|
||||||
|
- **Go** binding — interest from algorithmic-trading shops running on
|
||||||
|
Linux + Go infra.
|
||||||
|
- **C / C++** header export (`cbindgen`) — drops Wickra into existing
|
||||||
|
C/C++ trading stacks (e.g. older Bloomberg / FIX-protocol shops).
|
||||||
|
- **Swift** — niche but real, iOS / macOS native trading apps.
|
||||||
|
- **.NET** — closes the Windows-native gap that NAPI-Node doesn't fill
|
||||||
|
(some shops are still on .NET Framework).
|
||||||
|
|
||||||
|
None of these are committed — each is a 1-2-month project on its own,
|
||||||
|
and bindings without active maintenance are a liability. Priority will
|
||||||
|
be driven by which language community shows up with PRs.
|
||||||
|
|
||||||
|
### `wickra-data` widening
|
||||||
|
|
||||||
|
- **Historical fetch from > 1 source.** Today only Binance REST/WS.
|
||||||
|
Add Coinbase and Kraken as reference implementations — explicitly
|
||||||
|
not exchange-aggregation, just "here are two more adapters using
|
||||||
|
the trait".
|
||||||
|
|
||||||
|
## Beyond — long-term aspirations
|
||||||
|
|
||||||
|
- **`wickra-backtest` sub-crate** (decision pending). A minimal
|
||||||
|
event-driven backtester wrapping signal generation + position
|
||||||
|
sizing + fees + slippage. Decision factor: do users keep building
|
||||||
|
these ad-hoc from `examples/`? If yes, codifying it saves the
|
||||||
|
ecosystem time. If most users plug Wickra into existing backtesters
|
||||||
|
(vectorbt, backtrader, Lean, Hummingbot), keep Wickra focused.
|
||||||
|
- **`wickra-plot` companion** (low priority). `plotters`-backed Rust
|
||||||
|
rendering of indicator outputs. Mainly useful for static report
|
||||||
|
generation; live charting belongs in the JS/web layer.
|
||||||
|
- **Academic adoption.** Citable `CITATION.cff`; targeting at least
|
||||||
|
one peer-reviewed paper using Wickra as the reference indicator
|
||||||
|
engine.
|
||||||
|
|
||||||
|
## What is explicitly **not** on the roadmap
|
||||||
|
|
||||||
|
These are recurring requests that Wickra will decline so contributors
|
||||||
|
don't waste time on them:
|
||||||
|
|
||||||
|
| Feature | Why declined |
|
||||||
|
|---|---|
|
||||||
|
| Exchange aggregation across N venues | That's `ccxt`'s job. Wickra ships *one* feed implementor (Binance) for tests and demo; users plug their preferred exchange. |
|
||||||
|
| Full backtesting framework (à la Lean, vectorbt) | Scope creep. May land as `wickra-backtest` *if* a clear minimal API surfaces from user demand, but Wickra core stays an indicator library. |
|
||||||
|
| Strategy auto-tuning / hyperparameter search | Wrong abstraction layer — belongs in user-side ML/backtester. |
|
||||||
|
| Order-management / broker integration | Even further out of scope. |
|
||||||
|
| GUI / web-based studio | Marketing-site demos are fine; full IDE is not. |
|
||||||
|
| Indicator implementations that require optional Python deps (e.g. scipy KDE) | Bindings must work on a clean install. Pure-Rust math only. |
|
||||||
|
| Proprietary indicator implementations (e.g. paywalled vendor formulas) | License conflicts + audit burden. |
|
||||||
|
| GPU / CUDA acceleration | O(1) per update means the bottleneck is API overhead, not compute. SIMD-batch is a maybe; GPU adds no value for streaming. |
|
||||||
|
|
||||||
|
## How indicator wishlist requests are handled
|
||||||
|
|
||||||
|
1. **Open an issue** using the `feature_request` template, naming the
|
||||||
|
indicator, citing one of:
|
||||||
|
- TA-Lib reference
|
||||||
|
- pandas-ta reference
|
||||||
|
- peer-reviewed paper
|
||||||
|
- widely-published trading book
|
||||||
|
2. Maintainer triages within ~1 week. Acceptance criteria:
|
||||||
|
- Formula has at least one written reference (no random
|
||||||
|
YouTuber-only indicators)
|
||||||
|
- Implementation can be O(1) streaming
|
||||||
|
- Test vectors are obtainable (from reference lib, hand-computed,
|
||||||
|
or paper-provided)
|
||||||
|
3. Once accepted, the indicator gets added to the next family-batch
|
||||||
|
PR. Family-batches typically ship 5-20 indicators at a time.
|
||||||
|
|
||||||
|
## Versioning
|
||||||
|
|
||||||
|
Wickra follows [SemVer](https://semver.org/). The promise:
|
||||||
|
|
||||||
|
- **0.x.0 (minor):** new indicators, new bindings, new optional features,
|
||||||
|
new optional config knobs. Adding methods to `Indicator` with default
|
||||||
|
impls is minor.
|
||||||
|
- **0.x.y (patch):** bug fixes, performance improvements, doc fixes.
|
||||||
|
- **Major (1.0.0 and later):** changes to the `Indicator` trait
|
||||||
|
signature, removal of indicators, breaking changes to `Candle` /
|
||||||
|
`OHLCV` field order.
|
||||||
|
|
||||||
|
The 1.0 milestone is reserved for when the indicator catalogue is
|
||||||
|
considered "stable enough" and the bindings API has stabilised — likely
|
||||||
|
~2027 once 2-3 more bindings have shipped and stress-tested the trait.
|
||||||
|
|
||||||
|
## Discussion
|
||||||
|
|
||||||
|
For roadmap discussion, open a [Discussions](https://github.com/wickra-lib/wickra/discussions)
|
||||||
|
thread tagged `roadmap`. Specific indicator wishlist items go in
|
||||||
|
[Issues](https://github.com/wickra-lib/wickra/issues) via the
|
||||||
|
`feature_request` template.
|
||||||
Reference in New Issue
Block a user