added place holder for historic vol

This commit is contained in:
Palash Tyagi 2024-11-22 17:15:37 +00:00
parent cc08a3da59
commit f9d2513202

85
src/panel/historic_vol.rs Normal file
View File

@ -0,0 +1,85 @@
use ndarray::{Array, Array1, Zip};
use polars::prelude::*;
#[allow(dead_code)]
fn expo_weights(lback_periods: usize, half_life: f64) -> Array1<f64> {
// Calculates exponential series weights for finite horizon, normalized to 1.
let decf = 2f64.powf(-1.0 / half_life);
let mut weights = Array::from_iter(
(0..lback_periods)
.map(|ii| (lback_periods - ii - 1) as f64)
.map(|exponent| (decf.powf(exponent)) * (1.0 - decf)),
);
weights /= weights.sum();
weights
}
#[allow(dead_code)]
fn expo_std(x: &Array1<f64>, w: &Array1<f64>, remove_zeros: bool) -> f64 {
assert_eq!(x.len(), w.len(), "weights and window must have same length");
let (filtered_x, filtered_w) = if remove_zeros {
let indices: Vec<usize> = x
.iter()
.enumerate()
.filter_map(|(i, &val)| if val != 0.0 { Some(i) } else { None })
.collect();
(
Array::from_iter(indices.iter().map(|&i| x[i])),
Array::from_iter(indices.iter().map(|&i| w[i])),
)
} else {
(x.clone(), w.clone())
};
let filtered_w = &filtered_w / filtered_w.sum();
Zip::from(&filtered_x)
.and(&filtered_w)
.fold(0.0, |acc, &x_val, &w_val| acc + w_val * x_val.abs())
}
#[allow(dead_code)]
fn flat_std(x: &Array1<f64>, remove_zeros: bool) -> f64 {
let filtered_x = if remove_zeros {
x.iter()
.filter(|&&val| val != 0.0)
.cloned()
.collect::<Array1<f64>>()
} else {
x.clone()
};
filtered_x.mapv(f64::abs).mean().unwrap_or(0.0)
}
/// Calculate historic volatility.
/// Arguments:
/// - `df`: A Quantamental DataFrame.
/// - `xcat`: The category to calculate the historic volatility for.
/// - `cids`: A list of cross-sections. If none are provided, all cross-sections available
/// in the DataFrame will be used.
/// - `lback_periods`: The number of lookback periods to use for the calculation.
/// - `lback_method`: The method to use for the lookback period calculation. Options are
/// 'ma' (moving average) and 'xma' (exponential moving average).
/// - `half_life`: The half-life of the exponential weighting function.
/// - `start`: Only include data after this date. Defaults to the earliest date available.
/// - `end`: Only include data before this date. Defaults to the latest date available.
/// - `est_freq`: The frequency of the data. Defaults to 'D' (daily). Options are 'D' (daily),
/// 'W' (weekly), 'M' (monthly), and 'Q' (quarterly).
/// - `remove_zeros`: Whether to remove zero values from the calculation. Defaults to False.
/// - `postfix`: A string to append to XCAT of the result series.
/// - `nan_tolerance`: The maximum proportion of NaN values allowed in the calculation.
pub fn historic_vol(
df: polars::prelude::DataFrame,
xcat: String,
cids: Option<Vec<String>>,
lback_periods: Option<usize>,
lback_method: Option<String>,
half_life: Option<f64>,
start: Option<String>,
end: Option<String>,
est_freq: Option<String>,
remove_zeros: Option<bool>,
postfix: Option<String>,
nan_tolerance: Option<f64>,
) -> Result<DataFrame, Box<dyn std::error::Error>> {
println!("Calculating historic volatility with the following parameters:");
println!("xcat: {:?},\ncids: {:?},\nlback_periods: {:?},lback_method: {:?},\nhalf_life: {:?},\nstart: {:?},\nend: {:?},\nest_freq: {:?},\nremove_zeros: {:?},\npostfix: {:?},\nnan_tolerance: {:?}", xcat, cids, lback_periods,lback_method, half_life, start, end, est_freq, remove_zeros, postfix, nan_tolerance);
Ok(df.to_owned())
}