use rand::{distributions::Uniform, prelude::Distribution}; use rand::{rngs::StdRng, SeedableRng}; use rust_decimal::Decimal; #[derive(Copy, Clone, PartialEq, PartialOrd, Debug)] pub(super) struct MarketModifier(Decimal); impl MarketModifier { pub(super) fn modifier(&self) -> Decimal { self.0 } } #[derive(Clone, Debug)] pub(super) struct MarketMultiplier { rng: StdRng, sample_range: Uniform, volatility: Decimal, old_price: MarketModifier, buffer: Vec, } impl MarketMultiplier { pub(super) fn new(volatility: Decimal, initial_value: Decimal) -> Self { Self { rng: StdRng::from_entropy(), sample_range: Uniform::new_inclusive(-50, 50), volatility, old_price: MarketModifier(initial_value), buffer: vec![], } } } impl Iterator for MarketMultiplier { type Item = MarketModifier; fn next(&mut self) -> Option { // Algorithm from https://stackoverflow.com/a/8597889 let rng_multiplier = self.sample_range.sample(&mut self.rng); let delta = Decimal::new(2, 0) * self.volatility * Decimal::new(rng_multiplier, 2); self.old_price.0 += self.old_price.0 * delta; Some(self.old_price) } } impl MarketMultiplier { pub(super) fn next_n(&mut self, n: usize) -> Vec { self.ensure_buffer_capacity(n); let mut ret = self.buffer.split_off(n); std::mem::swap(&mut ret, &mut self.buffer); ret } pub(super) fn peek_n(&mut self, n: usize) -> &[MarketModifier] { self.ensure_buffer_capacity(n); &self.buffer[..n] } fn ensure_buffer_capacity(&mut self, n: usize) { for _ in 0..(n - self.buffer.len()) { let next_val = self.next().unwrap(); self.buffer.push(next_val); } } }