use chrono::{TimeZone, Utc};
use chrono_ta::indicators::{SimpleMovingAverage, StandardDeviation};
use chrono_ta::Next;
use std::time::Duration;
#[test]
fn test_daily_ohlc_no_replacement() {
let mut sma = SimpleMovingAverage::new(Duration::from_secs(3 * 86400)).unwrap();
let day1_open = Utc.with_ymd_and_hms(2024, 1, 1, 9, 30, 0).unwrap();
let result1 = sma.next((day1_open, 100.0));
assert_eq!(result1, 100.0);
let day1_close = Utc.with_ymd_and_hms(2024, 1, 1, 16, 0, 0).unwrap();
let result2 = sma.next((day1_close, 105.0));
assert_eq!(result2, 102.5);
let day2_open = Utc.with_ymd_and_hms(2024, 1, 2, 9, 30, 0).unwrap();
let result3 = sma.next((day2_open, 110.0));
assert_eq!(result3, 105.0);
let day2_close = Utc.with_ymd_and_hms(2024, 1, 2, 16, 0, 0).unwrap();
let result4 = sma.next((day2_close, 108.0));
assert_eq!(result4, 105.75);
}
#[test]
fn test_intraday_replacement_within_bucket() {
let mut sma = SimpleMovingAverage::new(Duration::from_secs(15 * 60)).unwrap();
let base_time = Utc.with_ymd_and_hms(2024, 1, 1, 9, 30, 0).unwrap();
let result1 = sma.next((base_time, 100.0));
assert_eq!(result1, 100.0);
let result2 = sma.next((base_time + chrono::Duration::minutes(5), 101.0));
assert_eq!(result2, 100.5);
let result3 = sma.next((base_time + chrono::Duration::minutes(10), 102.0));
assert_eq!(result3, 101.0);
let result4 = sma.next((base_time + chrono::Duration::minutes(11), 103.0));
assert_eq!(result4, 101.5);
let result5 = sma.next((base_time + chrono::Duration::minutes(15), 104.0));
assert_eq!(result5, 102.5); }
#[test]
fn test_standard_deviation_with_replacement() {
let mut sd = StandardDeviation::new(Duration::from_secs(3600)).unwrap();
let base_time = Utc.with_ymd_and_hms(2024, 1, 1, 10, 0, 0).unwrap();
sd.next((base_time, 10.0));
sd.next((base_time + chrono::Duration::minutes(1), 12.0));
sd.next((base_time + chrono::Duration::minutes(2), 11.0));
let _result1 = sd.next((
base_time + chrono::Duration::minutes(2) + chrono::Duration::seconds(30),
11.5,
));
let result2 = sd.next((base_time + chrono::Duration::minutes(3), 10.5));
assert!(result2 > 0.0); }
#[test]
fn test_transition_from_warmup_to_live() {
let mut sma = SimpleMovingAverage::new(Duration::from_secs(2 * 86400)).unwrap();
let day1_open = Utc.with_ymd_and_hms(2024, 1, 1, 9, 30, 0).unwrap();
sma.next((day1_open, 100.0));
let day1_close = Utc.with_ymd_and_hms(2024, 1, 1, 16, 0, 0).unwrap();
sma.next((day1_close, 102.0));
let day2_open = Utc.with_ymd_and_hms(2024, 1, 2, 9, 30, 0).unwrap();
let warmup_result = sma.next((day2_open, 104.0));
assert_eq!(warmup_result, 102.0);
let day2_mid = Utc.with_ymd_and_hms(2024, 1, 2, 10, 0, 0).unwrap();
let result = sma.next((day2_mid, 105.0));
assert_eq!(result, (100.0 + 102.0 + 105.0) / 3.0); }
#[test]
fn test_high_frequency_tick_data() {
let mut sma = SimpleMovingAverage::new(Duration::from_secs(5)).unwrap();
let base_time = Utc.with_ymd_and_hms(2024, 1, 1, 10, 0, 0).unwrap();
sma.next((base_time, 100.0));
sma.next((base_time + chrono::Duration::milliseconds(100), 100.1));
sma.next((base_time + chrono::Duration::milliseconds(200), 100.2));
sma.next((base_time + chrono::Duration::milliseconds(300), 100.3));
let result = sma.next((base_time + chrono::Duration::milliseconds(400), 100.4));
assert_eq!(result, 100.4); }
#[test]
fn test_minute_bar_replacement() {
let mut sma = SimpleMovingAverage::new(Duration::from_secs(5 * 60)).unwrap();
let base_time = Utc.with_ymd_and_hms(2024, 1, 1, 10, 0, 0).unwrap();
sma.next((base_time, 100.0));
let _result1 = sma.next((base_time + chrono::Duration::seconds(30), 100.5));
let _result2 = sma.next((base_time + chrono::Duration::minutes(1), 101.0));
let result3 = sma.next((base_time + chrono::Duration::minutes(2), 102.0));
assert!(result3 >= 100.0 && result3 <= 102.0);
}
#[test]
fn test_weekly_data_detection() {
let mut sma = SimpleMovingAverage::new(Duration::from_secs(21 * 86400)).unwrap();
let week1 = Utc.with_ymd_and_hms(2024, 1, 1, 0, 0, 0).unwrap();
let week2 = Utc.with_ymd_and_hms(2024, 1, 8, 0, 0, 0).unwrap();
let week3 = Utc.with_ymd_and_hms(2024, 1, 15, 0, 0, 0).unwrap();
let result1 = sma.next((week1, 100.0));
assert_eq!(result1, 100.0);
let result2 = sma.next((week2, 110.0));
assert_eq!(result2, 105.0);
let result3 = sma.next((week3, 120.0));
assert_eq!(result3, 110.0);
let week4 = Utc.with_ymd_and_hms(2024, 1, 22, 0, 0, 0).unwrap();
let result4 = sma.next((week4, 115.0));
assert_eq!(result4, 115.0); }