Logarithmic Moving Average
period = 100 | steepness = 2.5 | ma_type = ema | smooth = 10 | momentum_weight = 1.2 | long_threshold = 0.5 | short_threshold = -0.5 Overview
Logarithmic Moving Average uses an inverse logarithmic weighting curve to emphasize recent prices without falling off as aggressively as a short EMA. VectorTA computes that weighted baseline, measures its slope against a lookback anchor, combines that slope with logarithmic momentum and an R-squared quality term, then smooths the resulting signal with the selected moving-average family.
The indicator returns four aligned series: the weighted average itself, the smoothed signal, a position state of `1`, `0`, or `-1` based on the long and short thresholds, and a momentum confirmation flag that turns on when the signal and log-momentum terms agree. The optional `vwma` smoothing path can also incorporate volume.
Defaults: `period = 100`, `steepness = 2.5`, `ma_type = "ema"`, `smooth = 10`, `momentum_weight = 1.2`, `long_threshold = 0.5`, and `short_threshold = -0.5`.
Implementation Examples
Run the indicator on a raw slice or on candle closes with the default configuration.
use vector_ta::indicators::moving_averages::logarithmic_moving_average::{
logarithmic_moving_average,
LogarithmicMovingAverageInput,
LogarithmicMovingAverageParams,
};
use vector_ta::utilities::data_loader::{Candles, read_candles_from_csv};
let close = vec![100.0, 100.6, 101.2, 101.0, 102.4, 103.1, 103.6];
let output = logarithmic_moving_average(&LogarithmicMovingAverageInput::from_slice(
&close,
LogarithmicMovingAverageParams {
period: Some(100),
steepness: Some(2.5),
ma_type: Some("ema".to_string()),
smooth: Some(10),
momentum_weight: Some(1.2),
long_threshold: Some(0.5),
short_threshold: Some(-0.5),
},
))?;
let candles: Candles = read_candles_from_csv("data/sample.csv")?;
let candle_output = logarithmic_moving_average(&LogarithmicMovingAverageInput::with_default_candles(&candles))?;
println!("lma = {:?}", output.lma.last());
println!("signal = {:?}", candle_output.signal.last());
println!("position = {:?}", candle_output.position.last());
println!("momentum confirmed = {:?}", candle_output.momentum_confirmed.last()); API Reference
Input Methods ▼
// From candles with an explicit source
LogarithmicMovingAverageInput::from_candles(&Candles, &str, LogarithmicMovingAverageParams)
-> LogarithmicMovingAverageInput
// From a raw slice without volume
LogarithmicMovingAverageInput::from_slice(&[f64], LogarithmicMovingAverageParams)
-> LogarithmicMovingAverageInput
// From a raw slice with an aligned volume series
LogarithmicMovingAverageInput::from_slice_with_volume(&[f64], &[f64], LogarithmicMovingAverageParams)
-> LogarithmicMovingAverageInput
// From candles with default source and parameters
LogarithmicMovingAverageInput::with_default_candles(&Candles)
-> LogarithmicMovingAverageInput Parameters Structure ▼
pub struct LogarithmicMovingAverageParams {
pub period: Option<usize>, // default 100
pub steepness: Option<f64>, // default 2.5
pub ma_type: Option<String>, // default "ema"
pub smooth: Option<usize>, // default 10
pub momentum_weight: Option<f64>, // default 1.2
pub long_threshold: Option<f64>, // default 0.5
pub short_threshold: Option<f64>, // default -0.5
} Output Structure ▼
pub struct LogarithmicMovingAverageOutput {
pub lma: Vec<f64>,
pub signal: Vec<f64>,
pub position: Vec<f64>,
pub momentum_confirmed: Vec<f64>,
} Validation, Warmup & NaNs ▼
periodandsmoothmust both be greater than0.steepnessandmomentum_weightmust be finite positive numbers.long_thresholdmust stay greater thanshort_threshold.ma_typemust normalize toema,sma,wma,rma, orvwma.- The input slice must be non-empty, contain at least one finite value, and include a contiguous finite run at least as long as
period. - VWMA smoothing requires volume data, and any provided volume slice must match the price slice length.
- Warmup values remain
NaNuntil enough finite data exists for the logarithmic average, the slope lookback, and the selected signal smoother. - The stream returns
Noneuntil the latest bar produces finite values for all four outputs. - Batch mode validates every range axis and rejects unsupported kernels through
InvalidKernelForBatch.
Builder, Streaming & Batch APIs ▼
// Builder
LogarithmicMovingAverageBuilder::new()
.period(usize)
.steepness(f64)
.smooth(usize)
.momentum_weight(f64)
.long_threshold(f64)
.short_threshold(f64)
.kernel(Kernel)
.apply(&Candles)
LogarithmicMovingAverageBuilder::new()
.apply_slice(&[f64])
LogarithmicMovingAverageBuilder::new()
.apply_slice_with_volume(&[f64], &[f64], &str)
LogarithmicMovingAverageBuilder::new()
.into_stream(&str)
// Stream
LogarithmicMovingAverageStream::try_new(LogarithmicMovingAverageParams)
LogarithmicMovingAverageStream::update(f64, Option<f64>) -> Option<(f64, f64, f64, f64)>
// Batch
LogarithmicMovingAverageBatchBuilder::new()
.period(usize, usize, usize)
.steepness(f64, f64, f64)
.smooth(usize, usize, usize)
.momentum_weight(f64, f64, f64)
.long_threshold(f64, f64, f64)
.short_threshold(f64, f64, f64)
.ma_type(&str)
.kernel(Kernel)
.apply_slice(&[f64])
LogarithmicMovingAverageBatchBuilder::new()
.apply_slice_with_volume(&[f64], &[f64])
LogarithmicMovingAverageBatchBuilder::new()
.apply(&Candles) Error Handling ▼
pub enum LogarithmicMovingAverageError {
EmptyInputData,
AllValuesNaN,
InvalidPeriod { period: usize, data_len: usize },
InvalidSmooth { smooth: usize, data_len: usize },
InvalidSteepness { steepness: f64 },
InvalidMaType { ma_type: String },
InvalidMomentumWeight { momentum_weight: f64 },
InvalidThresholds { long_threshold: f64, short_threshold: f64 },
DataLengthMismatch { data_len: usize, volume_len: usize },
MissingVolumeForVwma,
NotEnoughValidData { needed: usize, valid: usize },
OutputLengthMismatch { expected: usize, got: usize },
InvalidRange { start: String, end: String, step: String },
InvalidKernelForBatch(Kernel),
} Python Bindings
Python exposes a scalar function, a streaming class, and a batch sweep. The scalar function returns four NumPy arrays: `lma`, `signal`, `position`, and `momentum_confirmed`. The stream returns one four-value tuple or `None`, while batch returns flattened matrices plus the tested parameter axes and output dimensions.
import numpy as np
from vector_ta import (
logarithmic_moving_average,
logarithmic_moving_average_batch,
LogarithmicMovingAverageStream,
)
data = np.asarray(close_values, dtype=np.float64)
volume = np.asarray(volume_values, dtype=np.float64)
lma, signal, position, momentum_confirmed = logarithmic_moving_average(
data,
period=100,
steepness=2.5,
ma_type="ema",
smooth=10,
momentum_weight=1.2,
long_threshold=0.5,
short_threshold=-0.5,
volume=None,
kernel="auto",
)
stream = LogarithmicMovingAverageStream(
period=80,
steepness=2.8,
ma_type="vwma",
smooth=8,
momentum_weight=1.4,
long_threshold=0.7,
short_threshold=-0.7,
)
print(stream.update(data[-1], float(volume[-1])))
batch = logarithmic_moving_average_batch(
data,
period_range=(60, 100, 20),
steepness_range=(2.0, 3.0, 0.5),
smooth_range=(6, 10, 2),
momentum_weight_range=(1.0, 1.4, 0.2),
long_threshold_range=(0.4, 0.8, 0.2),
short_threshold_range=(-0.8, -0.4, 0.2),
ma_type="ema",
volume=None,
kernel="auto",
)
print(batch["signal"].shape)
print(batch["periods"])
print(batch["steepnesses"]) JavaScript/WASM Bindings
The WASM surface exposes scalar, batch, and into-buffer entry points. The scalar function returns an object with `lma`, `signal`, `position`, and `momentum_confirmed` arrays. The batch function returns flattened matrices, output dimensions, and the tested parameter combinations.
import init, {
logarithmic_moving_average_js,
logarithmic_moving_average_batch_js,
} from "@vectoralpha/vector_ta";
await init();
const single = logarithmic_moving_average_js(
close,
[],
100,
2.5,
"ema",
10,
1.2,
0.5,
-0.5,
);
console.log(single.lma);
console.log(single.signal);
console.log(single.position);
console.log(single.momentum_confirmed);
const batch = logarithmic_moving_average_batch_js(close, [], {
period_range: [60, 100, 20],
steepness_range: [2.0, 3.0, 0.5],
smooth_range: [6, 10, 2],
momentum_weight_range: [1.0, 1.4, 0.2],
long_threshold_range: [0.4, 0.8, 0.2],
short_threshold_range: [-0.8, -0.4, 0.2],
ma_type: "ema",
});
console.log(batch.lma);
console.log(batch.signal);
console.log(batch.position);
console.log(batch.momentum_confirmed);
console.log(batch.rows, batch.cols); CUDA Bindings (Rust)
Additional details for the CUDA bindings can be found inside the VectorTA repository.
Performance Analysis
Across sizes, Rust CPU runs about 1.14× faster than Tulip C in this benchmark.
AMD Ryzen 9 9950X (CPU) | NVIDIA RTX 4090 (GPU)
Related Indicators
Arnaud Legoux Moving Average
Moving average indicator
Buff Averages
Technical analysis 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 Distance Coefficient Filter
Moving average indicator