use std::sync::Arc;
use crate::adapters::fmp;
use crate::error::Result;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum IntradayInterval {
Min1,
Min5,
Min15,
Min30,
Hour1,
Hour4,
}
impl IntradayInterval {
fn as_str(self) -> &'static str {
match self {
Self::Min1 => "1min",
Self::Min5 => "5min",
Self::Min15 => "15min",
Self::Min30 => "30min",
Self::Hour1 => "1hour",
Self::Hour4 => "4hour",
}
}
}
#[derive(Clone, Debug)]
pub struct FmpHandle {
symbol: Arc<str>,
}
impl FmpHandle {
pub(crate) fn new(symbol: Arc<str>) -> Self {
Self { symbol }
}
pub fn symbol(&self) -> &str {
&self.symbol
}
pub async fn quote(&self) -> Result<Vec<fmp::FmpQuote>> {
fmp::quote(&self.symbol).await
}
pub async fn historical(
&self,
from: Option<&str>,
to: Option<&str>,
) -> Result<fmp::HistoricalPriceResponse> {
let params = fmp::HistoricalPriceParams {
from: from.map(str::to_owned),
to: to.map(str::to_owned),
};
fmp::historical_price_daily(&self.symbol, Some(params)).await
}
pub async fn intraday(
&self,
interval: IntradayInterval,
from: Option<&str>,
to: Option<&str>,
) -> Result<Vec<fmp::IntradayPrice>> {
let params = if from.is_some() || to.is_some() {
Some(fmp::HistoricalPriceParams {
from: from.map(str::to_owned),
to: to.map(str::to_owned),
})
} else {
None
};
fmp::historical_price_intraday(&self.symbol, interval.as_str(), params).await
}
pub async fn income_statement(
&self,
period: fmp::Period,
limit: Option<u32>,
) -> Result<Vec<fmp::IncomeStatement>> {
fmp::income_statement(&self.symbol, period, limit).await
}
pub async fn balance_sheet(
&self,
period: fmp::Period,
limit: Option<u32>,
) -> Result<Vec<fmp::BalanceSheet>> {
fmp::balance_sheet(&self.symbol, period, limit).await
}
pub async fn cash_flow(
&self,
period: fmp::Period,
limit: Option<u32>,
) -> Result<Vec<fmp::CashFlow>> {
fmp::cash_flow(&self.symbol, period, limit).await
}
pub async fn key_metrics(
&self,
period: fmp::Period,
limit: Option<u32>,
) -> Result<Vec<fmp::KeyMetrics>> {
fmp::key_metrics(&self.symbol, period, limit).await
}
pub async fn ratios(
&self,
period: fmp::Period,
limit: Option<u32>,
) -> Result<Vec<fmp::FinancialRatios>> {
fmp::financial_ratios(&self.symbol, period, limit).await
}
pub async fn profile(&self) -> Result<Vec<fmp::CompanyProfile>> {
fmp::company_profile(&self.symbol).await
}
pub async fn news(&self, limit: u32) -> Result<Vec<fmp::StockNews>> {
fmp::stock_news(&self.symbol, limit).await
}
}
#[cfg(test)]
mod tests {
use super::*;
#[allow(dead_code)]
async fn _fmp_method_signatures_compile(h: &FmpHandle) {
let _ = h.quote().await;
let _ = h.historical(None, None).await;
let _ = h.intraday(IntradayInterval::Min1, None, None).await;
let _ = h.income_statement(fmp::Period::Quarter, Some(4)).await;
let _ = h.balance_sheet(fmp::Period::Quarter, Some(4)).await;
let _ = h.cash_flow(fmp::Period::Quarter, Some(4)).await;
let _ = h.key_metrics(fmp::Period::Quarter, Some(4)).await;
let _ = h.ratios(fmp::Period::Quarter, Some(4)).await;
let _ = h.profile().await;
let _ = h.news(10).await;
}
#[test]
fn handle_holds_symbol() {
let h = FmpHandle::new(Arc::from("AAPL"));
assert_eq!(h.symbol(), "AAPL");
}
#[test]
fn handle_clone_is_cheap_arc_clone() {
let h1 = FmpHandle::new(Arc::from("AAPL"));
let h2 = h1.clone();
assert_eq!(h1.symbol(), h2.symbol());
}
}