examples: move Rust examples into a top-level examples/rust/ crate

The three Rust examples (backtest, fetch_btcusdt, live_binance) used to
live each in their own crate's examples/ dir, splitting the example set
across crates and burying it inside the source tree. Move them into a new
workspace member crate at `examples/rust/` (package `wickra-examples`,
`publish = false`) so all language examples sit under one top-level
`examples/<lang>/` tree.

* `examples/rust/Cargo.toml` declares the per-binary deps (wickra,
  wickra-data with the `live-binance` feature always on, serde_json, tokio
  for the macro and current-thread runtime).
* `examples/rust/src/bin/{backtest,fetch_btcusdt,live_binance}.rs` are the
  three migrated binaries; their doc-comments and the fetch_btcusdt output
  path are updated for the new location and run command
  (`cargo run -p wickra-examples --bin <name>`).
* Workspace `Cargo.toml` lists the new member; the now-empty
  `[dev-dependencies]` extras (`wickra`, `tokio` in wickra-data and
  `serde_json` in wickra) that existed only for these examples are dropped.
* The `[[example]] live_binance` table is removed from wickra-data's
  manifest since the file moved out.
* README "Languages" + project-layout, examples/README.md, Quickstart-Rust
  and Data-Layer are pointed at the new paths and commands.

