finance_query/models/fundamentals/
financial_data.rs1use crate::models::format::{Both, Format};
2use finance_query_derive::FormatConvert;
3use serde::{Deserialize, Serialize};
4
5#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, FormatConvert)]
14#[serde(rename_all = "camelCase", bound = "")]
15#[non_exhaustive]
16pub struct FinancialData<F: Format = Both> {
17 #[serde(skip_serializing_if = "Option::is_none")]
19 pub current_price: Option<F::Value<f64>>,
20
21 #[serde(skip_serializing_if = "Option::is_none")]
23 pub current_ratio: Option<F::Value<f64>>,
24
25 #[serde(skip_serializing_if = "Option::is_none")]
27 pub debt_to_equity: Option<F::Value<f64>>,
28
29 #[serde(skip_serializing_if = "Option::is_none")]
31 pub earnings_growth: Option<F::Value<f64>>,
32
33 #[serde(skip_serializing_if = "Option::is_none")]
35 pub ebitda: Option<F::Value<i64>>,
36
37 #[serde(skip_serializing_if = "Option::is_none")]
39 pub ebitda_margins: Option<F::Value<f64>>,
40
41 #[serde(skip_serializing_if = "Option::is_none")]
43 pub financial_currency: Option<String>,
44
45 #[serde(skip_serializing_if = "Option::is_none")]
47 pub free_cashflow: Option<F::Value<i64>>,
48
49 #[serde(skip_serializing_if = "Option::is_none")]
51 pub gross_margins: Option<F::Value<f64>>,
52
53 #[serde(skip_serializing_if = "Option::is_none")]
55 pub gross_profits: Option<F::Value<i64>>,
56
57 #[serde(skip_serializing_if = "Option::is_none")]
59 pub max_age: Option<i64>,
60
61 #[serde(skip_serializing_if = "Option::is_none")]
63 pub number_of_analyst_opinions: Option<F::Value<i64>>,
64
65 #[serde(skip_serializing_if = "Option::is_none")]
67 pub operating_cashflow: Option<F::Value<i64>>,
68
69 #[serde(skip_serializing_if = "Option::is_none")]
71 pub operating_margins: Option<F::Value<f64>>,
72
73 #[serde(skip_serializing_if = "Option::is_none")]
75 pub profit_margins: Option<F::Value<f64>>,
76
77 #[serde(skip_serializing_if = "Option::is_none")]
79 pub quick_ratio: Option<F::Value<f64>>,
80
81 #[serde(skip_serializing_if = "Option::is_none")]
83 pub recommendation_key: Option<String>,
84
85 #[serde(skip_serializing_if = "Option::is_none")]
87 pub recommendation_mean: Option<F::Value<f64>>,
88
89 #[serde(skip_serializing_if = "Option::is_none")]
91 pub return_on_assets: Option<F::Value<f64>>,
92
93 #[serde(skip_serializing_if = "Option::is_none")]
95 pub return_on_equity: Option<F::Value<f64>>,
96
97 #[serde(skip_serializing_if = "Option::is_none")]
99 pub revenue_growth: Option<F::Value<f64>>,
100
101 #[serde(skip_serializing_if = "Option::is_none")]
103 pub revenue_per_share: Option<F::Value<f64>>,
104
105 #[serde(skip_serializing_if = "Option::is_none")]
107 pub target_high_price: Option<F::Value<f64>>,
108
109 #[serde(skip_serializing_if = "Option::is_none")]
111 pub target_low_price: Option<F::Value<f64>>,
112
113 #[serde(skip_serializing_if = "Option::is_none")]
115 pub target_mean_price: Option<F::Value<f64>>,
116
117 #[serde(skip_serializing_if = "Option::is_none")]
119 pub target_median_price: Option<F::Value<f64>>,
120
121 #[serde(skip_serializing_if = "Option::is_none")]
123 pub total_cash: Option<F::Value<i64>>,
124
125 #[serde(skip_serializing_if = "Option::is_none")]
127 pub total_cash_per_share: Option<F::Value<f64>>,
128
129 #[serde(skip_serializing_if = "Option::is_none")]
131 pub total_debt: Option<F::Value<i64>>,
132
133 #[serde(skip_serializing_if = "Option::is_none")]
135 pub total_revenue: Option<F::Value<i64>>,
136}
137
138#[cfg(test)]
139mod tests {
140 use super::*;
141
142 #[test]
143 fn test_deserialize_financial_data() {
144 let json = r#"{
145 "currentPrice": {
146 "fmt": "276.97",
147 "raw": 276.97
148 },
149 "ebitda": {
150 "fmt": "144.75B",
151 "longFmt": "144,748,003,328",
152 "raw": 144748003328
153 },
154 "financialCurrency": "USD",
155 "recommendationKey": "buy"
156 }"#;
157
158 let data: FinancialData = serde_json::from_str(json).unwrap();
159 assert_eq!(
160 data.current_price.as_ref().map(|v| v.raw),
161 Some(Some(276.97))
162 );
163 assert_eq!(
164 data.ebitda.as_ref().map(|v| v.raw),
165 Some(Some(144748003328))
166 );
167 assert_eq!(data.financial_currency.as_deref(), Some("USD"));
168 assert_eq!(data.recommendation_key.as_deref(), Some("buy"));
169 }
170
171 #[test]
172 fn test_into_raw() {
173 let json = r#"{
174 "currentPrice": {"fmt": "276.97", "raw": 276.97},
175 "financialCurrency": "USD",
176 "recommendationKey": "buy"
177 }"#;
178
179 let data: FinancialData = serde_json::from_str(json).unwrap();
180 let raw = data.into_raw();
181 assert_eq!(raw.current_price, Some(276.97));
182 assert_eq!(raw.financial_currency.as_deref(), Some("USD"));
183 assert_eq!(raw.recommendation_key.as_deref(), Some("buy"));
184 }
185
186 #[test]
187 fn test_into_pretty() {
188 let json = r#"{
189 "currentPrice": {"fmt": "276.97", "raw": 276.97},
190 "ebitda": {"fmt": "144.75B", "longFmt": "144,748,003,328", "raw": 144748003328}
191 }"#;
192
193 let data: FinancialData = serde_json::from_str(json).unwrap();
194 let pretty = data.into_pretty();
195 assert_eq!(pretty.current_price.as_deref(), Some("276.97"));
196 assert_eq!(pretty.ebitda.as_deref(), Some("144.75B"));
197 }
198}