vtse/vtse-server/src/market/generator.rs

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);
}
}
}