67 lines
1.8 KiB
Rust
67 lines
1.8 KiB
Rust
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<i64>,
|
|
volatility: Decimal,
|
|
old_price: MarketModifier,
|
|
buffer: Vec<MarketModifier>,
|
|
}
|
|
|
|
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<Self::Item> {
|
|
// 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<MarketModifier> {
|
|
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);
|
|
}
|
|
}
|
|
}
|