Inverse Fisher Transform RSI (IFT-RSI)

Parameters: rsi_period = 5 | wma_period = 9

Overview

The Inverse Fisher Transform RSI amplifies momentum signals by applying a hyperbolic tangent transformation to smoothed RSI values, creating an oscillator that snaps decisively to extremes rather than lingering in neutral zones like traditional momentum indicators. First calculating RSI with Wilder's smoothing, then applying weighted moving average smoothing, the indicator finally transforms these values through the inverse Fisher function to produce sharp, binary signals bounded between -1 and +1. When IFT-RSI approaches +1, it signals powerful bullish momentum that often coincides with breakout acceleration, while readings near -1 indicate intense selling pressure typically found at capitulation lows. The transformation compresses middle values while expanding extremes, eliminating the ambiguous 40 to 60 RSI range where traditional momentum indicators provide unclear signals, instead forcing clear overbought or oversold readings. Traders appreciate IFT-RSI for its ability to identify momentum exhaustion points with precision, as the indicator tends to flatline at extremes just before reversals, providing earlier exit signals than gradual RSI divergences. Additionally, the double smoothing process filters out minor fluctuations while the Fisher transformation ensures rapid response to genuine momentum shifts, creating cleaner signals for both mean reversion and trend continuation strategies.

Implementation Examples

Get started with IFT‑RSI in just a few lines:

use vectorta::indicators::ift_rsi::{ift_rsi, IftRsiInput, IftRsiParams};
use vectorta::utilities::data_loader::{Candles, read_candles_from_csv};

// Using with price data slice
let prices = vec![100.0, 102.0, 101.5, 103.0, 105.0, 104.5];
let params = IftRsiParams {
    rsi_period: Some(5),
    wma_period: Some(9),
};
let input = IftRsiInput::from_slice(&prices, params);
let result = ift_rsi(&input)?;

// Using with Candles data structure
// Quick and simple with default parameters (rsi=5, wma=9; source="close")
let candles: Candles = read_candles_from_csv("data/sample.csv")?;
let input = IftRsiInput::with_default_candles(&candles);
let result = ift_rsi(&input)?;

// Access the IFT-RSI values
for value in result.values {
    println!("IFT-RSI: {}", value);
}

API Reference

Input Methods
// From price slice
IftRsiInput::from_slice(&[f64], IftRsiParams) -> IftRsiInput

// From candles with custom source
IftRsiInput::from_candles(&Candles, &str, IftRsiParams) -> IftRsiInput

// From candles with default params (close prices, rsi=5, wma=9)
IftRsiInput::with_default_candles(&Candles) -> IftRsiInput
Parameters Structure
pub struct IftRsiParams {
    pub rsi_period: Option<usize>, // Default: 5
    pub wma_period: Option<usize>, // Default: 9
}
Output Structure
pub struct IftRsiOutput {
    pub values: Vec<f64>, // IFT-RSI values in [-1, 1]
}
Validation, Warmup & NaNs
  • rsi_period > 0, wma_period > 0, and each must be <= len; otherwise IftRsiError::InvalidPeriod.
  • Requires at least max(rsi_period, wma_period) valid points after first finite; else IftRsiError::NotEnoughValidData.
  • Warmup prefix length: first_non_nan + rsi_period + wma_period − 1; indices before are NaN.
  • Streaming: returns None until RSI seed and WMA window are ready; then returns tanh(WMA(0.1·(RSI−50))) per update.
  • Leading NaNs delay the first value; subsequent NaNs in inputs are handled by computing from the first finite segment.
Error Handling
use vectorta::indicators::ift_rsi::{ift_rsi, IftRsiError};

match ift_rsi(&input) {
    Ok(output) => process_results(output.values),
    Err(IftRsiError::EmptyData) => eprintln!("empty input"),
    Err(IftRsiError::AllValuesNaN) => eprintln!("all values are NaN"),
    Err(IftRsiError::InvalidPeriod { rsi_period, wma_period, data_len }) => {
        eprintln!("invalid periods: rsi={}, wma={}, len={}", rsi_period, wma_period, data_len)
    }
    Err(IftRsiError::NotEnoughValidData { needed, valid }) => {
        eprintln!("need {} valid points, only {}", needed, valid)
    }
    Err(IftRsiError::RsiCalculationError(e)) => eprintln!("RSI error: {}", e),
    Err(IftRsiError::WmaCalculationError(e)) => eprintln!("WMA error: {}", e),
    Err(IftRsiError::LengthMismatch { dst_len, data_len }) => {
        eprintln!("dst_len={} != data_len={}", dst_len, data_len)
    }
    Err(IftRsiError::WrongKernelForBatch) => eprintln!("use a batch kernel for batch ops"),
}

