finance_query/constants/enums/
interval.rs1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
8pub enum Interval {
9 #[serde(rename = "1m")]
11 OneMinute,
12 #[serde(rename = "2m")]
14 TwoMinutes,
15 #[serde(rename = "5m")]
17 FiveMinutes,
18 #[serde(rename = "15m")]
20 FifteenMinutes,
21 #[serde(rename = "30m")]
23 ThirtyMinutes,
24 #[serde(rename = "1h", alias = "60m")]
26 OneHour,
27 #[serde(rename = "90m")]
29 NinetyMinutes,
30 #[serde(rename = "1d")]
32 OneDay,
33 #[serde(rename = "5d")]
35 FiveDays,
36 #[serde(rename = "1wk")]
38 OneWeek,
39 #[serde(rename = "1mo")]
41 OneMonth,
42 #[serde(rename = "3mo")]
44 ThreeMonths,
45}
46
47impl Interval {
48 pub fn as_str(&self) -> &'static str {
50 match self {
51 Interval::OneMinute => "1m",
52 Interval::TwoMinutes => "2m",
53 Interval::FiveMinutes => "5m",
54 Interval::FifteenMinutes => "15m",
55 Interval::ThirtyMinutes => "30m",
56 Interval::OneHour => "1h",
57 Interval::NinetyMinutes => "90m",
58 Interval::OneDay => "1d",
59 Interval::FiveDays => "5d",
60 Interval::OneWeek => "1wk",
61 Interval::OneMonth => "1mo",
62 Interval::ThreeMonths => "3mo",
63 }
64 }
65
66 #[cfg(feature = "backtesting")]
72 pub const fn bars_per_year(self) -> f64 {
73 match self {
74 Interval::OneMinute => 98_280.0,
75 Interval::TwoMinutes => 49_140.0,
76 Interval::FiveMinutes => 19_656.0,
77 Interval::FifteenMinutes => 6_552.0,
78 Interval::ThirtyMinutes => 3_276.0,
79 Interval::OneHour => 1_638.0,
80 Interval::NinetyMinutes => 1_092.0,
81 Interval::OneDay => 252.0,
82 Interval::FiveDays => 50.4,
83 Interval::OneWeek => 52.0,
84 Interval::OneMonth => 12.0,
85 Interval::ThreeMonths => 4.0,
86 }
87 }
88
89 #[cfg(any(feature = "backtesting", feature = "binance", feature = "kraken"))]
94 pub(crate) const fn duration_secs(self) -> i64 {
95 match self {
96 Interval::OneMinute => 60,
97 Interval::TwoMinutes => 120,
98 Interval::FiveMinutes => 300,
99 Interval::FifteenMinutes => 900,
100 Interval::ThirtyMinutes => 1_800,
101 Interval::OneHour => 3_600,
102 Interval::NinetyMinutes => 5_400,
103 Interval::OneDay => 86_400,
104 Interval::FiveDays => 432_000,
105 Interval::OneWeek => 604_800,
106 Interval::OneMonth => 2_592_000,
107 Interval::ThreeMonths => 7_776_000,
108 }
109 }
110}
111
112impl std::fmt::Display for Interval {
113 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
114 f.write_str(self.as_str())
115 }
116}
117
118impl std::str::FromStr for Interval {
119 type Err = ();
120
121 fn from_str(s: &str) -> Result<Self, Self::Err> {
125 match s.trim().to_lowercase().as_str() {
126 "1m" => Ok(Interval::OneMinute),
127 "2m" => Ok(Interval::TwoMinutes),
128 "5m" => Ok(Interval::FiveMinutes),
129 "15m" => Ok(Interval::FifteenMinutes),
130 "30m" => Ok(Interval::ThirtyMinutes),
131 "1h" | "60m" => Ok(Interval::OneHour),
132 "90m" => Ok(Interval::NinetyMinutes),
133 "1d" => Ok(Interval::OneDay),
134 "5d" => Ok(Interval::FiveDays),
135 "1wk" => Ok(Interval::OneWeek),
136 "1mo" => Ok(Interval::OneMonth),
137 "3mo" => Ok(Interval::ThreeMonths),
138 _ => Err(()),
139 }
140 }
141}
142
143#[cfg(test)]
144mod tests {
145 use super::*;
146
147 #[test]
148 fn test_interval_as_str() {
149 assert_eq!(Interval::OneMinute.as_str(), "1m");
150 assert_eq!(Interval::FiveMinutes.as_str(), "5m");
151 assert_eq!(Interval::OneDay.as_str(), "1d");
152 assert_eq!(Interval::OneWeek.as_str(), "1wk");
153 }
154
155 #[test]
156 fn test_interval_from_str_round_trips_as_str() {
157 for interval in [
158 Interval::OneMinute,
159 Interval::TwoMinutes,
160 Interval::FiveMinutes,
161 Interval::FifteenMinutes,
162 Interval::ThirtyMinutes,
163 Interval::OneHour,
164 Interval::NinetyMinutes,
165 Interval::OneDay,
166 Interval::FiveDays,
167 Interval::OneWeek,
168 Interval::OneMonth,
169 Interval::ThreeMonths,
170 ] {
171 assert_eq!(interval.as_str().parse(), Ok(interval));
172 }
173 assert_eq!("1D".parse(), Ok(Interval::OneDay));
174 assert_eq!(" 1d ".parse(), Ok(Interval::OneDay));
175 assert_eq!("bogus".parse::<Interval>(), Err(()));
176 }
177
178 #[cfg(any(feature = "backtesting", feature = "binance", feature = "kraken"))]
179 #[test]
180 fn test_interval_duration_secs() {
181 use super::super::TimeRange;
182
183 assert_eq!(Interval::OneMinute.duration_secs(), 60);
184 assert_eq!(Interval::OneHour.duration_secs(), 3_600);
185 assert_eq!(Interval::OneDay.duration_secs(), 86_400);
186 assert_eq!(Interval::OneWeek.duration_secs(), 604_800);
187 assert_eq!(
189 Interval::OneMonth.duration_secs(),
190 TimeRange::OneMonth.approx_duration_secs()
191 );
192 assert_eq!(
193 Interval::ThreeMonths.duration_secs(),
194 TimeRange::ThreeMonths.approx_duration_secs()
195 );
196 }
197}