finance_query/ticker/
fmp.rs1use std::sync::Arc;
16
17use crate::adapters::fmp;
18use crate::error::Result;
19
20#[derive(Debug, Clone, Copy, PartialEq, Eq)]
22pub enum IntradayInterval {
23 Min1,
25 Min5,
27 Min15,
29 Min30,
31 Hour1,
33 Hour4,
35}
36
37impl IntradayInterval {
38 fn as_str(self) -> &'static str {
39 match self {
40 Self::Min1 => "1min",
41 Self::Min5 => "5min",
42 Self::Min15 => "15min",
43 Self::Min30 => "30min",
44 Self::Hour1 => "1hour",
45 Self::Hour4 => "4hour",
46 }
47 }
48}
49
50#[derive(Clone, Debug)]
52pub struct FmpHandle {
53 symbol: Arc<str>,
54}
55
56impl FmpHandle {
57 pub(crate) fn new(symbol: Arc<str>) -> Self {
58 Self { symbol }
59 }
60
61 pub fn symbol(&self) -> &str {
62 &self.symbol
63 }
64
65 pub async fn quote(&self) -> Result<Vec<fmp::FmpQuote>> {
69 fmp::quote(&self.symbol).await
70 }
71
72 pub async fn historical(
76 &self,
77 from: Option<&str>,
78 to: Option<&str>,
79 ) -> Result<fmp::HistoricalPriceResponse> {
80 let params = fmp::HistoricalPriceParams {
81 from: from.map(str::to_owned),
82 to: to.map(str::to_owned),
83 };
84 fmp::historical_price_daily(&self.symbol, Some(params)).await
85 }
86
87 pub async fn intraday(
91 &self,
92 interval: IntradayInterval,
93 from: Option<&str>,
94 to: Option<&str>,
95 ) -> Result<Vec<fmp::IntradayPrice>> {
96 let params = if from.is_some() || to.is_some() {
97 Some(fmp::HistoricalPriceParams {
98 from: from.map(str::to_owned),
99 to: to.map(str::to_owned),
100 })
101 } else {
102 None
103 };
104 fmp::historical_price_intraday(&self.symbol, interval.as_str(), params).await
105 }
106
107 pub async fn income_statement(
111 &self,
112 period: fmp::Period,
113 limit: Option<u32>,
114 ) -> Result<Vec<fmp::IncomeStatement>> {
115 fmp::income_statement(&self.symbol, period, limit).await
116 }
117
118 pub async fn balance_sheet(
122 &self,
123 period: fmp::Period,
124 limit: Option<u32>,
125 ) -> Result<Vec<fmp::BalanceSheet>> {
126 fmp::balance_sheet(&self.symbol, period, limit).await
127 }
128
129 pub async fn cash_flow(
133 &self,
134 period: fmp::Period,
135 limit: Option<u32>,
136 ) -> Result<Vec<fmp::CashFlow>> {
137 fmp::cash_flow(&self.symbol, period, limit).await
138 }
139
140 pub async fn key_metrics(
144 &self,
145 period: fmp::Period,
146 limit: Option<u32>,
147 ) -> Result<Vec<fmp::KeyMetrics>> {
148 fmp::key_metrics(&self.symbol, period, limit).await
149 }
150
151 pub async fn ratios(
155 &self,
156 period: fmp::Period,
157 limit: Option<u32>,
158 ) -> Result<Vec<fmp::FinancialRatios>> {
159 fmp::financial_ratios(&self.symbol, period, limit).await
160 }
161
162 pub async fn profile(&self) -> Result<Vec<fmp::CompanyProfile>> {
166 fmp::company_profile(&self.symbol).await
167 }
168
169 pub async fn news(&self, limit: u32) -> Result<Vec<fmp::StockNews>> {
173 fmp::stock_news(&self.symbol, limit).await
174 }
175}
176
177#[cfg(test)]
178mod tests {
179 use super::*;
180
181 #[allow(dead_code)]
185 async fn _fmp_method_signatures_compile(h: &FmpHandle) {
186 let _ = h.quote().await;
187 let _ = h.historical(None, None).await;
188 let _ = h.intraday(IntradayInterval::Min1, None, None).await;
189 let _ = h.income_statement(fmp::Period::Quarter, Some(4)).await;
190 let _ = h.balance_sheet(fmp::Period::Quarter, Some(4)).await;
191 let _ = h.cash_flow(fmp::Period::Quarter, Some(4)).await;
192 let _ = h.key_metrics(fmp::Period::Quarter, Some(4)).await;
193 let _ = h.ratios(fmp::Period::Quarter, Some(4)).await;
194 let _ = h.profile().await;
195 let _ = h.news(10).await;
196 }
197
198 #[test]
199 fn handle_holds_symbol() {
200 let h = FmpHandle::new(Arc::from("AAPL"));
201 assert_eq!(h.symbol(), "AAPL");
202 }
203
204 #[test]
205 fn handle_clone_is_cheap_arc_clone() {
206 let h1 = FmpHandle::new(Arc::from("AAPL"));
207 let h2 = h1.clone();
208 assert_eq!(h1.symbol(), h2.symbol());
209 }
210}