Python Bindings

Basic Usage

Calculate IFT‑RSI using NumPy arrays (required args: rsi_period, wma_period):

import numpy as np
from vectorta import ift_rsi

# Prepare price data as NumPy array
prices = np.array([100.0, 102.0, 101.5, 103.0, 105.0, 104.5])

# Calculate IFT-RSI with typical Ehlers defaults (5/9)
result = ift_rsi(prices, rsi_period=5, wma_period=9)

# Specify kernel for performance optimization
result = ift_rsi(prices, rsi_period=5, wma_period=9, kernel="avx2")

print(f"IFT-RSI values: {result}")
Streaming Real-time Updates

Process real-time price updates efficiently:

from vectorta import IftRsiStream

# Initialize streaming IFT-RSI calculator
stream = IftRsiStream(rsi_period=5, wma_period=9)

# Process real-time price updates
for price in price_feed:
    value = stream.update(price)
    if value is not None:
        print(f"Current IFT-RSI: {value}")
Batch Parameter Optimization

Test multiple parameter combinations:

import numpy as np
from vectorta import ift_rsi_batch

prices = np.array([...])

# Define parameter ranges: (start, end, step)
rsi_range = (3, 14, 1)
wma_range = (5, 21, 2)

results = ift_rsi_batch(
    prices,
    rsi_period_range=rsi_range,
    wma_period_range=wma_range,
    kernel="auto"
)

print(results["values"].shape)  # (rows, len(prices))
print(results["rsi_periods"], results["wma_periods"])
CUDA Acceleration

CUDA support for IFT‑RSI is currently under development. The API will follow the same pattern as other CUDA‑enabled indicators.

# Coming soon: CUDA-accelerated IFT-RSI calculations
# Pattern will mirror other CUDA-enabled indicators in vectorta
# (batch parameter sweeps and many-series kernels).

JavaScript/WASM Bindings

Basic Usage

Calculate IFT‑RSI in JavaScript/TypeScript:

import { ift_rsi_js } from 'vectorta-wasm';

// Price data as Float64Array or regular array
const prices = new Float64Array([100.0, 102.0, 101.5, 103.0, 105.0, 104.5]);

// Calculate IFT-RSI with specified parameters
const result = ift_rsi_js(prices, 5, 9);  // rsi=5, wma=9

console.log('IFT-RSI values:', result);
Memory-Efficient Operations

Use zero-copy operations for large datasets:

import { ift_rsi_alloc, ift_rsi_free, ift_rsi_into, memory } from 'vectorta-wasm';

const prices = new Float64Array([/* your data */]);
const length = prices.length;

// Allocate WASM memory for input and output
const inPtr = ift_rsi_alloc(length);
const outPtr = ift_rsi_alloc(length);

// Copy input data into WASM memory
new Float64Array(memory.buffer, inPtr, length).set(prices);

// Calculate directly into allocated memory
// Args: in_ptr, out_ptr, len, rsi_period, wma_period
ift_rsi_into(inPtr, outPtr, length, 5, 9);

// Read results (slice() to copy out)
const iftValues = new Float64Array(memory.buffer, outPtr, length).slice();

// Free allocated memory when done
ift_rsi_free(inPtr, length);
ift_rsi_free(outPtr, length);

console.log('IFT-RSI values:', iftValues);
Batch Processing

Test multiple parameter combinations efficiently:

import { ift_rsi_batch } from 'vectorta-wasm';

const prices = new Float64Array([/* historical prices */]);

// Define parameter sweep ranges as [start, end, step]
const config = {
  rsi_period_range: [3, 14, 1],
  wma_period_range: [5, 21, 2],
};

// Calculate all combinations; returns an object
const out = ift_rsi_batch(prices, config);

// out: { values: Float64Array, combos: Array<{rsi_period?: number, wma_period?: number}>, rows, cols }
console.log('rows x cols:', out.rows, 'x', out.cols);
console.log('combos:', out.combos);

// Reshape flat values per row as needed
const matrix = [];
for (let r = 0; r < out.rows; r++) {
  const start = r * out.cols;
  matrix.push(out.values.slice(start, start + out.cols));
}

// Access a particular combination's series
const firstComboValues = matrix[0];

Performance Analysis

Comparison:
View:
Loading chart...

AMD Ryzen 9 9950X (CPU) | NVIDIA RTX 4090 (GPU) | Benchmarks: 2026-01-05

Related Indicators