Polarized Fractal Efficiency (PFE)
period = 10 | smoothing = 5 Overview
Polarized Fractal Efficiency (PFE) quantifies how efficiently price travels from point A to point B by comparing the direct distance against the actual path taken. The indicator divides the straight line distance between current price and the price n periods ago by the sum of all incremental step lengths within that window, then multiplies by 100 and applies a sign reflecting direction. When price moves in a straight line, PFE approaches +100 or -100 depending on trend direction; when price meanders sideways, PFE gravitates toward zero. An exponential moving average smooths the raw efficiency calculation to filter noise and highlight persistent directional movement. Traders interpret high absolute PFE values as strong trending markets suitable for momentum strategies, while values near zero suggest choppy conditions better suited for mean reversion approaches.
Implementation Examples
Get started with PFE in just a few lines:
use vectorta::indicators::pfe::{pfe, PfeInput, PfeParams};
use vectorta::utilities::data_loader::{Candles, read_candles_from_csv};
// Using with price data slice
let prices = vec![100.0, 101.0, 102.5, 101.8, 103.2, 104.0];
let params = PfeParams { period: Some(10), smoothing: Some(5) }; // defaults are 10/5
let input = PfeInput::from_slice(&prices, params);
let result = pfe(&input)?;
// Using with Candles data structure
// Quick and simple with default parameters (period=10, smoothing=5; source="close")
let candles: Candles = read_candles_from_csv("data/sample.csv")?;
let input = PfeInput::with_default_candles(&candles);
let result = pfe(&input)?;
// Access the PFE values
for value in result.values {
println!("PFE: {}", value);
} API Reference
Input Methods ▼
// From price slice
PfeInput::from_slice(&[f64], PfeParams) -> PfeInput
// From candles with custom source
PfeInput::from_candles(&Candles, &str, PfeParams) -> PfeInput
// From candles with default params (close prices, period=10, smoothing=5)
PfeInput::with_default_candles(&Candles) -> PfeInput Parameters Structure ▼
#[derive(Default)]
pub struct PfeParams {
pub period: Option<usize>, // Default: 10
pub smoothing: Option<usize>, // Default: 5
} Output Structure ▼
pub struct PfeOutput {
pub values: Vec<f64>, // PFE values (signed, EMA-smoothed), NaN prefix during warmup
} Validation, Warmup & NaNs ▼
period > 0elsePfeError::InvalidPeriod;smoothing > 0elsePfeError::InvalidSmoothing.- Data must contain at least one finite value; otherwise
PfeError::AllValuesNaN. Empty slice:PfeError::EmptyInputData. - Requires at least
period + 1valid points after the first finite value; otherwisePfeError::NotEnoughValidData(needed = period + 1). - Warmup: indices
[0 .. first + period)areNaN; first computable index isfirst + period. - EMA smoothing is seeded with the first available signed raw value (
α = 2/(s+1)). - If the denominator is ≈0 at any step, raw PFE is treated as
0.0.
Error Handling ▼
use vectorta::indicators::pfe::{pfe, PfeError};
match pfe(&input) {
Ok(output) => process_results(output.values),
Err(PfeError::EmptyInputData) => eprintln!("input is empty"),
Err(PfeError::AllValuesNaN) => eprintln!("all values are NaN"),
Err(PfeError::InvalidPeriod { period, data_len }) => {
eprintln!("invalid period: {} for len {}", period, data_len)
}
Err(PfeError::NotEnoughValidData { needed, valid }) => {
eprintln!("not enough valid data: needed {}, got {}", needed, valid)
}
Err(PfeError::InvalidSmoothing { smoothing }) => {
eprintln!("invalid smoothing: {}", smoothing)
}
} Python Bindings
Basic Usage ▼
Calculate PFE using NumPy arrays (defaults: period=10, smoothing=5):
import numpy as np
from vectorta import pfe
# Prepare price data as NumPy array
prices = np.array([100.0, 101.0, 102.5, 101.8, 103.2, 104.0])
# Calculate PFE with defaults (10/5)
result = pfe(prices, period=10, smoothing=5)
# Or specify custom parameters and kernel
result = pfe(prices, period=14, smoothing=5, kernel="avx2")
print(f"PFE values: {result}") Streaming Real-time Updates ▼
Process real-time price updates efficiently:
from vectorta import PfeStream
# Initialize streaming PFE calculator
stream = PfeStream(period=10, smoothing=5)
# Process real-time price updates
for price in price_feed:
pfe_value = stream.update(price)
if pfe_value is not None:
# PFE value is ready (None during warmup period)
print(f"Current PFE: {pfe_value}") Batch Parameter Optimization ▼
Test multiple parameter combinations for optimization:
import numpy as np
from vectorta import pfe_batch
prices = np.array([...]) # Your historical prices
# (start, end, step) for each parameter
period_range = (5, 20, 5) # 5, 10, 15, 20
smoothing_range = (1, 10, 1) # 1..10
results = pfe_batch(
prices,
period_range=period_range,
smoothing_range=smoothing_range,
kernel="auto"
)
print(results['values'].shape) # (num_combinations, len(prices))
print(results['periods']) # periods tested
print(results['smoothings']) # smoothings tested CUDA Acceleration ▼
CUDA support for PFE is currently under development. The API will follow the same pattern as other CUDA-enabled indicators.
# Coming soon: CUDA-accelerated PFE calculations
# See APO page for the expected API patterns. JavaScript/WASM Bindings
Basic Usage ▼
Calculate PFE in JavaScript/TypeScript:
import { pfe_js } from 'vectorta-wasm';
const prices = new Float64Array([100.0, 101.0, 102.5, 101.8, 103.2, 104.0]);
// Calculate PFE with specified parameters
const result = pfe_js(prices, 10, 5);
console.log('PFE values:', result); Memory-Efficient Operations ▼
Use zero-copy operations for better performance with large datasets:
import { pfe_alloc, pfe_free, pfe_into, memory } from 'vectorta-wasm';
const prices = new Float64Array([/* your data */]);
const length = prices.length;
const inPtr = pfe_alloc(length);
const outPtr = pfe_alloc(length);
new Float64Array(memory.buffer, inPtr, length).set(prices);
// Args: in_ptr, out_ptr, len, period, smoothing
pfe_into(inPtr, outPtr, length, 10, 5);
const pfeValues = new Float64Array(memory.buffer, outPtr, length).slice();
pfe_free(inPtr, length);
pfe_free(outPtr, length);
console.log('PFE values:', pfeValues); Batch Processing ▼
Test multiple parameter combinations efficiently:
import { pfe_batch } from 'vectorta-wasm';
const prices = new Float64Array([/* historical prices */]);
// Unified batch API accepts a config object
const config = {
period_range: [5, 20, 5], // 5, 10, 15, 20
smoothing_range: [1, 10, 1], // 1..10
};
const out = pfe_batch(prices, config);
// out: { values: Float64Array, combos: Array<{period:number, smoothing:number}>, rows:number, cols:number }
// Reshape flat values into [rows x cols]
const rows = out.rows, cols = out.cols;
const matrix: number[][] = [];
for (let r = 0; r < rows; r++) {
const start = r * cols;
matrix.push(Array.from(out.values.slice(start, start + cols)));
}
// Access row for a specific parameter combo
const target = { period: 10, smoothing: 5 };
const idx = out.combos.findIndex(c => c.period === target.period && c.smoothing === target.smoothing);
const values = idx >= 0 ? matrix[idx] : undefined; Performance Analysis
AMD Ryzen 9 9950X (CPU) | NVIDIA RTX 4090 (GPU) | Benchmarks: 2026-01-05
Related Indicators
Average Directional Index
Technical analysis indicator
Average Directional Movement Index Rating
Technical analysis indicator
Alligator
Technical analysis indicator
Aroon
Technical analysis indicator
Aroon Oscillator
Technical analysis indicator
Chande Momentum Oscillator
Technical analysis indicator