use chrono::{Duration, NaiveDateTime};
use pandrs::dataframe::{DataFrame, EnhancedDataFrameWindowExt};
use pandrs::error::Result;
use pandrs::series::window::WindowClosed;
use pandrs::series::Series;
#[allow(clippy::result_large_err)]
#[allow(clippy::result_large_err)]
fn main() -> Result<()> {
println!("PandRS Alpha.7: Enhanced Window Operations Example");
println!("==================================================");
let dates = [
"2024-01-01 09:00:00",
"2024-01-01 09:15:00",
"2024-01-01 09:30:00",
"2024-01-01 09:45:00",
"2024-01-01 10:00:00",
"2024-01-01 10:15:00",
"2024-01-01 10:30:00",
"2024-01-01 10:45:00",
"2024-01-01 11:00:00",
"2024-01-01 11:15:00",
"2024-01-01 11:30:00",
"2024-01-01 11:45:00",
];
let prices = [
100.0, 102.5, 101.8, 103.2, 104.1, 102.9, 105.6, 107.2, 106.8, 108.1, 109.3, 107.9,
];
let volumes = [
1000, 1500, 1200, 1800, 2200, 1600, 2400, 2100, 1900, 2300, 2000, 1700,
];
let returns = [
0.0, 0.025, -0.007, 0.014, 0.009, -0.012, 0.026, 0.015, -0.004, 0.012, 0.011, -0.013,
];
let datetime_series: Vec<NaiveDateTime> = dates
.iter()
.map(|date_str| NaiveDateTime::parse_from_str(date_str, "%Y-%m-%d %H:%M:%S"))
.collect::<std::result::Result<Vec<_>, _>>()
.map_err(|e| pandrs::error::Error::InvalidValue(format!("Date parsing error: {e}")))?;
let mut df = DataFrame::new();
df.add_column(
"datetime".to_string(),
Series::new(datetime_series, Some("datetime".to_string()))?,
)?;
df.add_column(
"price".to_string(),
Series::new(
prices.iter().map(|p| p.to_string()).collect::<Vec<_>>(),
Some("price".to_string()),
)?,
)?;
df.add_column(
"volume".to_string(),
Series::new(
volumes.iter().map(|v| v.to_string()).collect::<Vec<_>>(),
Some("volume".to_string()),
)?,
)?;
df.add_column(
"returns".to_string(),
Series::new(
returns.iter().map(|r| r.to_string()).collect::<Vec<_>>(),
Some("returns".to_string()),
)?,
)?;
println!("Original Financial Data:");
println!("{df:?}");
println!();
println!("1. Enhanced Rolling Window Operations");
println!("=====================================");
let rolling_config = df
.rolling(3)
.min_periods(2)
.center(false)
.closed(WindowClosed::Right)
.columns(vec!["price".to_string(), "volume".to_string()]);
let rolling_ops = df.apply_rolling(&rolling_config);
let rolling_mean = rolling_ops.mean()?;
println!("Rolling Mean (window=3, min_periods=2):");
println!("{rolling_mean:?}");
println!();
let rolling_std = rolling_ops.std(1)?;
println!("Rolling Standard Deviation (ddof=1):");
println!("{rolling_std:?}");
println!();
let rolling_quantile = rolling_ops.quantile(0.75)?;
println!("Rolling 75th Percentile:");
println!("{rolling_quantile:?}");
println!();
println!("2. Enhanced Expanding Window Operations");
println!("======================================");
let expanding_config = df
.expanding(2)
.columns(vec!["price".to_string(), "returns".to_string()]);
let expanding_ops = df.apply_expanding(&expanding_config);
let expanding_mean = expanding_ops.mean()?;
let expanding_std = expanding_ops.std(1)?;
println!("Expanding Mean (min_periods=2):");
println!("{expanding_mean:?}");
println!();
println!("Expanding Standard Deviation:");
println!("{expanding_std:?}");
println!();
println!("3. Enhanced Exponentially Weighted Moving Operations");
println!("====================================================");
let ewm_config_span = df
.ewm()
.span(4)
.adjust(true)
.columns(vec!["price".to_string(), "returns".to_string()]);
let ewm_ops = df.apply_ewm(&ewm_config_span)?;
let ewm_mean = ewm_ops.mean()?;
println!("EWM Mean (span=4, adjust=true):");
println!("{ewm_mean:?}");
println!();
let ewm_config_alpha = df
.ewm()
.alpha(0.3)
.unwrap()
.adjust(false)
.columns(vec!["price".to_string()]);
let ewm_ops_alpha = df.apply_ewm(&ewm_config_alpha)?;
let ewm_var = ewm_ops_alpha.var(1)?;
println!("EWM Variance (alpha=0.3, adjust=false):");
println!("{ewm_var:?}");
println!();
println!("4. Time-based Rolling Windows");
println!("=============================");
let time_rolling = df.rolling_time(Duration::minutes(30), "datetime")?;
let time_mean = time_rolling.mean()?;
let time_count = time_rolling.count()?;
println!("Time-based Rolling Mean (30-minute window):");
println!("{time_mean:?}");
println!();
println!("Time-based Rolling Count (30-minute window):");
println!("{time_count:?}");
println!();
println!("5. Multi-column Rolling Operations");
println!("==================================");
let multi_rolling = df.rolling(4).min_periods(3);
let multi_ops = df.apply_rolling(&multi_rolling);
let multi_mean = multi_ops.mean()?;
let multi_max = multi_ops.max()?;
let multi_min = multi_ops.min()?;
println!("Multi-column Rolling Mean (all numeric columns):");
println!("{multi_mean:?}");
println!();
println!("Multi-column Rolling Max:");
println!("{multi_max:?}");
println!();
println!("Multi-column Rolling Min:");
println!("{multi_min:?}");
println!();
println!("6. Custom Aggregation Functions");
println!("===============================");
let custom_rolling = df.rolling(3).columns(vec!["price".to_string()]);
let custom_ops = df.apply_rolling(&custom_rolling);
let price_momentum = custom_ops.apply(|window| {
if window.is_empty() {
0.0
} else {
let max_val = window.iter().fold(f64::NEG_INFINITY, |a, &b| a.max(b));
let min_val = window.iter().fold(f64::INFINITY, |a, &b| a.min(b));
max_val - min_val
}
})?;
println!("Price Momentum (max-min in 3-period window):");
println!("{price_momentum:?}");
println!();
println!("7. Advanced Window Parameters");
println!("=============================");
let centered_rolling = df
.rolling(5)
.center(true)
.min_periods(3)
.closed(WindowClosed::Both)
.columns(vec!["price".to_string()]);
let centered_ops = df.apply_rolling(¢ered_rolling);
let centered_mean = centered_ops.mean()?;
println!("Centered Rolling Mean (window=5, center=true):");
println!("{centered_mean:?}");
println!();
println!("Enhanced Window Operations Example Completed Successfully!");
println!("=========================================================");
Ok(())
}