use super::*;
struct NoAntitheticModel;
impl SimulationModel for NoAntitheticModel {
fn name(&self) -> &'static str {
"NoAntithetic"
}
fn generate_path(
&self,
_rng: &mut MonteCarloRng,
time_horizon: &TimeHorizon,
path_id: usize,
) -> SimulationPath {
let n = time_horizon.n_steps();
SimulationPath::new(
time_horizon.time_points(),
vec![1.0; n + 1],
PathMetadata {
path_id,
seed: 0,
is_antithetic: false,
},
)
}
}
#[test]
fn test_default_antithetic_path_impl() {
let model = NoAntitheticModel;
let mut rng = MonteCarloRng::new(42);
let horizon = TimeHorizon::years(1);
let path = model.generate_antithetic_path(&mut rng, &horizon, 0);
assert_eq!(path.values.len(), horizon.n_steps() + 1);
}
#[test]
fn test_simulate_with_budget_convergence_not_converged() {
let engine = MonteCarloEngine::new(42).with_variance_reduction(VarianceReduction::None);
let model = ConstantGrowthModel {
initial: 100.0,
growth_rate: 0.05,
};
let horizon = TimeHorizon::years(1);
let budget = Budget::Convergence {
patience: 100, min_delta: 0.0, max_simulations: 200,
};
let result = engine.simulate_with_budget(&model, &horizon, &budget);
assert!(result.n_paths() > 0);
}
#[test]
fn test_values_at_time_out_of_bounds() {
let engine = MonteCarloEngine::new(42).with_n_simulations(10);
let model = ConstantGrowthModel {
initial: 100.0,
growth_rate: 0.05,
};
let horizon = TimeHorizon::years(1);
let result = engine.simulate(&model, &horizon);
let vals = result.values_at_time(99999);
assert!(vals.is_empty());
}