use crate::interbar_math::EntropyCache;
use parking_lot::RwLock;
use std::sync::Arc;
use std::sync::LazyLock;
pub const GLOBAL_ENTROPY_CACHE_CAPACITY: u64 = 1024;
pub static GLOBAL_ENTROPY_CACHE: LazyLock<Arc<RwLock<EntropyCache>>> = LazyLock::new(|| {
Arc::new(RwLock::new(EntropyCache::with_capacity(
GLOBAL_ENTROPY_CACHE_CAPACITY,
)))
});
pub fn get_global_entropy_cache() -> Arc<RwLock<EntropyCache>> {
GLOBAL_ENTROPY_CACHE.clone()
}
pub fn create_local_entropy_cache() -> Arc<RwLock<EntropyCache>> {
Arc::new(RwLock::new(EntropyCache::new()))
}
pub fn warm_up_entropy_cache() {
let cache = get_global_entropy_cache();
let Some(mut cache_guard) = cache.try_write() else {
return; };
let base_price = 100.0;
for i in 0..30 {
let mut prices = Vec::with_capacity(100);
let variation = base_price * 0.005; for j in 0..100 {
let offset = (((i as f64 * 7.0 + j as f64 * 3.0) % 100.0) - 50.0) / 1000.0;
prices.push(base_price + variation * offset);
}
let entropy =
crate::interbar_math::compute_entropy_adaptive_cached(&prices, &mut cache_guard);
if entropy.is_finite() {
cache_guard.insert(&prices, entropy);
}
}
for i in 0..25 {
let mut prices = Vec::with_capacity(150);
let variation = base_price * 0.01; let trend = (i as f64 / 25.0) - 0.5; for j in 0..150 {
let random_component = (((i as f64 * 11.0 + j as f64 * 7.0) % 100.0) - 50.0) / 100.0;
let trend_component = trend * (j as f64 / 150.0);
prices.push(base_price + variation * (random_component + trend_component * 0.5));
}
let entropy =
crate::interbar_math::compute_entropy_adaptive_cached(&prices, &mut cache_guard);
if entropy.is_finite() {
cache_guard.insert(&prices, entropy);
}
}
for i in 0..20 {
let mut prices = Vec::with_capacity(200);
let variation = base_price * (0.015 + 0.005 * ((i as f64 / 20.0) - 0.5) * 2.0); for j in 0..200 {
let phase = ((i as f64 * 13.0 + j as f64 * 5.0) % 100.0) / 100.0;
let oscillation = (phase * std::f64::consts::TAU).sin();
prices.push(base_price + variation * oscillation);
}
let entropy =
crate::interbar_math::compute_entropy_adaptive_cached(&prices, &mut cache_guard);
if entropy.is_finite() {
cache_guard.insert(&prices, entropy);
}
}
for i in 0..15 {
let mut prices = Vec::with_capacity(250);
let trend_strength = 0.01 * ((i as f64 / 15.0) - 0.5) * 2.0; let mut current_price = base_price;
for j in 0..250 {
let noise = (((i as f64 * 17.0 + j as f64 * 11.0) % 100.0) - 50.0) / 500.0;
current_price += trend_strength + noise;
prices.push(current_price);
}
let entropy =
crate::interbar_math::compute_entropy_adaptive_cached(&prices, &mut cache_guard);
if entropy.is_finite() {
cache_guard.insert(&prices, entropy);
}
}
for i in 0..10 {
let mut prices = Vec::with_capacity(300);
let gap_size = base_price * (0.01 + 0.005 * (i as f64 / 10.0)); let mut current_price = base_price;
for j in 0..50 {
let move_progress = j as f64 / 50.0;
current_price = base_price + gap_size * move_progress;
prices.push(current_price);
}
for j in 50..300 {
let consolidation = (((i as f64 * 19.0 + j as f64 * 3.0) % 100.0) - 50.0) / 1000.0;
prices.push(current_price + gap_size * consolidation * 0.5);
}
let entropy =
crate::interbar_math::compute_entropy_adaptive_cached(&prices, &mut cache_guard);
if entropy.is_finite() {
cache_guard.insert(&prices, entropy);
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_global_cache_singleton() {
let cache1 = get_global_entropy_cache();
let cache2 = get_global_entropy_cache();
assert_eq!(Arc::strong_count(&cache1), Arc::strong_count(&cache2));
}
#[test]
fn test_global_cache_thread_safe() {
use std::thread;
let cache = get_global_entropy_cache();
let mut handles = vec![];
for i in 0..4 {
let cache_clone = cache.clone();
let handle = thread::spawn(move || {
let _guard = cache_clone.write();
i
});
handles.push(handle);
}
for handle in handles {
let _ = handle.join();
}
}
#[test]
fn test_local_cache_independence() {
let local1 = create_local_entropy_cache();
let local2 = create_local_entropy_cache();
let ptr1 = Arc::as_ptr(&local1);
let ptr2 = Arc::as_ptr(&local2);
assert_ne!(
ptr1, ptr2,
"Local caches should point to different EntropyCache instances"
);
}
#[test]
fn test_warm_up_entropy_cache_completes() {
warm_up_entropy_cache();
let cache = get_global_entropy_cache();
let guard = cache.read();
let sample_prices = vec![100.0, 100.5, 100.2, 100.8, 100.1];
let _ = guard.get(&sample_prices); }
#[test]
fn test_global_cache_capacity() {
assert_eq!(GLOBAL_ENTROPY_CACHE_CAPACITY, 1024);
}
}