Ehlers Distance Coefficient Filter (EDCF)
period = 15 Overview
The Ehlers Distance Coefficient Filter (EDCF), developed by John Ehlers, creates an adaptive smoothing filter that automatically adjusts its behavior based on market volatility using a unique distance weighting approach. Rather than using fixed weights like traditional moving averages, EDCF calculates weights dynamically by measuring the squared distances between consecutive price samples within the lookback window. Larger price movements generate higher weights, causing the filter to respond more quickly to significant changes. This non linear weighting scheme allows EDCF to reduce noise during sideways markets while maintaining responsiveness during trending periods. The filter essentially becomes more reactive when price movements are decisive and more stable when movements are minor.
EDCF excels at adapting to changing market conditions without manual parameter adjustments. During low volatility consolidation phases, the distance weights become more uniform, causing the filter to smooth price action similar to a traditional moving average. When volatility increases and price makes larger moves, the squared distance calculation heavily weights these significant changes, allowing the filter to track price more closely. This adaptive behavior makes EDCF particularly effective in markets that alternate between trending and ranging states. The period parameter determines the lookback window for distance calculations, with typical values ranging from 10 to 20 periods depending on the desired balance between smoothness and responsiveness.
Traders use EDCF as a superior alternative to traditional moving averages for trend identification and signal generation. The filter provides cleaner signals during choppy markets by automatically reducing sensitivity when price movements lack conviction. Crossovers between price and EDCF generate trading signals with fewer whipsaws than fixed weight averages, as the adaptive weighting helps distinguish genuine breakouts from noise. Many traders employ EDCF as a baseline for other calculations, using its adaptive smoothing to improve oscillators or band indicators. The filter also works well for dynamic support and resistance levels, as its adaptive nature keeps it relevant to current market volatility rather than lagging behind like traditional smoothing methods.
Implementation Examples
Get started with EDCF in a few lines:
use vectorta::indicators::moving_averages::edcf::{edcf, EdcfInput, EdcfParams};
use vectorta::utilities::data_loader::{Candles, read_candles_from_csv};
// Using with a price slice
let prices = vec![100.0, 102.0, 101.5, 103.0, 105.0, 104.5];
let params = EdcfParams { period: Some(15) };
let input = EdcfInput::from_slice(&prices, params);
let result = edcf(&input)?;
// Using with Candles (defaults: period=15, source="close")
let candles: Candles = read_candles_from_csv("data/sample.csv")?;
let input = EdcfInput::with_default_candles(&candles);
let result = edcf(&input)?;
// Access the filtered values
for value in result.values {
println!("EDCF: {}", value);
} API Reference
Input Methods ▼
// From price slice
EdcfInput::from_slice(&[f64], EdcfParams) -> EdcfInput
// From candles with custom source
EdcfInput::from_candles(&Candles, &str, EdcfParams) -> EdcfInput
// From candles with default params (close, period=15)
EdcfInput::with_default_candles(&Candles) -> EdcfInput Parameters Structure ▼
pub struct EdcfParams {
pub period: Option<usize>, // Default: 15
} Output Structure ▼
pub struct EdcfOutput {
pub values: Vec<f64>, // Weighted filter values matching input length
} Validation, Warmup & NaNs ▼
period > 0andperiod ≤ len(data), otherwiseEdcfError::InvalidPeriod.- Must have at least
2×periodvalid points after the first finite value; otherwiseEdcfError::NotEnoughValidData. - Warmup: indices
[.. first_finite + 2×period)areNaNby design. - Constant windows can yield
NaNwhen the weights’ sum is zero. edcf_into_slice: destination length must equal input length, elseEdcfError::OutputLenMismatch.- Streaming: returns
Noneuntil filled withperiodsamples; non‑finite inputs returnNone.
Error Handling ▼
use vectorta::indicators::moving_averages::edcf::{edcf, EdcfInput, EdcfParams, EdcfError};
match edcf(&EdcfInput::from_slice(&prices, EdcfParams { period: Some(15) })) {
Ok(output) => process_results(output.values),
Err(EdcfError::NoData) => println!("No data provided"),
Err(EdcfError::AllValuesNaN) => println!("All input values are NaN"),
Err(EdcfError::InvalidPeriod { period, data_len }) =>
println!("Invalid period {} for data length {}", period, data_len),
Err(EdcfError::NotEnoughValidData { needed, valid }) =>
println!("Need {} valid points, only {}", needed, valid),
Err(EdcfError::OutputLenMismatch { expected, got }) =>
println!("Output buffer len mismatch: expected {}, got {}", expected, got),
Err(EdcfError::InvalidKernel) => println!("Invalid kernel specified for batch computation"),
} Python Bindings
Basic Usage ▼
import numpy as np
from vectorta import edcf, EdcfStream
prices = np.array([100.0, 102.0, 101.5, 103.0, 105.0, 104.5], dtype=np.float64)
# One-shot calculation
values = edcf(prices, period=15)
# Streaming
stream = EdcfStream(period=15)
out = []
for p in prices:
v = stream.update(float(p))
out.append(np.nan if v is None else v) Batch Processing ▼
Test parameter ranges efficiently:
import numpy as np
from vectorta import edcf_batch
prices = np.array([...], dtype=np.float64)
period_range = (5, 30, 5) # 5, 10, 15, 20, 25, 30
res = edcf_batch(prices, period_range, kernel="auto")
print(res.keys()) # values, periods
print(res['values'].shape) # (num_periods, len(prices))
print(res['periods']) CUDA Acceleration ▼
CUDA interfaces are available for EDCF when built with CUDA support.
import numpy as np
from vectorta import edcf_cuda_batch_dev, edcf_cuda_many_series_one_param_dev
# Option 1: Single series, many parameters
prices_f32 = np.array([...], dtype=np.float32)
period_range = (5, 30, 1)
dev_id = 0
gpu_out = edcf_cuda_batch_dev(prices_f32, period_range, device_id=dev_id)
# Option 2: Many series (time-major [T, N]), one parameter
tm = np.array([[...], [...]], dtype=np.float32) # shape [T, N]
gpu_out2 = edcf_cuda_many_series_one_param_dev(tm, period=15, device_id=dev_id) JavaScript/WASM Bindings
Basic Usage ▼
Calculate EDCF in JavaScript/TypeScript:
import { edcf_js } from 'vectorta-wasm';
const prices = new Float64Array([100.0, 102.0, 101.5, 103.0, 105.0, 104.5]);
const values = edcf_js(prices, 15);
console.log('EDCF values:', values); Note: EDCF allocates and reads a full distance buffer; in WASM this is significantly slower than native (20–60×). Consider ALMA/EMA/HMA for browser workloads.
Memory-Efficient Operations ▼
Use zero-copy operations for large datasets:
import { edcf_alloc, edcf_free, edcf_into, memory } from 'vectorta-wasm';
const prices = new Float64Array([/* your data */]);
const len = prices.length;
const inPtr = edcf_alloc(len);
const outPtr = edcf_alloc(len);
new Float64Array(memory.buffer, inPtr, len).set(prices);
// Args: in_ptr, out_ptr, len, period
edcf_into(inPtr, outPtr, len, 15);
const values = new Float64Array(memory.buffer, outPtr, len).slice();
edcf_free(inPtr, len);
edcf_free(outPtr, len); Batch Processing ▼
Test multiple period values efficiently:
import { edcf_batch_js, edcf_batch_metadata_js } from 'vectorta-wasm';
const prices = new Float64Array([/* historical prices */]);
const periodStart = 5, periodEnd = 30, periodStep = 5;
const metadata = edcf_batch_metadata_js(periodStart, periodEnd, periodStep);
const numCombos = metadata.length; // one value per period
const results = edcf_batch_js(prices, periodStart, periodEnd, periodStep);
// results is flat: [combo1..., combo2..., ...]
const matrix: number[][] = [];
for (let i = 0; i < numCombos; i++) {
const start = i * prices.length;
const end = start + prices.length;
matrix.push(Array.from(results.slice(start, end)));
} Performance Analysis
AMD Ryzen 9 9950X (CPU) | NVIDIA RTX 4090 (GPU) | Benchmarks: 2026-01-05
Related Indicators
Arnaud Legoux Moving Average
Moving average indicator
Compound Ratio Moving Average (CoRa Wave)
Moving average indicator
Centered Weighted Moving Average
Moving average indicator
Double Exponential Moving Average
Moving average indicator
Ehlers Error-Correcting EMA (ECEMA)
Moving average indicator
Ehlers Instantaneous Trendline
Moving average indicator