Relative Strength Index (RSI)
period = 14 Overview
The Relative Strength Index (RSI) measures momentum by comparing the magnitude of recent gains to recent losses, oscillating between 0 and 100 to reveal whether bullish or bearish momentum dominates. J. Welles Wilder developed RSI in 1978 using a smoothed ratio of average gains to average losses over 14 periods, with his proprietary smoothing technique that weights recent data more heavily than simple averages. The calculation first separates positive and negative price changes, averages each using Wilder's smoothing method, then transforms the ratio into an oscillator bounded between 0 and 100. Readings above 70 traditionally signal overbought conditions where price has risen too far too fast, while values below 30 indicate oversold territory where selling pressure may have exhausted. Traders watch for divergences between RSI and price as early reversal warnings, such as price making new highs while RSI fails to exceed its previous peak. The 50 level acts as a momentum threshold, with sustained readings above confirming bullish bias and values below suggesting bearish control of the market.
Defaults: period = 14.
Implementation Examples
Get started with RSI in just a few lines:
use vectorta::indicators::rsi::{rsi, RsiInput, RsiParams};
use vectorta::utilities::data_loader::{Candles, read_candles_from_csv};
// Using with a price slice
let prices = vec![100.0, 102.0, 101.0, 103.0, 104.5, 104.0];
let params = RsiParams { period: Some(14) }; // default is 14
let input = RsiInput::from_slice(&prices, params);
let result = rsi(&input)?;
// Using with Candles (defaults: period=14, source="close")
let candles: Candles = read_candles_from_csv("data/sample.csv")?;
let input = RsiInput::with_default_candles(&candles);
let result = rsi(&input)?;
// Access RSI values
for value in result.values {
println!("RSI: {}", value);
} API Reference
Input Methods ▼
// From price slice
RsiInput::from_slice(&[f64], RsiParams) -> RsiInput
// From candles with custom source
RsiInput::from_candles(&Candles, &str, RsiParams) -> RsiInput
// From candles with default params (close, period=14)
RsiInput::with_default_candles(&Candles) -> RsiInput Parameters Structure ▼
pub struct RsiParams {
pub period: Option<usize>, // Default: 14
} Output Structure ▼
pub struct RsiOutput {
pub values: Vec<f64>, // RSI values (0..=100), warmup as NaN
} Validation, Warmup & NaNs ▼
period > 0andperiod ≤ len(data); otherwiseRsiError::InvalidPeriod.- If all inputs are
NaN, returnsRsiError::AllValuesNaN. - Must have at least
periodvalid values after the first finite input; elseRsiError::NotEnoughValidData. - Warmup: indices before
first + periodareNaN; the first non-NaN is atfirst + period. - If
AvgGain + AvgLoss == 0at any step, RSI is50.0. rsi_into_slicerequiresdst.len() == data.len(), otherwiseRsiError::LengthMismatch.- Batch requires a batch kernel; otherwise
RsiError::UnsupportedKernel.
Error Handling ▼
use vectorta::indicators::rsi::RsiError;
match rsi(&input) {
Ok(output) => process(output.values),
Err(RsiError::EmptyInputData) => println!("Input data is empty"),
Err(RsiError::AllValuesNaN) => println!("All input values are NaN"),
Err(RsiError::InvalidPeriod { period, data_len }) =>
println!("Invalid period {} for length {}", period, data_len),
Err(RsiError::NotEnoughValidData { needed, valid }) =>
println!("Need {} valid points, only {}", needed, valid),
Err(RsiError::LengthMismatch { dst, src }) =>
println!("Destination len {} != source len {}", dst, src),
Err(RsiError::UnsupportedKernel) => println!("Unsupported kernel for batch operation"),
} Python Bindings
Basic Usage ▼
Calculate RSI using NumPy arrays (default period=14):
import numpy as np
from vectorta import rsi
prices = np.array([100.0, 102.0, 101.0, 103.0, 104.5])
# Default period (14)
values = rsi(prices, period=14)
# Select kernel ("auto", "scalar", "avx2", "avx512") if available on your platform
values = rsi(prices, period=14, kernel="auto")
print(values) Streaming Real-time Updates ▼
from vectorta import RsiStream
stream = RsiStream(period=14)
for price in price_feed:
rsi_value = stream.update(price)
if rsi_value is not None:
print("RSI:", rsi_value) Batch Parameter Optimization ▼
Test multiple period values efficiently:
import numpy as np
from vectorta import rsi_batch
prices = np.array([...], dtype=float)
# Define (start, end, step)
period_range = (5, 30, 5) # 5, 10, 15, 20, 25, 30
results = rsi_batch(prices, period_range, kernel="auto")
print(results["values"].shape) # (num_periods, len(prices))
print(results["periods"]) # array of tested periods CUDA Acceleration ▼
CUDA support for RSI is currently under development. The API will follow the same pattern as other CUDA-enabled indicators.
# Coming soon: CUDA-accelerated RSI batch operations
# Patterns will mirror other CUDA-enabled indicators in this project. JavaScript/WASM Bindings
Basic Usage ▼
Calculate RSI with the WASM module:
import { rsi_js } from 'vectorta-wasm';
const prices = new Float64Array([100.0, 102.0, 101.0, 103.0]);
const values = rsi_js(prices, 14); // period=14
console.log('RSI:', values); Memory-Efficient Operations ▼
Use zero-copy operations for large datasets:
import { rsi_alloc, rsi_free, rsi_into, memory } from 'vectorta-wasm';
const prices = new Float64Array([/* your data */]);
const len = prices.length;
const inPtr = rsi_alloc(len);
const outPtr = rsi_alloc(len);
new Float64Array(memory.buffer, inPtr, len).set(prices);
// Args: in_ptr, out_ptr, len, period
rsi_into(inPtr, outPtr, len, 14);
const out = new Float64Array(memory.buffer, outPtr, len).slice();
rsi_free(inPtr, len);
rsi_free(outPtr, len);
console.log('RSI:', out); Batch Processing ▼
Test multiple period values with a single call:
import { rsi_batch } from 'vectorta-wasm';
const prices = new Float64Array([/* historical prices */]);
// config = { period_range: [start, end, step] }
const config = { period_range: [5, 30, 5] };
const res = rsi_batch(prices, config);
// res = { values: Float64Array, combos: RsiParams[], rows, cols }
// values are flattened row-major: rows=num_combos, cols=prices.length
console.log(res.rows, res.cols, res.combos); Performance Analysis
Across sizes, Rust CPU runs about 2.98× faster than Tulip C in this benchmark.
AMD Ryzen 9 9950X (CPU) | NVIDIA RTX 4090 (GPU) | Benchmarks: 2026-01-05