1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#[cfg(feature = "simd_assets")]
pub use crate::indicators::simd_indicators::by_asset::ema::indicator_by_assets;
#[cfg(feature = "simd_options")]
pub use crate::indicators::simd_indicators::by_option::ema::indicator_by_options;
use std::simd::{Simd, StdFloat};
/// Computes the EMA multiplier pair for `N` lanes with potentially different periods.
///
/// Returns `(per, 1 - per)` where `per = 2.0 / (period + 1.0)` for each lane,
/// suitable for use with [`calc_simd`].
///
/// # Arguments
///
/// * `periods` - Array of per-lane EMA periods.
///
/// # Returns
///
/// A tuple `(multiplier, inv_multiplier)` as SIMD vectors.
#[inline(always)]
pub fn multiplier_simd<const N: usize>(periods: [usize; N]) -> (Simd<f64, N>, Simd<f64, N>) {
// Convert usize array to f64 array
let mut f64_periods = [0.0; N];
for i in 0..N {
f64_periods[i] = periods[i] as f64;
}
// Create SIMD vectors
let periods_simd = Simd::<f64, N>::from_array(f64_periods);
let two = Simd::<f64, N>::splat(2.0);
let one = Simd::<f64, N>::splat(1.0);
// Calculate: 2.0 / (period + 1.0)
let per = two / (periods_simd + one);
(per, one - per)
}
/// Computes one bar of the Exponential Moving Average (EMA) for `N` assets simultaneously
/// using SIMD parallelism.
///
/// Applies the standard EMA formula: `prev_ema * inv_multiplier + value * multiplier`.
///
/// # Arguments
///
/// * `value` - Current prices for this bar.
/// * `prev_ema` - Previous EMA values for each lane.
/// * `multipliers` - Tuple `(multiplier, inv_multiplier)` from [`multiplier_simd`].
///
/// # Returns
///
/// Updated EMA values for all `N` lanes.
#[inline(always)]
pub fn calc_simd<const N: usize>(
value: Simd<f64, N>,
prev_ema: Simd<f64, N>,
multipliers: (Simd<f64, N>, Simd<f64, N>),
) -> Simd<f64, N> {
let (multiplier, inv_multiplier) = multipliers;
//prev_ema * inv_multiplier + value * multiplier
prev_ema.mul_add(inv_multiplier, value * multiplier)
}