nautilus_architect_ax/common/
parse.rs1pub use nautilus_core::serialization::{
19 deserialize_decimal_or_zero, deserialize_optional_decimal,
20 deserialize_optional_decimal_from_str, deserialize_optional_decimal_or_zero, parse_decimal,
21 parse_optional_decimal,
22};
23use nautilus_model::{data::BarSpecification, enums::BarAggregation};
24
25use super::enums::AxCandleWidth;
26
27pub fn map_bar_spec_to_candle_width(spec: &BarSpecification) -> anyhow::Result<AxCandleWidth> {
33 match spec.step.get() {
34 1 => match spec.aggregation {
35 BarAggregation::Second => Ok(AxCandleWidth::Seconds1),
36 BarAggregation::Minute => Ok(AxCandleWidth::Minutes1),
37 BarAggregation::Hour => Ok(AxCandleWidth::Hours1),
38 BarAggregation::Day => Ok(AxCandleWidth::Days1),
39 _ => anyhow::bail!("Unsupported bar aggregation: {:?}", spec.aggregation),
40 },
41 5 => match spec.aggregation {
42 BarAggregation::Second => Ok(AxCandleWidth::Seconds5),
43 BarAggregation::Minute => Ok(AxCandleWidth::Minutes5),
44 _ => anyhow::bail!(
45 "Unsupported bar step 5 with aggregation {:?}",
46 spec.aggregation
47 ),
48 },
49 15 if spec.aggregation == BarAggregation::Minute => Ok(AxCandleWidth::Minutes15),
50 step => anyhow::bail!(
51 "Unsupported bar step: {step} with aggregation {:?}",
52 spec.aggregation
53 ),
54 }
55}
56
57#[cfg(test)]
58mod tests {
59 use nautilus_model::enums::PriceType;
60 use rstest::rstest;
61
62 use super::*;
63
64 #[rstest]
65 fn test_map_bar_spec_1_second() {
66 let spec = BarSpecification::new(1, BarAggregation::Second, PriceType::Last);
67 let result = map_bar_spec_to_candle_width(&spec);
68 assert!(result.is_ok());
69 assert!(matches!(result.unwrap(), AxCandleWidth::Seconds1));
70 }
71
72 #[rstest]
73 fn test_map_bar_spec_5_second() {
74 let spec = BarSpecification::new(5, BarAggregation::Second, PriceType::Last);
75 let result = map_bar_spec_to_candle_width(&spec);
76 assert!(result.is_ok());
77 assert!(matches!(result.unwrap(), AxCandleWidth::Seconds5));
78 }
79
80 #[rstest]
81 fn test_map_bar_spec_1_minute() {
82 let spec = BarSpecification::new(1, BarAggregation::Minute, PriceType::Last);
83 let result = map_bar_spec_to_candle_width(&spec);
84 assert!(result.is_ok());
85 assert!(matches!(result.unwrap(), AxCandleWidth::Minutes1));
86 }
87
88 #[rstest]
89 fn test_map_bar_spec_5_minute() {
90 let spec = BarSpecification::new(5, BarAggregation::Minute, PriceType::Last);
91 let result = map_bar_spec_to_candle_width(&spec);
92 assert!(result.is_ok());
93 assert!(matches!(result.unwrap(), AxCandleWidth::Minutes5));
94 }
95
96 #[rstest]
97 fn test_map_bar_spec_15_minute() {
98 let spec = BarSpecification::new(15, BarAggregation::Minute, PriceType::Last);
99 let result = map_bar_spec_to_candle_width(&spec);
100 assert!(result.is_ok());
101 assert!(matches!(result.unwrap(), AxCandleWidth::Minutes15));
102 }
103
104 #[rstest]
105 fn test_map_bar_spec_1_hour() {
106 let spec = BarSpecification::new(1, BarAggregation::Hour, PriceType::Last);
107 let result = map_bar_spec_to_candle_width(&spec);
108 assert!(result.is_ok());
109 assert!(matches!(result.unwrap(), AxCandleWidth::Hours1));
110 }
111
112 #[rstest]
113 fn test_map_bar_spec_1_day() {
114 let spec = BarSpecification::new(1, BarAggregation::Day, PriceType::Last);
115 let result = map_bar_spec_to_candle_width(&spec);
116 assert!(result.is_ok());
117 assert!(matches!(result.unwrap(), AxCandleWidth::Days1));
118 }
119
120 #[rstest]
121 fn test_map_bar_spec_unsupported_step() {
122 let spec = BarSpecification::new(3, BarAggregation::Minute, PriceType::Last);
123 let result = map_bar_spec_to_candle_width(&spec);
124 assert!(result.is_err());
125 }
126
127 #[rstest]
128 fn test_map_bar_spec_unsupported_aggregation() {
129 let spec = BarSpecification::new(1, BarAggregation::Tick, PriceType::Last);
130 let result = map_bar_spec_to_candle_width(&spec);
131 assert!(result.is_err());
132 }
133}