jquants_api_client/api/
morning_session_stock_prices.rs1use serde::{Deserialize, Serialize};
4
5use super::{
6 shared::traits::{
7 builder::JQuantsBuilder,
8 pagination::{HasPaginationKey, MergePage, Paginatable},
9 },
10 JQuantsApiClient, JQuantsPlanClient,
11};
12
13#[derive(Clone, Serialize)]
17pub struct MorningSessionStockPricesApiBuilder {
18 #[serde(skip)]
19 client: JQuantsApiClient,
20
21 #[serde(skip_serializing_if = "Option::is_none")]
23 code: Option<String>,
24
25 #[serde(skip_serializing_if = "Option::is_none")]
27 pagination_key: Option<String>,
28}
29
30impl JQuantsBuilder<MorningSessionStockPricesResponse> for MorningSessionStockPricesApiBuilder {
31 async fn send(self) -> Result<MorningSessionStockPricesResponse, crate::JQuantsError> {
32 self.send_ref().await
33 }
34
35 async fn send_ref(&self) -> Result<MorningSessionStockPricesResponse, crate::JQuantsError> {
36 self.client.inner.get("prices/prices_am", &self).await
37 }
38}
39
40impl Paginatable<MorningSessionStockPricesResponse> for MorningSessionStockPricesApiBuilder {
41 fn pagination_key(mut self, pagination_key: impl Into<String>) -> Self {
42 self.pagination_key = Some(pagination_key.into());
43 self
44 }
45}
46
47impl MorningSessionStockPricesApiBuilder {
48 pub(crate) fn new(client: JQuantsApiClient) -> Self {
49 Self {
50 client,
51 code: None,
52 pagination_key: None,
53 }
54 }
55
56 pub fn code(mut self, code: impl Into<String>) -> Self {
58 self.code = Some(code.into());
59 self
60 }
61}
62
63pub trait MorningSessionStockPricesApi: JQuantsPlanClient {
65 fn morning_session_stock_prices(&self) -> MorningSessionStockPricesApiBuilder {
67 MorningSessionStockPricesApiBuilder::new(self.get_api_client().clone())
68 }
69}
70
71#[derive(Debug, Clone, PartialEq, Deserialize)]
75pub struct MorningSessionStockPricesResponse {
76 prices_am: Vec<MorningStockPriceItem>,
78 pagination_key: Option<String>,
80}
81impl HasPaginationKey for MorningSessionStockPricesResponse {
82 fn get_pagination_key(&self) -> Option<&str> {
83 self.pagination_key.as_deref()
84 }
85}
86impl MergePage for MorningSessionStockPricesResponse {
87 fn merge_page(
88 page: Result<Vec<Self>, crate::JQuantsError>,
89 ) -> Result<Self, crate::JQuantsError> {
90 let mut page = page?;
91 let mut merged = page.pop().unwrap();
92 for p in page {
93 merged.prices_am.extend(p.prices_am);
94 }
95 merged.pagination_key = None;
96
97 Ok(merged)
98 }
99}
100
101#[derive(Debug, Clone, PartialEq, Deserialize)]
103pub struct MorningStockPriceItem {
104 #[serde(rename = "Date")]
106 pub date: String,
107 #[serde(rename = "Code")]
109 pub code: String,
110 #[serde(rename = "MorningOpen")]
112 pub morning_open: Option<f64>,
113 #[serde(rename = "MorningHigh")]
115 pub morning_high: Option<f64>,
116 #[serde(rename = "MorningLow")]
118 pub morning_low: Option<f64>,
119 #[serde(rename = "MorningClose")]
121 pub morning_close: Option<f64>,
122 #[serde(rename = "MorningVolume")]
124 pub morning_volume: Option<f64>,
125 #[serde(rename = "MorningTurnoverValue")]
127 pub morning_turnover_value: Option<f64>,
128}
129
130#[cfg(test)]
131mod tests {
132 use super::*;
133
134 #[test]
135 fn test_deserialize_morning_session_stock_prices_response() {
136 let json = r#"
137 {
138 "prices_am": [
139 {
140 "Date": "2023-03-20",
141 "Code": "39400",
142 "MorningOpen": 232.0,
143 "MorningHigh": 244.0,
144 "MorningLow": 232.0,
145 "MorningClose": 240.0,
146 "MorningVolume": 52600.0,
147 "MorningTurnoverValue": 12518800.0
148 }
149 ],
150 "pagination_key": "value1.value2."
151 }
152 "#;
153 let response: MorningSessionStockPricesResponse = serde_json::from_str(json).unwrap();
154 let expected_response: MorningSessionStockPricesResponse =
155 MorningSessionStockPricesResponse {
156 prices_am: vec![MorningStockPriceItem {
157 date: "2023-03-20".to_string(),
158 code: "39400".to_string(),
159 morning_open: Some(232.0),
160 morning_high: Some(244.0),
161 morning_low: Some(232.0),
162 morning_close: Some(240.0),
163 morning_volume: Some(52600.0),
164 morning_turnover_value: Some(12518800.0),
165 }],
166 pagination_key: Some("value1.value2.".to_string()),
167 };
168
169 pretty_assertions::assert_eq!(response, expected_response);
170 }
171
172 #[test]
173 fn test_deserialize_morning_session_stock_prices_response_no_data() {
174 let json = r#"
175 {
176 "prices_am": [
177 {
178 "Date": "2023-03-20",
179 "Code": "39400",
180 "MorningOpen": null,
181 "MorningHigh": null,
182 "MorningLow": null,
183 "MorningClose": null,
184 "MorningVolume": null,
185 "MorningTurnoverValue": null
186 }
187 ],
188 "pagination_key": "value1.value2."
189 }
190 "#;
191 let response: MorningSessionStockPricesResponse = serde_json::from_str(json).unwrap();
192 let expected_response: MorningSessionStockPricesResponse =
193 MorningSessionStockPricesResponse {
194 prices_am: vec![MorningStockPriceItem {
195 date: "2023-03-20".to_string(),
196 code: "39400".to_string(),
197 morning_open: None,
198 morning_high: None,
199 morning_low: None,
200 morning_close: None,
201 morning_volume: None,
202 morning_turnover_value: None,
203 }],
204 pagination_key: Some("value1.value2.".to_string()),
205 };
206
207 pretty_assertions::assert_eq!(response, expected_response);
208 }
209}