jquants_api_client/api/
trading_calendar.rs

1//! Trading Calendar API.
2
3use serde::{Deserialize, Serialize};
4
5use super::{
6    shared::{traits::builder::JQuantsBuilder, types::holiday_division::HolidayDivision},
7    JQuantsApiClient, JQuantsPlanClient,
8};
9
10/// Builder for Trading Calendar API.
11#[derive(Clone, Serialize)]
12pub struct TradingCalendarBuilder {
13    #[serde(skip)]
14    client: JQuantsApiClient,
15
16    /// Holiday division.
17    #[serde(skip_serializing_if = "Option::is_none", rename = "holidaydivision")]
18    holiday_division: Option<HolidayDivision>,
19    /// Starting point of data period (e.g., "20210901" or "2021-09-01")
20    #[serde(skip_serializing_if = "Option::is_none")]
21    from: Option<String>,
22    /// End point of data period (e.g., "20210907" or "2021-09-07")
23    #[serde(skip_serializing_if = "Option::is_none")]
24    to: Option<String>,
25}
26
27impl JQuantsBuilder<TradingCalendarResponse> for TradingCalendarBuilder {
28    async fn send(self) -> Result<TradingCalendarResponse, crate::JQuantsError> {
29        self.send_ref().await
30    }
31
32    async fn send_ref(&self) -> Result<TradingCalendarResponse, crate::JQuantsError> {
33        self.client
34            .inner
35            .get("markets/trading_calendar", self)
36            .await
37    }
38}
39
40impl TradingCalendarBuilder {
41    /// Create a new builder.
42    pub(crate) fn new(client: JQuantsApiClient) -> Self {
43        Self {
44            client,
45            holiday_division: None,
46            from: None,
47            to: None,
48        }
49    }
50
51    /// Set holiday division.
52    pub fn holiday_division(mut self, holiday_division: impl Into<HolidayDivision>) -> Self {
53        self.holiday_division = Some(holiday_division.into());
54        self
55    }
56
57    /// Set starting point of data period (e.g., "20210901" or "2021-09-01")
58    pub fn from(mut self, from: impl Into<String>) -> Self {
59        self.from = Some(from.into());
60        self
61    }
62
63    /// Set end point of data period (e.g., "20210907" or "2021-09-07")
64    pub fn to(mut self, to: impl Into<String>) -> Self {
65        self.to = Some(to.into());
66        self
67    }
68}
69
70/// Builder for Trading Calendar API.
71pub trait TradingCalendarApi: JQuantsPlanClient {
72    /// Get API builder for Trading Calendar.
73    ///
74    /// Use [Trading Calendar (/markets/trading_calendar) API](https://jpx.gitbook.io/j-quants-en/api-reference/trading_calendar)
75    fn get_trading_calendar(&self) -> TradingCalendarBuilder {
76        TradingCalendarBuilder::new(self.get_api_client().clone())
77    }
78}
79
80/// Trading Calendar response.
81///
82/// See: [API Reference](https://jpx.gitbook.io/j-quants-en/api-reference/trading_calendar)
83#[derive(Debug, Clone, PartialEq, Deserialize)]
84pub struct TradingCalendarResponse {
85    /// List of trading calendar data
86    pub trading_calendar: Vec<TradingCalendarItem>,
87}
88
89/// Represents a single trading calendar data.
90#[derive(Debug, Clone, PartialEq, Deserialize)]
91pub struct TradingCalendarItem {
92    /// Trade date (YYYY-MM-DD)
93    #[serde(rename = "Date")]
94    pub date: String,
95
96    /// Holiday division
97    #[serde(rename = "HolidayDivision")]
98    pub holiday_division: HolidayDivision,
99}
100
101#[cfg(test)]
102mod tests {
103    use super::*;
104
105    #[test]
106    fn test_deserialize_trading_calendar_response() {
107        let json = r#"
108            {
109                "trading_calendar": [
110                    {
111                        "Date": "2015-04-01",
112                        "HolidayDivision": "1"
113                    }
114                ]
115            }
116        "#;
117
118        let response: TradingCalendarResponse = serde_json::from_str(json).unwrap();
119        let expected_response = TradingCalendarResponse {
120            trading_calendar: vec![TradingCalendarItem {
121                date: "2015-04-01".to_string(),
122                holiday_division: HolidayDivision::BusinessDay,
123            }],
124        };
125
126        pretty_assertions::assert_eq!(response, expected_response);
127    }
128
129    #[test]
130    fn test_deserialize_trading_calendar_response_multiple_items() {
131        let json = r#"
132            {
133                "trading_calendar": [
134                    {
135                        "Date": "2015-03-25",
136                        "HolidayDivision": "2"
137                    },
138                    {
139                        "Date": "2015-04-01",
140                        "HolidayDivision": "1"
141                    }
142                ]
143            }
144        "#;
145
146        let response: TradingCalendarResponse = serde_json::from_str(json).unwrap();
147        let expected_response = TradingCalendarResponse {
148            trading_calendar: vec![
149                TradingCalendarItem {
150                    date: "2015-03-25".to_string(),
151                    holiday_division: HolidayDivision::HalfDayTrading,
152                },
153                TradingCalendarItem {
154                    date: "2015-04-01".to_string(),
155                    holiday_division: HolidayDivision::BusinessDay,
156                },
157            ],
158        };
159
160        pretty_assertions::assert_eq!(response, expected_response);
161    }
162
163    #[test]
164    fn test_deserialize_trading_calendar_response_no_data() {
165        let json = r#"
166            {
167                "trading_calendar": []
168            }
169        "#;
170
171        let response: TradingCalendarResponse = serde_json::from_str(json).unwrap();
172        let expected_response = TradingCalendarResponse {
173            trading_calendar: vec![],
174        };
175
176        pretty_assertions::assert_eq!(response, expected_response);
177    }
178}