gurufocus_api/
keyratios.rs

1use serde::Deserialize;
2use serde_json::Value;
3
4pub use crate::strnum::FloatOrString;
5
6/// Structure holding all key ratios for a single stock.
7#[derive(Deserialize, Debug)]
8#[serde(deny_unknown_fields)]
9pub struct KeyRatios {
10    #[serde(rename = "Basic")]
11    pub basic: Basic,
12    #[serde(rename = "Fundamental")]
13    pub fundamental: Value,
14    #[serde(rename = "Valuation Ratio")]
15    pub valuation_ratio: Value,
16    #[serde(rename = "Profitability")]
17    pub profitability: Value,
18    #[serde(rename = "Growth")]
19    pub growth: Value,
20    #[serde(rename = "Price")]
21    pub price: Value,
22    #[serde(rename = "Dividends")]
23    pub dividends: Value,
24    #[serde(rename = "Income Statement")]
25    pub income_statement: Option<IncomeStatement>,
26    #[serde(rename = "Valuation")]
27    pub valuation: Option<Valuation>,
28    #[serde(rename = "Quality")]
29    pub quality: Option<Quality>,
30}
31
32#[derive(Deserialize, Debug)]
33#[serde(deny_unknown_fields)]
34pub struct IncomeStatement {
35    #[serde(rename = "Selling, General, & Admin. Expense")]
36    pub selling_general_and_admin_expense: FloatOrString,
37}
38
39#[derive(Deserialize, Debug)]
40#[serde(deny_unknown_fields)]
41pub struct Basic {
42    #[serde(rename = "Price Updated Time")]
43    pub price_updated_time: String,
44    #[serde(rename = "Company")]
45    pub company: String,
46}
47
48#[derive(Deserialize, Debug)]
49#[serde(deny_unknown_fields)]
50pub struct Valuation {
51    #[serde(rename = "Earnings Power Value (EPV)")]
52    pub epv: FloatOrString,
53}
54
55#[derive(Deserialize, Debug)]
56#[serde(deny_unknown_fields)]
57pub struct Quality {
58    #[serde(rename = "Predictability Rank")]
59    pub predictability_rank: FloatOrString,
60}
61
62/// Container for analyst estimates for all periods
63#[derive(Deserialize, Debug)]
64#[serde(deny_unknown_fields)]
65pub struct AnalystEstimates {
66    pub annual: PeriodAnalystEstimate,
67    pub quarterly: PeriodAnalystEstimate,
68}
69
70/// Container for analyst estimates for annual periods
71#[derive(Deserialize, Debug)]
72#[serde(deny_unknown_fields)]
73pub struct PeriodAnalystEstimate {
74    pub long_term_growth_rate_mean: FloatOrString,
75    pub long_term_revenue_growth_rate_mean: FloatOrString,
76    pub date: Vec<String>,
77    pub revenue_estimate: Vec<FloatOrString>,
78    pub eps_nri_estimate: Vec<FloatOrString>,
79    pub per_share_eps_estimate: Vec<FloatOrString>,
80    pub ebit_estimate: Vec<FloatOrString>,
81    pub ebitda_estimate: Vec<FloatOrString>,
82    pub dividend_estimate: Vec<FloatOrString>,
83    pub gross_margin_estimate: Vec<FloatOrString>,
84    pub net_income_estimate: Vec<FloatOrString>,
85    pub pettm_estimate: Vec<FloatOrString>,
86    pub pretax_income_estimate: Vec<FloatOrString>,
87    pub roa_estimate: Vec<FloatOrString>,
88    pub roe_estimate: Vec<FloatOrString>,
89    pub operating_cash_flow_per_share_estimate: Vec<FloatOrString>,
90    pub book_value_per_share_estimate: Option<Vec<FloatOrString>>,
91    pub future_per_share_eps_estimate_growth: Option<FloatOrString>,
92    pub future_eps_nri_estimate_growth: Option<FloatOrString>,
93    pub future_revenue_estimate_growth: Option<FloatOrString>,
94    pub future_ebit_estimate_growth: Option<FloatOrString>,
95    pub future_ebitda_estimate_growth: Option<FloatOrString>,
96    pub future_dividend_estimate_growth: Option<FloatOrString>,
97    pub future_net_income_estimate_growth: Option<FloatOrString>,
98    pub future_pretax_income_estimate_growth: Option<FloatOrString>,
99    pub future_book_value_per_share_estimate_growth: Option<FloatOrString>,
100    pub future_roa_estimate_growth: Option<FloatOrString>,
101    pub future_roe_estimate_growth: Option<FloatOrString>,
102    pub future_gross_margin_estimate_growth: Option<FloatOrString>,
103    pub future_operating_cash_flow_per_share_estimate_growth: Option<FloatOrString>,
104}
105
106#[cfg(test)]
107mod tests {
108    use super::super::*;
109    use super::*;
110    use std::env;
111
112    #[tokio::test]
113    async fn test_key_ratios() {
114        if let Ok(token) = env::var("GURUFOCUS_TOKEN") {
115            if !token.is_empty() {
116                let gf_connect = GuruFocusConnector::new(token);
117
118                // Get key ratios of Berkshire Hathaway
119                let stock = "NYSE:BRK.A";
120                let key_ratios_json = gf_connect.get_key_ratios(stock).await;
121                assert!(key_ratios_json.is_ok());
122
123                let key_ratios = serde_json::from_value::<KeyRatios>(key_ratios_json.unwrap());
124                assert!(key_ratios.is_ok());
125            }
126        }
127    }
128
129    #[tokio::test]
130    async fn test_analyst_estimates() {
131        if let Ok(token) = env::var("GURUFOCUS_TOKEN") {
132            if !token.is_empty() {
133                let gf_connect = GuruFocusConnector::new(token);
134
135                let stock = "NAS:CSCO";
136                let estimates_json = gf_connect.get_analyst_estimate(stock).await;
137                assert!(estimates_json.is_ok());
138
139                let estimates = serde_json::from_value::<AnalystEstimates>(estimates_json.unwrap());
140                assert!(estimates.is_ok());
141            }
142        }
143    }
144}