Fibonacci Weighted Moving Average (FWMA)

Parameters: period = 5

Overview

The Fibonacci Weighted Moving Average applies nature's golden ratio sequence as weights to create a unique smoothing that naturally emphasizes recent price action while maintaining mathematical harmony across the lookback window. Each price point receives a weight based on Fibonacci numbers (1, 1, 2, 3, 5, 8...), with the most recent data assigned the highest Fibonacci value, creating an organic progression that many traders believe aligns with natural market cycles. After multiplying prices by their Fibonacci weights, the sum gets normalized to produce an average that responds faster to new developments than simple averages yet smoother than aggressive exponential weighting. Traders find FWMA particularly effective during trending markets where the Fibonacci weighting captures momentum shifts earlier while the normalized calculation prevents overshooting during volatile swings. The indicator serves dual purposes as both a dynamic support and resistance level during trends and an early warning system for potential reversals when price diverges significantly from the FWMA line. Moreover, the mathematical elegance of Fibonacci relationships appeals to traders who view markets through the lens of natural patterns and sacred geometry, making FWMA a bridge between technical analysis and mathematical philosophy. Because Fibonacci weights concentrate most influence into the most recent ~7–10 bars, increasing the period beyond roughly 10–12 only changes the curve very slightly. In practice that “plateau” is expected behavior, not a bug in the period handling.

Implementation Examples

Get started with FWMA in just a few lines:

use vectorta::indicators::moving_averages::fwma::{fwma, FwmaInput, FwmaParams};
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 = FwmaParams { period: Some(5) };
let input = FwmaInput::from_slice(&prices, params);
let result = fwma(&input)?;

// Using with Candles data structure (default: period=5, source="close")
let candles: Candles = read_candles_from_csv("data/sample.csv")?;
let input = FwmaInput::with_default_candles(&candles);
let result = fwma(&input)?;

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

API Reference

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

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

// From candles with default params (close prices, period=5)
FwmaInput::with_default_candles(&Candles) -> FwmaInput
Parameters Structure
pub struct FwmaParams {
    pub period: Option<usize>, // Default: 5
}
Output Structure
pub struct FwmaOutput {
    pub values: Vec<f64>, // FWMA values (normalized Fibonacci-weighted mean)
}
Validation, Warmup & NaNs
  • period > 0 and period ≤ data_len; otherwise FwmaError::InvalidPeriod.
  • Requires at least period valid points after the first finite value; else FwmaError::NotEnoughValidData.
  • Empty slice: FwmaError::EmptyInputData. All-NaN slice: FwmaError::AllValuesNaN.
  • Warmup: indices before first_finite + period − 1 are initialized to NaN.
  • NaNs in any window propagate to the corresponding output index.
  • Streaming: returns None until period inputs have been observed; then emits a value each update.
Error Handling
use vectorta::indicators::moving_averages::fwma::{fwma, FwmaInput, FwmaParams, FwmaError};

let input = FwmaInput::from_slice(&prices, FwmaParams { period: Some(5) });
match fwma(&input) {
    Ok(out) => println!("first value: {:?}", out.values.iter().find(|v| v.is_finite())),
    Err(FwmaError::EmptyInputData) => eprintln!("fwma: input slice is empty"),
    Err(FwmaError::AllValuesNaN) => eprintln!("fwma: all input values are NaN"),
    Err(FwmaError::InvalidPeriod { period, data_len }) => {
        eprintln!("fwma: invalid period {period} for length {data_len}")
    }
    Err(FwmaError::NotEnoughValidData { needed, valid }) => {
        eprintln!("fwma: need {needed} valid points, only {valid}")
    }
    Err(FwmaError::ZeroFibonacciSum) => eprintln!("fwma: zero Fibonacci sum (normalization failed)"),
}

Python Bindings

Basic Usage

Calculate FWMA using NumPy arrays (default period=5):

import numpy as np
from vectorta import fwma

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

# Calculate FWMA with default (period=5)
result = fwma(prices, period=5)

# Specify kernel for performance optimization
result = fwma(prices, period=5, kernel="avx2")

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

Process real-time price updates efficiently:

from vectorta import FwmaStream

# Initialize streaming FWMA calculator
stream = FwmaStream(period=5)

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

Test multiple period values for optimization:

import numpy as np
from vectorta import fwma_batch

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

# Define period sweep (start, end, step)
period_range = (3, 20, 1)

results = fwma_batch(prices, period_range=period_range, kernel="auto")

print(results["values"].shape)  # (num_periods, len(prices))
print(results["periods"])       # array of periods tested
CUDA Acceleration

CUDA-enabled APIs are available when built with Python + CUDA features:

# Requires vectorta built with CUDA support
from vectorta import fwma_cuda_batch_dev, fwma_cuda_many_series_one_param_dev
import numpy as np

# One series, many periods on GPU
prices = np.array([...], dtype=np.float64)
out_dev = fwma_cuda_batch_dev(prices, period_range=(3, 20, 1), device_id=0)

# Many series (time-major), one period on GPU
data_tm = np.array([...], dtype=np.float32)  # shape [T, N]
out_dev2 = fwma_cuda_many_series_one_param_dev(data_tm, period=5, device_id=0)

JavaScript/WASM Bindings

Basic Usage

Calculate FWMA in JavaScript/TypeScript:

import { fwma_js } from 'vectorta-wasm';

const prices = new Float64Array([100.0, 102.0, 101.5, 103.0, 105.0, 104.5]);

// Calculate FWMA for a given period
const values = fwma_js(prices, 5);
console.log('FWMA values:', values);
Memory-Efficient Operations

Use zero-copy operations for large datasets:

import { fwma_alloc, fwma_free, fwma_into, memory } from 'vectorta-wasm';

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

const inPtr = fwma_alloc(len);
const outPtr = fwma_alloc(len);

new Float64Array(memory.buffer, inPtr, len).set(prices);

// Args: in_ptr, out_ptr, len, period
fwma_into(inPtr, outPtr, len, 5);

const out = new Float64Array(memory.buffer, outPtr, len).slice();

fwma_free(inPtr, len);
fwma_free(outPtr, len);

console.log('FWMA values:', out);
Batch Processing

Test multiple period values efficiently:

import { fwma_batch_js, fwma_batch_metadata_js } from 'vectorta-wasm';

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

// Define period sweep range
const start = 3, end = 20, step = 1;  // 3, 4, 5, ..., 20

// Get metadata about periods tested
const periods = fwma_batch_metadata_js(start, end, step);
const numCombos = periods.length;

// Calculate all combinations
const results = fwma_batch_js(prices, start, end, step);

// Reshape into matrix [numCombos x len]
const matrix = [];
for (let i = 0; i < numCombos; i++) {
  const s = i * prices.length;
  matrix.push(results.slice(s, s + prices.length));
}

// Access results for a specific period
const p = periods[0];
const fwmaValues = matrix[0];

Performance Analysis

Comparison:
View:
Loading chart...

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

Related Indicators