# Centaur Technical Indicators
[](https://crates.io/crates/centaur_technical_indicators)
[](https://docs.rs/centaur_technical_indicators/)
[](https://github.com/ChironMind/CentaurTechnicalIndicators-Rust/actions)
[](LICENSE-MIT)
[](https://crates.io/crates/centaur_technical_indicators)
[](https://github.com/ChironMind/CentaurTechnicalIndicators-Rust-tutorials)
[](https://github.com/ChironMind/CentaurTechnicalIndicators-Rust-benchmarks)
A highly configurable and high-performance technical indicators library written in pure Rust.
Designed for flexibility, speed, and advanced use cases in quantitative and algorithmic trading.
Part of the Centaur Research and Technologies ecosystem — visit [https://centaurresearchtechnologies.com/](https://centaurresearchtechnologies.com/) for more.
Looking for the Python bindings? See: [CentaurTechnicalIndicators-Python](https://github.com/chironmind/CentaurTechnicalIndicators-Python)
Looking for the WASM bindings? See: [CentaurTechnicalIndicators-JS](https://github.com/chironmind/CentaurTechnicalIndicators-JS)
---
## 🚀 Getting Started (Tutorial)
> The fastest way to get up and running with Centaur Technical Indicators.
**1. Add Centaur Technical Indicators to your project:**
```shell
cargo add centaur_technical_indicators
```
Or, manually in your `Cargo.toml`:
```toml
centaur_technical_indicators = "1.3.0"
```
**2. Calculate your first indicator:**
```rust
use centaur_technical_indicators::{moving_average, MovingAverageType};
let prices = vec![100.2, 100.46, 100.53, 100.38, 100.19];
let ma = moving_average::single::moving_average(&prices, MovingAverageType::Simple).unwrap();
println!("Simple Moving Average: {}", ma);
```
Expected output:
```
Simple Moving Average: 100.352
```
**3. Explore more tutorials**
- [Getting started tutorial](https://github.com/ChironMind/CentaurTechnicalIndicators-Rust-tutorials/blob/main/getting_started.md)
- [Choosing the right model](https://github.com/ChironMind/CentaurTechnicalIndicators-Rust-tutorials/blob/main/choose_right_model.md)
- [Building your first strategy](https://github.com/ChironMind/CentaurTechnicalIndicators-Rust-tutorials/blob/main/first_strategy.md)
- [Backtesting tutorial](https://github.com/ChironMind/CentaurTechnicalIndicators-Rust-tutorials/blob/main/backtest.md)
- [Visualization tutorial](https://github.com/ChironMind/CentaurTechnicalIndicators-Rust-tutorials/blob/main/visualization.md)
---
## 🛠️ How-To Guides
> Task-oriented guides for common problems and advanced scenarios.
- [Load CSV Price Data:](https://github.com/ChironMind/CentaurTechnicalIndicators-Rust-how-to-guides/blob/main/load_csv.md) Parse OHLC prices from a file and calculate RSI
- [When to use a bulk vs single module:](https://github.com/ChironMind/CentaurTechnicalIndicators-Rust-how-to-guides/blob/main/bulk_vs_single.md) Understand when to use bulk functions or single functions
- [Choosing the right constant model type:](https://github.com/ChironMind/CentaurTechnicalIndicators-Rust-how-to-guides/blob/main/choose_constant_model_type.md) Programmatically determine the best `ConstantModelType`
- [Choosing the right deviation model:](https://github.com/ChironMind/CentaurTechnicalIndicators-Rust-how-to-guides/blob/main/choose_deviation_model.md) Programmatically determine the best deviation model
- [Choosing the right period:](https://github.com/ChironMind/CentaurTechnicalIndicators-Rust-how-to-guides/blob/main/choose_period.md) Programmatically determine the best period
- [How to use the Personalised Moving Average:](https://github.com/ChironMind/CentaurTechnicalIndicators-Rust-how-to-guides/blob/main/personliased_moving_average.md) Programmatically determine the alpha of the moving average
- [How to use the McGinley dynamic variation of functions:](https://github.com/ChironMind/CentaurTechnicalIndicators-Rust-how-to-guides/blob/main/mcginley_dynamic.md) Quick guide on how to use the McGinley Dynamic functions
*(Contributions welcome! Submit your favorite how-to guide as a PR.)*
---
## 📚 Reference
> For complete API details, see [docs.rs/centaur_technical_indicators](https://docs.rs/centaur_technical_indicators/).
### Example
A reference of how to call each function can be found
- [Reference Example](https://github.com/ChironMind/CentaurTechnicalIndicators-Rust/blob/main/examples/reference.rs)
Clone and run:
```shell
cargo build
cargo run --example reference
```
### Library Structure
- Modules based on their analysis areas (**`moving_average`**, **`momentum_indicators`**, **`strength_indicators`**...)
- **`bulk` & `single` submodules**
- `bulk`: Compute indicator over rolling periods, returns a vector.
- `single`: Compute indicator for the entire vector, returns a single value.
- Types used to personalise the technical indicators (**`MovingAverageType`**, **`DeviationModel`**, **`Position`**...)
---
## 🧠 Explanation & Design
### Why Centaur Technical Indicators?
- **Performance:** Pure Rust implementation for maximal speed, safety, and zero dependencies.
- **Configurability:** Most indicators are highly customizable—tweak calculation methods, periods, or even use medians instead of means.
- **Breadth:** Covers a wide range of technical indicators out of the box.
- **Advanced Use:** Designed for users who understand technical analysis and want deep control.
**Note:** Some features may require background in technical analysis. See [Investopedia: Technical Analysis](https://www.investopedia.com/terms/t/technicalanalysis.asp) for a primer.
---
## 📈 Available Indicators
All indicators are grouped into modules based on their analysis area, matching the `src/` layout. Each module has `bulk` (vector output) and `single` (scalar output) submodules. Each indicator appears in exactly one category.
### Basic Indicators
- Absolute Deviation, Log, Mean, Median, Mode, Std. Deviation, Variance, Max/Min
### Candle Indicators
- Ichimoku Cloud, Moving Constant Bands (Bollinger and generalised forms), Moving Constant Envelopes, Donchian Channels, Keltner Channels, Supertrend
### Chart Trends
- Trend break-down, overall trends, peak/valley analysis
- `peak_favorable_move` / `valley_favorable_move` — maximum favorable excursion (MFE); forward-looking (reads future bars; not a real-time signal)
### Correlation Indicators
- Asset-pair correlation
### Momentum Indicators
- Chaikin Oscillator, CCI, MACD, Money Flow Index, On Balance Volume, ROC, RSI, Stochastic Oscillator, Williams %R, Chande Momentum Oscillator, Percentage Price Oscillator
### Moving Averages
- Simple, Smoothed, Exponential, Personalised, McGinley Dynamic
### Other Indicators
- ROI, True Range, ATR, Internal Bar Strength, Positivity Indicator
### Strength Indicators
- Accumulation/Distribution, PVI, NVI, RVI
### Trend Indicators
- Aroon (Up/Down/Oscillator/Indicator), Parabolic Time-Price System, Directional Movement, Volume-Price Trend, True Strength Index
### Volatility Indicators
- Ulcer Index
> Some convenience wrappers (`signal_line`, `slow_stochastic`, `slowest_stochastic`, `volatility_system`) are still in the public API but are `#[deprecated]` for removal in 2.0. See [`docs/2_0_PLAN.md`](docs/2_0_PLAN.md) for migration recipes. The momentum wrappers reduce to "apply a moving average to the underlying indicator's output"; `volatility_system` has no direct 2.0 replacement.
---
## 📊 Performance Benchmarks
Want to know how fast Centaur Technical Indicators runs in real-world scenarios?
We provide detailed, reproducible benchmarks using realistic OHLCV data and a variety of indicators.
### Momentum Indicators
| Function | Time per Operation |
|-----------------------------------------------|--------------------|
| `relative_strength_index` | 573.86 µs |
| `stochastic_oscillator` | 784.13 µs |
| `williams_percent_r` | 76.256 µs |
| `money_flow_index` | 150.69 µs |
| `rate_of_change` | 5.3984 µs |
| `on_balance_volume` | 17.405 µs |
| `commodity_channel_index` | 103.19 µs |
| `mcginley_dynamic_commodity_channel_index` | 66.044 µs |
| `macd_line` | 51.482 µs |
| `mcginley_dynamic_macd_line` | 44.461 µs |
| `chaikin_oscillator` | 258.33 µs |
| `percentage_price_oscillator` | 58.060 µs |
| `chande_momentum_oscillator` | 370.14 µs |
### Candle Indicators
| Function | Time per Operation |
|-----------------------------------------------|--------------------|
| `moving_constant_envelopes` | 37.572 µs |
| `mcginley_dynamic_envelopes` | 39.264 µs |
| `moving_constant_bands` | 119.70 µs |
| `mcginley_dynamic_bands` | 43.219 µs |
| `ichimoku_cloud` | 192.93 µs |
| `donchian_channels` | 28.481 µs |
| `keltner_channel` | 318.05 µs |
| `supertrend` | 148.80 µs |
### Trend Indicators
| Function | Time per Operation |
|-----------------------------------------------|--------------------|
| `aroon_up` | 16.531 µs |
| `aroon_down` | 16.592 µs |
| `aroon_indicator` | 66.468 µs |
| `parabolic_time_price_system` | 43.939 µs |
| `directional_movement_system` | 88.965 µs |
| `volume_price_trend` | 6.2801 µs |
| `true_strength_index` | 705.25 µs |
### Strength Indicators
| Function | Time per Operation |
|-----------------------------------------------|--------------------|
| `accumulation_distribution` | 8.2935 µs |
| `positive_volume_index` | 7.6977 µs |
| `negative_volume_index` | 7.6167 µs |
| `relative_vigor_index` | 505.34 µs |
### Other Indicators
| Function | Time per Operation |
|-----------------------------------------------|--------------------|
| `return_on_investment` | 40.962 µs |
| `true_range` | 3.4663 µs |
| `average_true_range` | 122.08 µs |
| `internal_bar_strength` | 5.3943 µs |
| `positivity_indicator` | 20.683 µs |
### Basic Indicators
| Function | Time per Operation |
|-----------------------------------------------|--------------------|
| `mean` | 5.7432 µs |
| `median` | 333.68 µs |
| `mode` | 931.09 µs |
| `log` | 20.335 µs |
| `log_difference` | 42.223 µs |
| `variance` | 20.921 µs |
| `standard_deviation` | 24.095 µs |
| `absolute_deviation(Mean)` | 26.991 µs |
| `absolute_deviation(Median)` | 345.14 µs |
| `absolute_deviation(Mode)` | 956.83 µs |
### Chart Trends
| Function | Time per Operation |
|-----------------------------------------------|--------------------|
| `peaks` | 93.094 µs |
| `valleys` | 92.119 µs |
| `peak_trend` | 188.14 µs |
| `valley_trend` | 188.81 µs |
| `overall_trend` | 10.337 µs |
| `break_down_trends` | 14.655 ms |
### Correlation Indicators
| Function | Time per Operation |
|-----------------------------------------------|--------------------|
| `correlate_asset_prices` | 231.14 µs |
### Moving Average
| Function | Time per Operation |
|-----------------------------------------------|--------------------|
| `moving_average(Simple)` | 17.575 µs |
| `moving_average(Smoothed)` | 76.601 µs |
| `moving_average(Exponential)` | 78.505 µs |
| `mcginley_dynamic` | 39.653 µs |
### Volatility Indicators
| Function | Time per Operation |
|-----------------------------------------------|--------------------|
| `ulcer_index` | 65.959 µs |
*These results are from a Raspberry Pi 5 8GB, your machine will likely be faster!*
👉 [See all benchmarks and how to run your own](https://github.com/ChironMind/CentaurTechnicalIndicators-Rust-benchmarks)
---
## 🤝 Contributing
Contributions, bug reports, and feature requests are welcome!
- [Open an issue](https://github.com/ChironMind/CentaurTechnicalIndicators-Rust/issues)
- [Submit a pull request](https://github.com/ChironMind/CentaurTechnicalIndicators-Rust/pulls)
- See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines
### Local quality gates
Before opening a PR, run the same quality gates used in CI:
```bash
cargo fmt --all -- --check
cargo clippy --all-targets -- -D warnings
cargo test
cargo doc --no-deps
```
---
## 💬 Community & Support
- Start a [discussion](https://github.com/ChironMind/CentaurTechnicalIndicators-Rust/discussions)
- File [issues](https://github.com/ChironMind/CentaurTechnicalIndicators-Rust/issues)
- Add your project to the [Showcase](https://github.com/ChironMind/CentaurTechnicalIndicators-Rust/discussions/categories/show-and-tell)
---
## 🔀 Migrating from RustTI
Centaur Technical Indicators is the continuation of `RustTI` under a new name. The primary migration step is renaming imports and dependency entries from `rust_ti` to `centaur_technical_indicators`. **However, `1.0.0` (the rebrand release) also contained breaking API changes** — most notably the conversion of `panic!` paths to `Result<T, TechnicalIndicatorError>` returns and several signature reshapes. If you are upgrading from a pre-1.0 RustTI release, review the `## [1.0.0]` section of `CHANGELOG.md` for the full list before relying on the rename alone. See [`docs/CHANGELOG_RUSTTI_LEGACY.md`](docs/CHANGELOG_RUSTTI_LEGACY.md) for the pre-rebrand release history.
---
## 📰 Release Notes
**Latest (v1.3.0):**
- Added maximum favorable excursion (MFE) primitives: `chart_trends::peak_favorable_move` and `valley_favorable_move`
- Fixed `chart_trends::peaks` / `valleys` correctness bugs (spurious or dropped extrema around index 0 and after monotonic runs)
- Hardened library functions against all-NaN input that previously panicked
- Implemented `Display` on all public types; added per-category examples; declared MSRV 1.81
[Human friendly changelog →](https://github.com/ChironMind/CentaurTechnicalIndicators-Rust/blob/main/CHANGELOG.md)
[Full changelog →](https://github.com/ChironMind/CentaurTechnicalIndicators-Rust/releases)
---
## 📄 License
MIT License. See [LICENSE](LICENSE-MIT).