From 95a502461f9efde94fd7afdec3dbcce06dd9927f Mon Sep 17 00:00:00 2001 From: Mark Beinker Date: Sat, 27 Jan 2024 21:51:03 +0100 Subject: [PATCH] fix blocking and formatting --- examples/get_fxrates.rs | 4 +- examples/get_quote_history.rs | 4 +- examples/get_quote_period_interval.rs | 2 +- src/async_impl.rs | 5 +- src/blocking_impl.rs | 21 ++++++- src/lib.rs | 12 ++-- src/quote_summary.rs | 7 ++- src/quotes.rs | 85 +++++++++++++-------------- src/search_result.rs | 42 +++++++------ 9 files changed, 97 insertions(+), 85 deletions(-) diff --git a/examples/get_fxrates.rs b/examples/get_fxrates.rs index 1cf49c9..4663cab 100644 --- a/examples/get_fxrates.rs +++ b/examples/get_fxrates.rs @@ -6,7 +6,7 @@ use yahoo_finance_api as yahoo; fn get_history() -> Result { let provider = yahoo::YahooConnector::new(); let start = time::OffsetDateTime::UNIX_EPOCH; - let end= time::OffsetDateTime::now_utc(); + let end = time::OffsetDateTime::now_utc(); tokio_test::block_on(provider.get_quote_history("EUR=x", start, end)) } @@ -14,7 +14,7 @@ fn get_history() -> Result { fn get_history() -> Result { let provider = yahoo::YahooConnector::new(); let start = time::OffsetDateTime::UNIX_EPOCH; - let end= time::OffsetDateTime::now_utc(); + let end = time::OffsetDateTime::now_utc(); provider.get_quote_history("EUR=x", start, end) } diff --git a/examples/get_quote_history.rs b/examples/get_quote_history.rs index 07de15d..0466077 100644 --- a/examples/get_quote_history.rs +++ b/examples/get_quote_history.rs @@ -6,7 +6,7 @@ use yahoo_finance_api as yahoo; fn get_history() -> Result { let provider = yahoo::YahooConnector::new(); let start = time::OffsetDateTime::UNIX_EPOCH; - let end= time::OffsetDateTime::now_utc(); + let end = time::OffsetDateTime::now_utc(); tokio_test::block_on(provider.get_quote_history("VTI", start, end)) } @@ -14,7 +14,7 @@ fn get_history() -> Result { fn get_history() -> Result { let provider = yahoo::YahooConnector::new(); let start = time::OffsetDateTime::UNIX_EPOCH; - let end= time::OffsetDateTime::now_utc(); + let end = time::OffsetDateTime::now_utc(); provider.get_quote_history("VTI", start, end) } diff --git a/examples/get_quote_period_interval.rs b/examples/get_quote_period_interval.rs index 42a7804..36bb367 100644 --- a/examples/get_quote_period_interval.rs +++ b/examples/get_quote_period_interval.rs @@ -11,7 +11,7 @@ fn get_history() -> Result { #[cfg(feature = "blocking")] fn get_history() -> Result { let provider = yahoo::YahooConnector::new(); - provider.get_quote_history_interval("AAPL", "1d", "1m", true) + provider.get_quote_period_interval("AAPL", "1d", "1m", true) } fn main() { diff --git a/src/async_impl.rs b/src/async_impl.rs index e9c474f..337082e 100644 --- a/src/async_impl.rs +++ b/src/async_impl.rs @@ -57,13 +57,13 @@ impl YahooConnector { YResponse::from_json(self.send_request(&url).await?) } - /// Retrieve the quote history for the given ticker form date start to end (inclusive), if available; specifying the interval of the ticker. + /// Retrieve the quote history for the given ticker for a given period and ticker interval and optionally before and after regular trading hours pub async fn get_quote_period_interval( &self, ticker: &str, period: &str, interval: &str, - prepost: bool + prepost: bool, ) -> Result { let url = format!( YCHART_PERIOD_INTERVAL_QUERY!(), @@ -73,7 +73,6 @@ impl YahooConnector { interval = interval, prepost = prepost, ); - println!("result: {:?}", self.send_request(&url).await?); YResponse::from_json(self.send_request(&url).await?) } diff --git a/src/blocking_impl.rs b/src/blocking_impl.rs index afcaaaf..14f5d76 100644 --- a/src/blocking_impl.rs +++ b/src/blocking_impl.rs @@ -40,7 +40,6 @@ impl YahooConnector { start: OffsetDateTime, end: OffsetDateTime, interval: &str, - prepost: bool, ) -> Result { let url = format!( YCHART_PERIOD_QUERY!(), @@ -49,7 +48,25 @@ impl YahooConnector { start = start.unix_timestamp(), end = end.unix_timestamp(), interval = interval, - prepost = prepost + ); + YResponse::from_json(self.send_request(&url)?) + } + + /// Retrieve the quote history for the given ticker for a given period and ticker interval and optionally before and after regular trading hours + pub fn get_quote_period_interval( + &self, + ticker: &str, + period: &str, + interval: &str, + prepost: bool, + ) -> Result { + let url = format!( + YCHART_PERIOD_INTERVAL_QUERY!(), + url = self.url, + symbol = ticker, + period = period, + interval = interval, + prepost = prepost, ); YResponse::from_json(self.send_request(&url)?) } diff --git a/src/lib.rs b/src/lib.rs index d123290..68849d2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -159,9 +159,7 @@ fn main() { " )] -use std::{ - time::Duration, -}; +use std::time::Duration; use time::OffsetDateTime; #[cfg(feature = "blocking")] @@ -173,15 +171,15 @@ use reqwest::{Client, ClientBuilder}; // re-export time crate pub use time; -mod quotes; mod quote_summary; +mod quotes; mod search_result; mod yahoo_error; +pub use quote_summary::{YQuoteResponse, YQuoteSummary}; pub use quotes::{ - AdjClose, Dividend, CapitalGain, PeriodInfo, Quote, QuoteBlock, QuoteList, Split, TradingPeriods, YChart, - YMetaData, YQuoteBlock, YResponse, + AdjClose, CapitalGain, Dividend, PeriodInfo, Quote, QuoteBlock, QuoteList, Split, + TradingPeriods, YChart, YMetaData, YQuoteBlock, YResponse, }; -pub use quote_summary::{YQuoteResponse, YQuoteSummary}; pub use search_result::{ YNewsItem, YOptionResult, YOptionResults, YQuoteItem, YQuoteItemOpt, YSearchResult, YSearchResultOpt, diff --git a/src/quote_summary.rs b/src/quote_summary.rs index 1977f2b..afec778 100644 --- a/src/quote_summary.rs +++ b/src/quote_summary.rs @@ -12,8 +12,9 @@ impl YQuoteResponse { pub fn from_json(json: serde_json::Value) -> Result { Ok(serde_json::from_value( json.get("quoteResponse") - .ok_or(YahooError::DataInconsistency)? - .to_owned())?) + .ok_or(YahooError::DataInconsistency)? + .to_owned(), + )?) } } @@ -104,4 +105,4 @@ pub struct YQuoteSummary { pub to_currency: Option, pub coin_market_cap_link: Option, pub start_date: Option, -} \ No newline at end of file +} diff --git a/src/quotes.rs b/src/quotes.rs index 6e415a0..bbeed44 100644 --- a/src/quotes.rs +++ b/src/quotes.rs @@ -1,10 +1,8 @@ -use std::{ - collections::HashMap, - fmt -}; +use std::{collections::HashMap, fmt}; -use serde::{Deserialize, - de::{self, Deserializer, Visitor, SeqAccess, MapAccess} +use serde::{ + de::{self, Deserializer, MapAccess, SeqAccess, Visitor}, + Deserialize, }; use super::YahooError; @@ -75,7 +73,7 @@ impl YResponse { pub fn metadata(&self) -> Result { self.check_consistency()?; let stock = &self.chart.result[0]; - Ok( stock.meta.to_owned()) + Ok(stock.meta.to_owned()) } /// This method retrieves information about the splits that might have @@ -181,20 +179,23 @@ pub struct YMetaData { #[derive(Default, Debug, Clone, PartialEq, Eq)] pub struct TradingPeriods { - pub pre: Option>>, - pub regular: Option>>, - pub post: Option>>, + pub pre: Option>>, + pub regular: Option>>, + pub post: Option>>, } -impl<'de> Deserialize<'de> for TradingPeriods -{ +impl<'de> Deserialize<'de> for TradingPeriods { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { #[derive(Deserialize)] #[serde(field_identifier, rename_all = "lowercase")] - enum Field { Regular, Pre, Post } + enum Field { + Regular, + Pre, + Post, + } struct TradingPeriodsVisitor; @@ -209,12 +210,13 @@ impl<'de> Deserialize<'de> for TradingPeriods where V: SeqAccess<'de>, { - let regular: Vec = seq.next_element()? + let regular: Vec = seq + .next_element()? .ok_or_else(|| de::Error::invalid_length(0, &self))?; - Ok(TradingPeriods{ + Ok(TradingPeriods { pre: None, regular: Some(vec![regular]), - post: None + post: None, }) } @@ -232,27 +234,22 @@ impl<'de> Deserialize<'de> for TradingPeriods return Err(de::Error::duplicate_field("pre")); } pre = Some(map.next_value()?); - }, + } Field::Post => { if post.is_some() { return Err(de::Error::duplicate_field("post")); } post = Some(map.next_value()?); - }, + } Field::Regular => { if regular.is_some() { return Err(de::Error::duplicate_field("regular")); } regular = Some(map.next_value()?); - }, - + } } } - Ok(TradingPeriods{ - pre, - post, - regular, - }) + Ok(TradingPeriods { pre, post, regular }) } } @@ -361,14 +358,14 @@ pub struct Dividend { pub struct CapitalGain { /// This is the amount of capital gain distributed by the fund pub amount: f64, - /// This is the recorded date of the capital gain + /// This is the recorded date of the capital gain pub date: u64, } #[cfg(test)] mod tests { use super::*; - + #[test] fn test_deserialize_period_info() { let period_info_json = r#" @@ -379,7 +376,7 @@ mod tests { "gmtoffset": -18000 } "#; - let period_info_expected = PeriodInfo{ + let period_info_expected = PeriodInfo { timezone: "EST".to_string(), start: 1705501800, end: 1705525200, @@ -388,7 +385,7 @@ mod tests { let period_info_deserialized: PeriodInfo = serde_json::from_str(period_info_json).unwrap(); assert_eq!(&period_info_deserialized, &period_info_expected); } - + #[test] fn test_deserialize_trading_periods_simple() { let trading_periods_json = r#" @@ -404,17 +401,18 @@ mod tests { ] ] "#; - let trading_periods_expected = TradingPeriods{ + let trading_periods_expected = TradingPeriods { pre: None, - regular: Some(vec![vec![PeriodInfo{ + regular: Some(vec![vec![PeriodInfo { timezone: "EST".to_string(), start: 1705501800, end: 1705525200, gmtoffset: -18000, }]]), - post: None, + post: None, }; - let trading_periods_deserialized: TradingPeriods = serde_json::from_str(trading_periods_json).unwrap(); + let trading_periods_deserialized: TradingPeriods = + serde_json::from_str(trading_periods_json).unwrap(); assert_eq!(&trading_periods_expected, &trading_periods_deserialized); } @@ -434,17 +432,18 @@ mod tests { ] } "#; - let trading_periods_expected = TradingPeriods{ + let trading_periods_expected = TradingPeriods { pre: None, - regular: Some(vec![vec![PeriodInfo{ + regular: Some(vec![vec![PeriodInfo { timezone: "EST".to_string(), start: 1705501800, end: 1705525200, gmtoffset: -18000, }]]), - post: None + post: None, }; - let trading_periods_deserialized: TradingPeriods = serde_json::from_str(trading_periods_json).unwrap(); + let trading_periods_deserialized: TradingPeriods = + serde_json::from_str(trading_periods_json).unwrap(); assert_eq!(&trading_periods_expected, &trading_periods_deserialized); } @@ -484,28 +483,28 @@ mod tests { ] } "#; - let trading_periods_expected = TradingPeriods{ - pre: Some(vec![vec![PeriodInfo{ + let trading_periods_expected = TradingPeriods { + pre: Some(vec![vec![PeriodInfo { timezone: "EST".to_string(), start: 1705482000, end: 1705501800, gmtoffset: -18000, }]]), - regular: Some(vec![vec![PeriodInfo{ + regular: Some(vec![vec![PeriodInfo { timezone: "EST".to_string(), start: 1705501800, end: 1705525200, gmtoffset: -18000, }]]), - post: Some(vec![vec![PeriodInfo{ + post: Some(vec![vec![PeriodInfo { timezone: "EST".to_string(), start: 1705525200, end: 1705539600, gmtoffset: -18000, }]]), }; - let trading_periods_deserialized: TradingPeriods = serde_json::from_str(trading_periods_json).unwrap(); + let trading_periods_deserialized: TradingPeriods = + serde_json::from_str(trading_periods_json).unwrap(); assert_eq!(&trading_periods_expected, &trading_periods_deserialized); } } - diff --git a/src/search_result.rs b/src/search_result.rs index 4bc2cbd..321712a 100644 --- a/src/search_result.rs +++ b/src/search_result.rs @@ -148,28 +148,26 @@ impl YOptionResults { .collect(); cols }) - .map(|sv| { - YOptionResult { - name: sv[0].clone(), - last_trade_date: sv[1].clone(), - strike: sv[2].replace(',', "").parse::().unwrap_or(0.0), - last_price: sv[3].replace(',', "").parse::().unwrap_or(0.0), - bid: sv[4].replace(',', "").parse::().unwrap_or(0.0), - ask: sv[5].replace(',', "").parse::().unwrap_or(0.0), - change: sv[6].replace(',', "").parse::().unwrap_or(0.0), - change_pct: sv[7] - .replace(',', "") - .trim_end_matches('%') - .parse::() - .unwrap_or(0.0), - volume: sv[8].replace(',', "").parse::().unwrap_or(0), - open_interest: sv[9].replace(',', "").parse::().unwrap_or(0), - impl_volatility: sv[10] - .replace(',', "") - .trim_end_matches('%') - .parse::() - .unwrap_or(0.0), - } + .map(|sv| YOptionResult { + name: sv[0].clone(), + last_trade_date: sv[1].clone(), + strike: sv[2].replace(',', "").parse::().unwrap_or(0.0), + last_price: sv[3].replace(',', "").parse::().unwrap_or(0.0), + bid: sv[4].replace(',', "").parse::().unwrap_or(0.0), + ask: sv[5].replace(',', "").parse::().unwrap_or(0.0), + change: sv[6].replace(',', "").parse::().unwrap_or(0.0), + change_pct: sv[7] + .replace(',', "") + .trim_end_matches('%') + .parse::() + .unwrap_or(0.0), + volume: sv[8].replace(',', "").parse::().unwrap_or(0), + open_interest: sv[9].replace(',', "").parse::().unwrap_or(0), + impl_volatility: sv[10] + .replace(',', "") + .trim_end_matches('%') + .parse::() + .unwrap_or(0.0), }) .collect(); Self { options }