`cargo build -p wickra-examples` and `cargo run --release -p wickra-examples
--bin backtest -- examples/data/btcusdt-1d.csv` both succeed; the rest of
the workspace (core, data, wickra) builds, clippies (`--all-targets -D
warnings`) and tests (508 core + 28 data + 1 integration + 74+3+1
doctests) all stay green.
This commit is contained in:
kingchenc
2026-05-23 00:07:07 +02:00
parent a1c646ae7c
commit 747d1a5b1b
12 changed files with 68 additions and 41 deletions
Generated
+10 -2
View File
@@ -1974,7 +1974,6 @@ dependencies = [
"approx", "approx",
"criterion", "criterion",
"proptest", "proptest",
"serde_json",
"wickra-core", "wickra-core",
"wickra-data", "wickra-data",
] ]
@@ -2003,10 +2002,19 @@ dependencies = [
"tokio", "tokio",
"tokio-tungstenite", "tokio-tungstenite",
"url", "url",
"wickra",
"wickra-core", "wickra-core",
] ]
[[package]]
name = "wickra-examples"
version = "0.0.0"
dependencies = [
"serde_json",
"tokio",
"wickra",
"wickra-data",
]
[[package]] [[package]]
name = "wickra-node" name = "wickra-node"
version = "0.1.4" version = "0.1.4"
+1
View File
@@ -7,6 +7,7 @@ members = [
"bindings/python", "bindings/python",
"bindings/wasm", "bindings/wasm",
"bindings/node", "bindings/node",
"examples/rust",
] ]
exclude = ["fuzz"] exclude = ["fuzz"]
+7 -8
View File
@@ -120,7 +120,7 @@ inherit it automatically.
| Python (PyO3) | `pip install wickra` | `examples/python/backtest.py` | | Python (PyO3) | `pip install wickra` | `examples/python/backtest.py` |
| Node.js (napi-rs) | `npm install wickra` | `bindings/node/examples/backtest.js` | | Node.js (napi-rs) | `npm install wickra` | `bindings/node/examples/backtest.js` |
| Browser / WASM | `npm install wickra-wasm` | `bindings/wasm/examples/index.html` | | Browser / WASM | `npm install wickra-wasm` | `bindings/wasm/examples/index.html` |
| Rust | `cargo add wickra` | `crates/wickra/examples/backtest.rs` | | Rust | `cargo add wickra` | `examples/rust/src/bin/backtest.rs` |
Each binding ships several runnable examples (streaming, backtest, live feed); Each binding ships several runnable examples (streaming, backtest, live feed);
[`examples/README.md`](examples/README.md) is the full cross-language index. [`examples/README.md`](examples/README.md) is the full cross-language index.
@@ -182,23 +182,22 @@ A Python live-trading example using the public `websockets` package lives at
wickra/ wickra/
├── crates/ ├── crates/
│ ├── wickra-core/ core engine + all 71 indicators │ ├── wickra-core/ core engine + all 71 indicators
│ ├── wickra/ top-level facade crate (publishes on crates.io) │ ├── wickra/ top-level facade crate (publishes on crates.io) + benches/
│ │ + benches/, examples/ (backtest, fetch_btcusdt)
│ │ and examples/data/ real BTCUSDT datasets
│ └── wickra-data/ CSV reader, tick aggregator, live exchange feeds │ └── wickra-data/ CSV reader, tick aggregator, live exchange feeds
│ + examples/live_binance.rs
├── bindings/ ├── bindings/
│ ├── python/ PyO3 + maturin (publishes on PyPI) │ ├── python/ PyO3 + maturin (publishes on PyPI)
│ ├── node/ napi-rs (publishes on npm) + examples/ │ ├── node/ napi-rs (publishes on npm) + examples/
│ └── wasm/ wasm-bindgen (browsers, bundlers, Node) + examples/ │ └── wasm/ wasm-bindgen (browsers, bundlers, Node) + examples/
├── examples/ examples/README.md indexes every language ├── examples/ examples/README.md indexes every language
│ ├── data/ real BTCUSDT OHLCV datasets, one per timeframe
│ ├── rust/ Rust workspace member (`wickra-examples`)
│ └── python/ backtest, live trading, parallel assets, multi-tf │ └── python/ backtest, live trading, parallel assets, multi-tf
└── .github/workflows/ CI and release pipelines └── .github/workflows/ CI and release pipelines
``` ```
Rust benchmarks and examples live inside their crate Rust benchmarks live in `crates/wickra/benches/`; runnable Rust examples live
(`crates/wickra/benches/`, `crates/<name>/examples/`); there is no in the workspace member crate at `examples/rust/`. There is no top-level
top-level `benches/` directory. `benches/` directory.
## Building everything from source ## Building everything from source
-6
View File
@@ -42,9 +42,3 @@ live-binance = ["dep:tokio", "dep:tokio-tungstenite", "dep:futures-util", "dep:u
[dev-dependencies] [dev-dependencies]
approx = { workspace = true } approx = { workspace = true }
tempfile = "3" tempfile = "3"
wickra = { path = "../wickra" }
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
[[example]]
name = "live_binance"
required-features = ["live-binance"]
-3
View File
@@ -32,9 +32,6 @@ approx = { workspace = true }
criterion = { workspace = true } criterion = { workspace = true }
proptest = { workspace = true } proptest = { workspace = true }
wickra-data = { path = "../wickra-data" } wickra-data = { path = "../wickra-data" }
# Only the `fetch_btcusdt` example parses Binance REST JSON; a dev-dependency
# never reaches a downstream consumer's dependency tree.
serde_json = "1"
[[bench]] [[bench]]
name = "indicators" name = "indicators"
+3 -3
View File
@@ -150,10 +150,10 @@ dropped connection, skips non-kline frames (subscription acks, heartbeats),
applies a read timeout and message-size limits, and tracks a closed flag so a applies a read timeout and message-size limits, and tracks a closed flag so a
deliberately closed stream is not reused. deliberately closed stream is not reused.
A runnable example lives at `crates/wickra-data/examples/live_binance.rs`: A runnable example lives at `examples/rust/src/bin/live_binance.rs`:
```bash ```bash
cargo run -p wickra-data --example live_binance --features live-binance cargo run -p wickra-examples --bin live_binance
``` ```
## Example datasets ## Example datasets
@@ -183,7 +183,7 @@ Binance REST API and needs the system `curl` (shipped with Windows 10+, macOS
and Linux): and Linux):
```bash ```bash
cargo run -p wickra --example fetch_btcusdt cargo run -p wickra-examples --bin fetch_btcusdt
``` ```
## See also ## See also
+5 -5
View File
@@ -119,17 +119,17 @@ exact contract.
## A deeper example ## A deeper example
`crates/wickra/examples/backtest.rs` shipped with the workspace computes a `examples/rust/src/bin/backtest.rs` (in the `wickra-examples` workspace
panel of indicators (RSI, EMA, Bollinger, MACD, ATR, ADX, OBV) over an OHLCV crate) computes a panel of indicators (RSI, EMA, Bollinger, MACD, ATR, ADX,
CSV by way of `wickra-data`: OBV) over an OHLCV CSV by way of `wickra-data`:
```bash ```bash
cargo run --release --example backtest -- path/to/ohlcv.csv cargo run --release -p wickra-examples --bin backtest -- path/to/ohlcv.csv
``` ```
For live-data work, `wickra-data` ships a streaming CSV reader, a For live-data work, `wickra-data` ships a streaming CSV reader, a
tick-to-candle aggregator, a candle resampler, and a Binance kline WebSocket tick-to-candle aggregator, a candle resampler, and a Binance kline WebSocket
adapter under the `live-binance` feature. `crates/wickra-data/examples/live_binance.rs` adapter under the `live-binance` feature. `examples/rust/src/bin/live_binance.rs`
is the canonical example for the latter. is the canonical example for the latter.
## See also ## See also
+7 -5
View File
@@ -5,13 +5,15 @@ to the code they exercise so the language tooling (`cargo run --example`,
`node`) can find them; the Python examples have no crate of their own and `node`) can find them; the Python examples have no crate of their own and
live here under [`python/`](python/). live here under [`python/`](python/).
## Rust — `crates/*/examples/` ## Rust — `examples/rust/`
The Rust examples live in the `wickra-examples` workspace member crate.
| Example | What it does | Run | | Example | What it does | Run |
| --- | --- | --- | | --- | --- | --- |
| `backtest.rs` | Compute a basket of indicators over an OHLCV CSV and print a summary. | `cargo run -p wickra --example backtest -- <ohlcv.csv>` | | `backtest.rs` | Compute a basket of indicators over an OHLCV CSV and print a summary. | `cargo run -p wickra-examples --bin backtest -- <ohlcv.csv>` |
| `fetch_btcusdt.rs` | Download real BTCUSDT klines from the Binance REST API into `examples/data/`. | `cargo run -p wickra --example fetch_btcusdt` | | `fetch_btcusdt.rs` | Download real BTCUSDT klines from the Binance REST API into `examples/data/`. | `cargo run -p wickra-examples --bin fetch_btcusdt` |
| `live_binance.rs` | Stream live Binance klines through an indicator over a resilient WebSocket. | `cargo run -p wickra-data --example live_binance --features live-binance` | | `live_binance.rs` | Stream live Binance klines through an indicator over a resilient WebSocket. | `cargo run -p wickra-examples --bin live_binance` |
## Python — `examples/python/` ## Python — `examples/python/`
@@ -46,4 +48,4 @@ Build the native module first: `cd bindings/node && npm install && npx napi buil
per timeframe (1m, 5m, 15m, 1h, 12h, 1d, 1month), in the standard per timeframe (1m, 5m, 15m, 1h, 12h, 1d, 1month), in the standard
`timestamp,open,high,low,close,volume` layout. The Rust and Node backtest `timestamp,open,high,low,close,volume` layout. The Rust and Node backtest
examples and the indicator benchmarks run against them. Regenerate them with examples and the indicator benchmarks run against them. Regenerate them with
the latest market history via `cargo run -p wickra --example fetch_btcusdt`. the latest market history via `cargo run -p wickra-examples --bin fetch_btcusdt`.
+28
View File
@@ -0,0 +1,28 @@
[package]
name = "wickra-examples"
version = "0.0.0"
publish = false
description = "Runnable Rust examples for the Wickra technical-analysis library."
authors.workspace = true
edition.workspace = true
rust-version.workspace = true
license.workspace = true
repository.workspace = true
homepage.workspace = true
readme = "README.md"
[lints]
workspace = true
[dependencies]
# All examples sit on top of the indicator engine.
wickra = { path = "../../crates/wickra" }
# The data layer is needed by every example except streaming/parallel: CSV
# reading, the Binance live feed and the resampler all live here. The
# `live-binance` feature is always on for this crate so the live_binance
# binary just compiles.
wickra-data = { path = "../../crates/wickra-data", features = ["live-binance"] }
# fetch_btcusdt parses the Binance REST kline response.
serde_json = "1"
# live_binance uses #[tokio::main]; the current-thread runtime is enough.
tokio = { version = "1", features = ["rt", "macros"] }
@@ -2,7 +2,7 @@
//! //!
//! Build with: //! Build with:
//! ```text //! ```text
//! cargo run --release --example backtest -- path/to/ohlcv.csv //! cargo run --release -p wickra-examples --bin backtest -- path/to/ohlcv.csv
//! ``` //! ```
use std::env; use std::env;
@@ -1,13 +1,13 @@
//! Rust example: download real BTCUSDT spot candles from the Binance REST API //! Rust example: download real BTCUSDT spot candles from the Binance REST API
//! and write them as CSV datasets under `examples/data/`. //! and write them as CSV datasets under `examples/data/`.
//! //!
//! These are the datasets the indicator benchmarks (`benches/indicators.rs`) //! These are the datasets the indicator benchmarks (`crates/wickra/benches/
//! and the `example_data` integration test run against. They live at the //! indicators.rs`) and the `example_data` integration test run against. They
//! workspace `examples/data/` directory. Re-run this example to refresh //! live at the workspace `examples/data/` directory. Re-run this example to
//! them with the latest market history: //! refresh them with the latest market history:
//! //!
//! ```text //! ```text
//! cargo run -p wickra --example fetch_btcusdt //! cargo run -p wickra-examples --bin fetch_btcusdt
//! ``` //! ```
//! //!
//! HTTPS is handled by shelling out to the system `curl` — shipped with //! HTTPS is handled by shelling out to the system `curl` — shipped with
@@ -98,8 +98,6 @@ fn main() -> Result<(), Box<dyn Error>> {
let data_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")) let data_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("..") .join("..")
.join("..")
.join("examples")
.join("data"); .join("data");
std::fs::create_dir_all(&data_dir)?; std::fs::create_dir_all(&data_dir)?;
@@ -2,7 +2,7 @@
//! //!
//! Build with: //! Build with:
//! ```text //! ```text
//! cargo run --release --example live_binance --features wickra-data/live-binance -- BTCUSDT //! cargo run --release -p wickra-examples --bin live_binance -- BTCUSDT
//! ``` //! ```
//! //!
//! The example prints a line per bar close. Hit Ctrl+C to stop. //! The example prints a line per bar close. Hit Ctrl+C to stop.