use crate::interpreter::{Func, VarValue};
use std::sync::Arc;
pub fn sma() -> Func {
Func::Builtin(Arc::new(Box::new(|args: Vec<VarValue>| {
if args.len() != 2 {
panic!("`sma` expects 2 arguments: a numeric array, and a window length");
}
let data: Vec<f64> = match &args[0] {
VarValue::Array(vals) => vals.iter().map(to_f64_or_panic).collect(),
other => panic!("`sma`: expected array as first argument, got {:?}", other),
};
let window_len = match &args[1] {
VarValue::Int(n) => *n as usize,
other => panic!("`sma`: expected int as second argument, got {:?}", other),
};
let series = quant_mathema::smoothing::sma_series(&data, window_len);
VarValue::Array(series.into_iter().map(VarValue::Float).collect())
})))
}
pub fn ema() -> Func {
Func::Builtin(Arc::new(Box::new(|args: Vec<VarValue>| {
if args.len() != 2 {
panic!("`ema` expects 2 arguments: an array and a window length");
}
let series = match &args[0] {
VarValue::Array(vals) => vals.iter().map(to_f64_or_panic).collect::<Vec<f64>>(),
other => panic!("`ema`: expected array as first argument, got {:?}", other),
};
let window_len = match &args[1] {
VarValue::Int(n) => *n as usize,
other => panic!("`ema`: expected int as second argument, got {:?}", other),
};
let ema_series = quant_mathema::smoothing::ema_series(&series, window_len);
VarValue::Array(ema_series.into_iter().map(VarValue::Float).collect())
})))
}
pub fn vwma() -> Func {
Func::Builtin(Arc::new(Box::new(|args: Vec<VarValue>| {
if args.len() != 3 {
panic!("`vwma` expects 3 arguments: prices array, volumes array, window length");
}
let prices: Vec<f64> = match &args[0] {
VarValue::Array(vals) => vals.iter().map(to_f64_or_panic).collect(),
other => panic!("`vwma`: expected array as first argument, got {:?}", other),
};
let volumes: Vec<u32> = match &args[1] {
VarValue::Array(vals) => vals
.iter()
.map(|val| match val {
VarValue::Int(x) => *x as u32,
other => panic!(
"`vwma`: expected array of integers as second argument, got {:?}",
other
),
})
.collect(),
other => panic!("`vwma`: expected array as second argument, got {:?}", other),
};
let window_len = match &args[2] {
VarValue::Int(n) => *n as usize,
other => panic!("`vwma`: expected int as third argument, got {:?}", other),
};
let series = quant_mathema::smoothing::vwma_series(&prices, &volumes, window_len);
VarValue::Array(series.into_iter().map(VarValue::Float).collect())
})))
}
pub fn lsma() -> Func {
Func::Builtin(Arc::new(Box::new(|args: Vec<VarValue>| {
if args.len() != 2 {
panic!("`lsma` expects 2 arguments: a numeric array, and a window length");
}
let data: Vec<f64> = match &args[0] {
VarValue::Array(vals) => vals.iter().map(to_f64_or_panic).collect(),
other => panic!("`lsma`: expected array as first argument, got {:?}", other),
};
let window_len = match &args[2] {
VarValue::Int(n) => *n as usize,
other => panic!("`lsma`: expected int as second argument, got {:?}", other),
};
if let Ok(series) = quant_mathema::smoothing::lsma_series(&data, window_len) {
VarValue::Array(series.into_iter().map(VarValue::Float).collect())
} else {
VarValue::Array(Vec::new())
}
})))
}
fn to_f64_or_panic(v: &VarValue) -> f64 {
match v {
VarValue::Float(f) => *f,
VarValue::Int(i) => *i as f64,
other => panic!("expected numeric array element, got {:?}", other),
}
}