Kurtosis (Excess Kurtosis)
period = 5 Overview
Kurtosis measures the presence of extreme price movements and outliers by quantifying how peaked or flat the distribution of returns appears compared to a normal distribution, revealing when markets shift between calm and crisis modes. Positive excess kurtosis indicates fat tails with more extreme moves than expected from normal distributions, signaling increased risk of sudden price spikes or crashes that standard deviation alone cannot capture. When kurtosis rises sharply, it warns traders that the market has entered a regime where extreme events become more likely, requiring wider stops and reduced position sizes to account for tail risk. Negative kurtosis reveals platykurtic distributions where prices cluster tightly around the mean with fewer outliers, indicating stable conditions favorable for mean reversion strategies and tighter risk management. Options traders particularly monitor kurtosis because it directly impacts pricing models, as high kurtosis environments require adjustments to implied volatility smiles to accurately price tail risk protection. The indicator provides crucial intelligence about market regime changes, as shifts from low to high kurtosis often precede volatility expansions, while transitions from high to low kurtosis suggest markets returning to equilibrium after crisis periods.
Implementation Examples
Compute excess kurtosis from slices or candles:
use vectorta::indicators::kurtosis::{kurtosis, KurtosisInput, KurtosisParams};
use vectorta::utilities::data_loader::{Candles, read_candles_from_csv};
// From a numeric slice
let prices = vec![100.0, 101.0, 102.0, 99.0, 104.0, 98.0];
let params = KurtosisParams { period: Some(5) }; // Default is 5
let input = KurtosisInput::from_slice(&prices, params);
let out = kurtosis(&input)?;
// From Candles with default source and params (source = "hl2", period=5)
let candles: Candles = read_candles_from_csv("data/sample.csv")?;
let input = KurtosisInput::with_default_candles(&candles);
let out = kurtosis(&input)?;
// Access values
for v in out.values { println!("kurtosis: {}", v); } API Reference
Input Methods ▼
// From price slice
KurtosisInput::from_slice(&[f64], KurtosisParams) -> KurtosisInput
// From candles with custom source
KurtosisInput::from_candles(&Candles, &str, KurtosisParams) -> KurtosisInput
// From candles with default params (source="hl2", period=5)
KurtosisInput::with_default_candles(&Candles) -> KurtosisInput Parameters Structure ▼
#[derive(Debug, Clone)]
pub struct KurtosisParams {
pub period: Option<usize>, // Default: 5
} Output Structure ▼
#[derive(Debug, Clone)]
pub struct KurtosisOutput {
pub values: Vec<f64>, // Excess kurtosis values (m4/m2^2 - 3)
} Validation, Warmup & NaNs ▼
period > 0andperiod ≤ data.len(); otherwiseKurtosisError::InvalidPeriod.- Requires at least
periodvalid points after the first finite value; otherwiseKurtosisError::NotEnoughValidData. - Indices before
first_valid + period − 1areNaN(warmup prefix). - If any input inside a window is
NaN, that window’s output isNaN. - If the second central moment
m2is ~0 (no variance), the output isNaN. - Streaming: returns
Noneuntil the firstperiodvalues are buffered; then emits one value per update.
Error Handling ▼
use vectorta::indicators::kurtosis::{kurtosis, KurtosisError, KurtosisInput, KurtosisParams};
let input = KurtosisInput::from_slice(&prices, KurtosisParams { period: Some(5) });
match kurtosis(&input) {
Ok(output) => process(output.values),
Err(KurtosisError::EmptyInputData) => eprintln!("Empty input slice"),
Err(KurtosisError::AllValuesNaN) => eprintln!("All input values are NaN"),
Err(KurtosisError::InvalidPeriod { period, data_len }) =>
eprintln!("Invalid period {} for length {}", period, data_len),
Err(KurtosisError::NotEnoughValidData { needed, valid }) =>
eprintln!("Need {} valid points, only {} available", needed, valid),
Err(KurtosisError::ZeroOrMissingPeriod) =>
eprintln!("Zero or missing period"),
} Python Bindings
Basic Usage ▼
Calculate excess kurtosis using NumPy arrays:
import numpy as np
from vectorta import kurtosis
prices = np.array([100.0, 101.0, 102.0, 99.0, 104.0, 98.0], dtype=np.float64)
# period required; optional kernel: "auto", "scalar", "avx2", "avx512" (if available)
values = kurtosis(prices, period=5, kernel="auto")
print(values) Streaming ▼
from vectorta import KurtosisStream
stream = KurtosisStream(period=5)
for price in price_feed:
value = stream.update(price)
if value is not None:
print("kurtosis:", value) Batch Parameter Optimization ▼
Evaluate a sweep of period values:
import numpy as np
from vectorta import kurtosis_batch
prices = np.array([...], dtype=np.float64)
# (start, end, step)
res = kurtosis_batch(prices, period_range=(5, 20, 5), kernel="auto")
# Result dict contains a 2D array and tested periods
values_2d = res["values"] # shape: [rows, len(prices)]
periods = res["periods"] # tested period values
print(periods, values_2d.shape) CUDA Acceleration ▼
CUDA support for Kurtosis is currently under development. The API will follow the same pattern as other CUDA-enabled indicators.
# Coming soon: CUDA-accelerated kurtosis calculations
# from vectorta import kurtosis_cuda_batch, kurtosis_cuda_many_series_one_param
# import numpy as np
#
# # Parameter sweep on a single series
# res = kurtosis_cuda_batch(data=prices, period_range=(5, 20, 1), device_id=0)
# # Many series, one parameter set
# out = kurtosis_cuda_many_series_one_param(data_tm=portfolio_tm, period=5, device_id=0) JavaScript/WASM Bindings
Basic Usage ▼
Calculate Kurtosis in JavaScript/TypeScript:
import { kurtosis_js } from 'vectorta-wasm';
const prices = new Float64Array([100.0, 101.0, 102.0, 99.0, 104.0, 98.0]);
const values = kurtosis_js(prices, 5);
console.log('kurtosis:', values); Memory-Efficient Operations ▼
Use zero-copy operations for large datasets:
import { kurtosis_alloc, kurtosis_free, kurtosis_into, memory } from 'vectorta-wasm';
const prices = new Float64Array([/* your data */]);
const n = prices.length;
const inPtr = kurtosis_alloc(n);
const outPtr = kurtosis_alloc(n);
new Float64Array(memory.buffer, inPtr, n).set(prices);
// Args: in_ptr, out_ptr, len, period
kurtosis_into(inPtr, outPtr, n, 5);
const out = new Float64Array(memory.buffer, outPtr, n).slice();
kurtosis_free(inPtr, n);
kurtosis_free(outPtr, n);
console.log('kurtosis:', out); Batch Processing ▼
Unified batch API returns values and combos:
import { kurtosis_batch } from 'vectorta-wasm';
const prices = new Float64Array([/* historical prices */]);
const cfg = { period_range: [5, 20, 5] as [number, number, number] };
const result = kurtosis_batch(prices, cfg);
// result: { values: Float64Array, combos: { period: number | null }[], periods: number[], rows: number, cols: number }
const { values, combos, periods, rows, cols } = result;
console.log('rows x cols =', rows, 'x', cols);
console.log('periods tested:', periods); Performance Analysis
AMD Ryzen 9 9950X (CPU) | NVIDIA RTX 4090 (GPU) | Benchmarks: 2026-01-05
Related Indicators
High-Low Correlation
Technical analysis indicator
Deviation
Technical analysis indicator
Linear Regression Angle
Technical analysis indicator
Linear Regression Intercept
Technical analysis indicator
Linear Regression Slope
Technical analysis indicator
Mean Absolute Deviation
Technical analysis indicator