use anyhow::Result;
use burn::tensor::backend::Backend;
use polars::prelude::*;
use super::step_1_tensor_preparation;
use super::step_3_cnn_lstm_model_arch::TimeSeriesCnnLstm;
use crate::constants;
pub fn forecast<B: Backend>(
model: &TimeSeriesCnnLstm<B>,
df: &DataFrame,
device: &B::Device,
forecast_horizon: usize,
) -> Result<Vec<f64>> {
let sequence_length = constants::SEQUENCE_LENGTH;
let input_size = model.input_size();
if df.height() < sequence_length {
return Err(anyhow::anyhow!("Not enough data points for forecasting. Need at least {} rows.", sequence_length));
}
let df_slice = df.slice((df.height() - sequence_length) as i64, sequence_length);
println!("Preparing prediction tensors with reduced forecast horizon of {} steps", forecast_horizon);
let (features, _) = step_1_tensor_preparation::dataframe_to_tensors::<B>(
&df_slice,
sequence_length,
forecast_horizon, device,
true, None,
)?;
let input_tensor = if features.dims()[0] != 1 {
features.unsqueeze::<3>().reshape([1, sequence_length, input_size])
} else {
features
};
let predictions = model.forward(input_tensor);
let predictions_data = predictions.to_data().convert::<f32>();
let predictions_slice = predictions_data.as_slice::<f32>().unwrap();
let result = predictions_slice.iter()
.map(|&x| x as f64)
.collect::<Vec<f64>>();
println!("Successfully generated {} prediction steps", result.len());
Ok(result)
}
pub fn generate_ohlcv_predictions<B: Backend>(
model: &TimeSeriesCnnLstm<B>,
df: &DataFrame,
device: &B::Device,
forecast_horizon: usize,
denormalize: bool,
) -> Result<(Vec<f64>, Vec<f64>, Vec<f64>, Vec<f64>, Vec<f64>)> {
let predictions = forecast(model, df, device, forecast_horizon)?;
if !denormalize {
return Ok((
predictions.clone(), predictions.clone(), predictions.clone(), predictions.clone(), predictions.clone(), ));
}
println!("Warning: Denormalization is not fully implemented yet. Returning normalized predictions.");
Ok((
predictions.clone(), predictions.clone(), predictions.clone(), predictions.clone(), predictions.clone(), ))
}