use exc_core::types::candle::{Period, PeriodKind};
use std::time::Duration;
use time::{macros::offset, UtcOffset};
const W1: Duration = Duration::from_secs(7 * 24 * 3600);
const D3: Duration = Duration::from_secs(3 * 24 * 3600);
const D2: Duration = Duration::from_secs(2 * 24 * 3600);
const D1: Duration = Duration::from_secs(24 * 3600);
const H12: Duration = Duration::from_secs(12 * 3600);
const H6: Duration = Duration::from_secs(6 * 3600);
const H4: Duration = Duration::from_secs(4 * 3600);
const H2: Duration = Duration::from_secs(2 * 3600);
const H1: Duration = Duration::from_secs(3600);
const M30: Duration = Duration::from_secs(1800);
const M15: Duration = Duration::from_secs(900);
const M5: Duration = Duration::from_secs(300);
const M3: Duration = Duration::from_secs(180);
const M1: Duration = Duration::from_secs(60);
const S1: Duration = Duration::from_secs(1);
const HK: UtcOffset = offset!(+8);
pub fn period_to_bar(period: &Period) -> Option<&'static str> {
let utc_offset = period.utc_offset();
let is_utc = utc_offset.is_utc();
let is_hk = utc_offset == HK;
match period.kind() {
PeriodKind::Year => {
if is_utc {
Some("1Yutc")
} else if is_hk {
Some("1Y")
} else {
None
}
}
PeriodKind::Month => {
if is_utc {
Some("1Mutc")
} else if is_hk {
Some("1M")
} else {
None
}
}
PeriodKind::Duration(dur) => match dur {
W1 => {
if is_utc {
Some("1Wutc")
} else if is_hk {
Some("1W")
} else {
None
}
}
D3 => {
if is_utc {
Some("3Dutc")
} else if is_hk {
Some("3D")
} else {
None
}
}
D2 => {
if is_utc {
Some("2Dutc")
} else if is_hk {
Some("2D")
} else {
None
}
}
D1 => {
if is_utc {
Some("1Dutc")
} else if is_hk {
Some("1D")
} else {
None
}
}
H12 => {
if is_utc {
Some("12Hutc")
} else if is_hk {
Some("12H")
} else {
None
}
}
H6 => {
if is_utc {
Some("6Hutc")
} else if is_hk {
Some("6H")
} else {
None
}
}
H4 => Some("4H"),
H2 => Some("2H"),
H1 => Some("1H"),
M30 => Some("30m"),
M15 => Some("15m"),
M5 => Some("5m"),
M3 => Some("3m"),
M1 => Some("1m"),
S1 => Some("1s"),
_ => None,
},
}
}
pub fn bar_to_period(bar: &str) -> Option<Period> {
match bar {
"1s" => Some(Period::seconds(HK, 1)),
"1m" => Some(Period::minutes(HK, 1)),
"3m" => Some(Period::minutes(HK, 3)),
"5m" => Some(Period::minutes(HK, 5)),
"15m" => Some(Period::minutes(HK, 15)),
"30m" => Some(Period::minutes(HK, 30)),
"1H" => Some(Period::hours(HK, 1)),
"2H" => Some(Period::hours(HK, 2)),
"4H" => Some(Period::hours(HK, 4)),
"6H" => Some(Period::hours(HK, 6)),
"6Hutc" => Some(Period::hours(UtcOffset::UTC, 6)),
"12H" => Some(Period::hours(HK, 12)),
"12Hutc" => Some(Period::hours(UtcOffset::UTC, 12)),
"1D" => Some(Period::day(HK)),
"1Dutc" => Some(Period::day(UtcOffset::UTC)),
"2D" => Some(Period::days(HK, 2)),
"2Dutc" => Some(Period::days(UtcOffset::UTC, 2)),
"3D" => Some(Period::days(HK, 3)),
"3Dutc" => Some(Period::days(UtcOffset::UTC, 3)),
"1W" => Some(Period::weeks(HK, 1)),
"1Wutc" => Some(Period::weeks(UtcOffset::UTC, 1)),
"1M" => Some(Period::month(HK)),
"1Mutc" => Some(Period::month(UtcOffset::UTC)),
"1Y" => Some(Period::year(HK)),
"1Yutc" => Some(Period::year(UtcOffset::UTC)),
_ => None,
}
}
#[cfg(test)]
mod test {
use super::*;
fn test_bar(bar: &str) {
let period = bar_to_period(bar).unwrap_or_else(|| panic!("{bar}"));
let out_bar = period_to_bar(&period).unwrap_or_else(|| panic!("{bar} - {period}"));
assert_eq!(bar, out_bar);
}
fn test_period(period: Period) {
let bar = period_to_bar(&period).unwrap_or_else(|| panic!("{period}"));
let out_period = bar_to_period(bar).unwrap_or_else(|| panic!("{period} - {bar}"));
assert_eq!(period, out_period);
}
#[test]
fn test_all_bar() {
for bar in [
"1s", "1m", "3m", "5m", "15m", "30m", "1H", "2H", "4H", "6H", "6Hutc", "12H", "12Hutc",
"1D", "1Dutc", "2D", "2Dutc", "3D", "3Dutc", "1W", "1Wutc", "1M", "1Mutc", "1Y",
"1Yutc",
] {
test_bar(bar);
}
}
#[test]
fn test_all_period() {
for period in [
W1, D3, D2, D1, H12, H6, H4, H2, H1, M30, M15, M5, M3, M1, S1,
] {
let need_test_utc = period > H4;
let mut period = Period {
offset: HK,
kind: PeriodKind::Duration(period),
};
test_period(period);
if need_test_utc {
period.offset = UtcOffset::UTC;
test_period(period);
}
}
}
}