From e3f77c16fb3c60f178c1f83b32a714b7c14009d8 Mon Sep 17 00:00:00 2001 From: z-Wind Date: Sat, 1 Jun 2024 13:53:15 +0800 Subject: [PATCH] Adds commonly used attributes to the QuoteResponse struct. --- src/model/market_data/quote_response.rs | 303 +++++++++++++++++++++++- 1 file changed, 302 insertions(+), 1 deletion(-) diff --git a/src/model/market_data/quote_response.rs b/src/model/market_data/quote_response.rs index 5aceec1..f907ac5 100644 --- a/src/model/market_data/quote_response.rs +++ b/src/model/market_data/quote_response.rs @@ -33,11 +33,279 @@ pub enum QuoteResponse { Option(Box), } +impl QuoteResponse { + /// Returns the symbol of the quote + pub fn symbol(&self) -> &str { + match self { + QuoteResponse::Bond(x) => unimplemented!("{x}"), + QuoteResponse::Equity(x) => &x.symbol, + QuoteResponse::Forex(x) => &x.symbol, + QuoteResponse::Future(x) => &x.symbol, + QuoteResponse::FutureOption(x) => &x.symbol, + QuoteResponse::Index(x) => &x.symbol, + QuoteResponse::MutualFund(x) => &x.symbol, + QuoteResponse::Option(x) => &x.symbol, + } + } + + /// Returns the 52-week high price + pub fn n52week_high(&self) -> Option { + match self { + QuoteResponse::Bond(x) => unimplemented!("{x}"), + QuoteResponse::Equity(x) => Some(x.quote.n52week_high), + QuoteResponse::Forex(x) => Some(x.quote.n52week_high), + QuoteResponse::Future(_) => None, + QuoteResponse::FutureOption(_) => None, + QuoteResponse::Index(x) => Some(x.quote.n52week_high), + QuoteResponse::MutualFund(x) => Some(x.quote.n52week_high), + QuoteResponse::Option(_) => None, + } + } + + /// Returns the 52-week low price + pub fn n52week_low(&self) -> Option { + match self { + QuoteResponse::Bond(x) => unimplemented!("{x}"), + QuoteResponse::Equity(x) => Some(x.quote.n52week_low), + QuoteResponse::Forex(x) => Some(x.quote.n52week_low), + QuoteResponse::Future(_) => None, + QuoteResponse::FutureOption(_) => None, + QuoteResponse::Index(x) => Some(x.quote.n52week_low), + QuoteResponse::MutualFund(x) => Some(x.quote.n52week_low), + QuoteResponse::Option(_) => None, + } + } + + /// Returns the current best ask price + pub fn ask_price(&self) -> Option { + match self { + QuoteResponse::Bond(x) => unimplemented!("{x}"), + QuoteResponse::Equity(x) => Some(x.quote.ask_price), + QuoteResponse::Forex(x) => Some(x.quote.ask_price), + QuoteResponse::Future(x) => Some(x.quote.ask_price), + QuoteResponse::FutureOption(x) => Some(x.quote.ask_price), + QuoteResponse::Index(_) => None, + QuoteResponse::MutualFund(_) => None, + QuoteResponse::Option(x) => Some(x.quote.ask_price), + } + } + + /// Returns the number of shares for ask + pub fn ask_size(&self) -> Option { + match self { + QuoteResponse::Bond(x) => unimplemented!("{x}"), + QuoteResponse::Equity(x) => Some(x.quote.ask_size), + QuoteResponse::Forex(x) => Some(x.quote.ask_size), + QuoteResponse::Future(x) => Some(x.quote.ask_size), + QuoteResponse::FutureOption(x) => Some(x.quote.ask_size), + QuoteResponse::Index(_) => None, + QuoteResponse::MutualFund(_) => None, + QuoteResponse::Option(x) => Some(x.quote.ask_size), + } + } + + /// Returns the last ask time in Utc format + pub fn ask_time(&self) -> Option> { + match self { + QuoteResponse::Bond(x) => unimplemented!("{x}"), + QuoteResponse::Equity(x) => Some(x.quote.ask_time), + QuoteResponse::Forex(_) => None, + QuoteResponse::Future(x) => Some(x.quote.ask_time), + QuoteResponse::FutureOption(_) => None, + QuoteResponse::Index(_) => None, + QuoteResponse::MutualFund(_) => None, + QuoteResponse::Option(_) => None, + } + } + + /// Returns the current best bid price + pub fn bid_price(&self) -> Option { + match self { + QuoteResponse::Bond(x) => unimplemented!("{x}"), + QuoteResponse::Equity(x) => Some(x.quote.bid_price), + QuoteResponse::Forex(x) => Some(x.quote.bid_price), + QuoteResponse::Future(x) => Some(x.quote.bid_price), + QuoteResponse::FutureOption(x) => Some(x.quote.bid_price), + QuoteResponse::Index(_) => None, + QuoteResponse::MutualFund(_) => None, + QuoteResponse::Option(x) => Some(x.quote.bid_price), + } + } + + /// Returns the number of shares for bid + pub fn bid_size(&self) -> Option { + match self { + QuoteResponse::Bond(x) => unimplemented!("{x}"), + QuoteResponse::Equity(x) => Some(x.quote.bid_size), + QuoteResponse::Forex(x) => Some(x.quote.bid_size), + QuoteResponse::Future(x) => Some(x.quote.bid_size), + QuoteResponse::FutureOption(x) => Some(x.quote.bid_size), + QuoteResponse::Index(_) => None, + QuoteResponse::MutualFund(_) => None, + QuoteResponse::Option(x) => Some(x.quote.bid_size), + } + } + + /// Returns the last bid time in Utc format + pub fn bid_time(&self) -> Option> { + match self { + QuoteResponse::Bond(x) => unimplemented!("{x}"), + QuoteResponse::Equity(x) => Some(x.quote.bid_time), + QuoteResponse::Forex(_) => None, + QuoteResponse::Future(x) => Some(x.quote.bid_time), + QuoteResponse::FutureOption(_) => None, + QuoteResponse::Index(_) => None, + QuoteResponse::MutualFund(_) => None, + QuoteResponse::Option(_) => None, + } + } + + /// Returns the previous day's closing price + pub fn close_price(&self) -> f64 { + match self { + QuoteResponse::Bond(x) => unimplemented!("{x}"), + QuoteResponse::Equity(x) => x.quote.close_price, + QuoteResponse::Forex(x) => x.quote.close_price, + QuoteResponse::Future(x) => x.quote.close_price, + QuoteResponse::FutureOption(x) => x.quote.close_price, + QuoteResponse::Index(x) => x.quote.close_price, + QuoteResponse::MutualFund(x) => x.quote.close_price, + QuoteResponse::Option(x) => x.quote.close_price, + } + } + + /// Returns the day's high trade price + pub fn high_price(&self) -> Option { + match self { + QuoteResponse::Bond(x) => unimplemented!("{x}"), + QuoteResponse::Equity(x) => Some(x.quote.high_price), + QuoteResponse::Forex(x) => Some(x.quote.high_price), + QuoteResponse::Future(x) => Some(x.quote.high_price), + QuoteResponse::FutureOption(x) => Some(x.quote.high_price), + QuoteResponse::Index(x) => Some(x.quote.high_price), + QuoteResponse::MutualFund(_) => None, + QuoteResponse::Option(x) => Some(x.quote.high_price), + } + } + + /// Returns the latest traded price + pub fn last_price(&self) -> Option { + match self { + QuoteResponse::Bond(x) => unimplemented!("{x}"), + QuoteResponse::Equity(x) => Some(x.quote.last_price), + QuoteResponse::Forex(x) => Some(x.quote.last_price), + QuoteResponse::Future(x) => Some(x.quote.last_price), + QuoteResponse::FutureOption(x) => Some(x.quote.last_price), + QuoteResponse::Index(x) => Some(x.quote.last_price), + QuoteResponse::MutualFund(_) => None, + QuoteResponse::Option(x) => Some(x.quote.last_price), + } + } + + /// Returns the number of shares traded with the last trade + pub fn last_size(&self) -> Option { + match self { + QuoteResponse::Bond(x) => unimplemented!("{x}"), + QuoteResponse::Equity(x) => Some(x.quote.last_size), + QuoteResponse::Forex(x) => Some(x.quote.last_size), + QuoteResponse::Future(x) => Some(x.quote.last_size), + QuoteResponse::FutureOption(x) => Some(x.quote.last_size), + QuoteResponse::Index(_) => None, + QuoteResponse::MutualFund(_) => None, + QuoteResponse::Option(x) => Some(x.quote.last_size), + } + } + + /// Returns the day's low trade price + pub fn low_price(&self) -> Option { + match self { + QuoteResponse::Bond(x) => unimplemented!("{x}"), + QuoteResponse::Equity(x) => Some(x.quote.low_price), + QuoteResponse::Forex(x) => Some(x.quote.low_price), + QuoteResponse::Future(x) => Some(x.quote.low_price), + QuoteResponse::FutureOption(x) => Some(x.quote.low_price), + QuoteResponse::Index(x) => Some(x.quote.low_price), + QuoteResponse::MutualFund(_) => None, + QuoteResponse::Option(x) => Some(x.quote.low_price), + } + } + + /// Returns the current last-prev close price difference + pub fn net_change(&self) -> f64 { + match self { + QuoteResponse::Bond(x) => unimplemented!("{x}"), + QuoteResponse::Equity(x) => x.quote.net_change, + QuoteResponse::Forex(x) => x.quote.net_change, + QuoteResponse::Future(x) => x.quote.net_change, + QuoteResponse::FutureOption(x) => x.quote.net_change, + QuoteResponse::Index(x) => x.quote.net_change, + QuoteResponse::MutualFund(x) => x.quote.net_change, + QuoteResponse::Option(x) => x.quote.net_change, + } + } + + /// Returns the day's open trade price + pub fn open_price(&self) -> Option { + match self { + QuoteResponse::Bond(x) => unimplemented!("{x}"), + QuoteResponse::Equity(x) => Some(x.quote.open_price), + QuoteResponse::Forex(x) => Some(x.quote.open_price), + QuoteResponse::Future(x) => Some(x.quote.open_price), + QuoteResponse::FutureOption(x) => Some(x.quote.open_price), + QuoteResponse::Index(x) => Some(x.quote.open_price), + QuoteResponse::MutualFund(_) => None, + QuoteResponse::Option(x) => Some(x.quote.open_price), + } + } + + /// Returns the time of the latest quote in Utc format + pub fn quote_time(&self) -> Option> { + match self { + QuoteResponse::Bond(x) => unimplemented!("{x}"), + QuoteResponse::Equity(x) => Some(x.quote.quote_time), + QuoteResponse::Forex(x) => Some(x.quote.quote_time), + QuoteResponse::Future(x) => Some(x.quote.quote_time), + QuoteResponse::FutureOption(x) => Some(x.quote.quote_time), + QuoteResponse::Index(_) => None, + QuoteResponse::MutualFund(_) => None, + QuoteResponse::Option(x) => Some(x.quote.quote_time), + } + } + + /// Returns the time of the last trade in Utc format + pub fn trade_time(&self) -> chrono::DateTime { + match self { + QuoteResponse::Bond(x) => unimplemented!("{x}"), + QuoteResponse::Equity(x) => x.quote.trade_time, + QuoteResponse::Forex(x) => x.quote.trade_time, + QuoteResponse::Future(x) => x.quote.trade_time, + QuoteResponse::FutureOption(x) => x.quote.trade_time, + QuoteResponse::Index(x) => x.quote.trade_time, + QuoteResponse::MutualFund(x) => x.quote.trade_time, + QuoteResponse::Option(x) => x.quote.trade_time, + } + } + + /// Returns the total volume of trades for the day including pre/post market + pub fn total_volume(&self) -> Option { + match self { + QuoteResponse::Bond(x) => unimplemented!("{x}"), + QuoteResponse::Equity(x) => Some(x.quote.total_volume), + QuoteResponse::Forex(x) => Some(x.quote.total_volume), + QuoteResponse::Future(x) => Some(x.quote.total_volume), + QuoteResponse::FutureOption(x) => Some(x.quote.total_volume), + QuoteResponse::Index(x) => Some(x.quote.total_volume), + QuoteResponse::MutualFund(x) => x.quote.total_volume, + QuoteResponse::Option(x) => Some(x.quote.total_volume), + } + } +} + #[cfg(test)] mod tests { use super::*; - use std::collections::HashMap; + use float_cmp::assert_approx_eq; #[test] fn test_de() { @@ -61,5 +329,38 @@ mod tests { let val = serde_json::from_str::(json); println!("{val:?}"); assert!(val.is_ok()); + + let result = val.unwrap().responses.remove("AAPL").unwrap(); + assert_eq!("AAPL", result.symbol()); + assert_approx_eq!(f64, 199.62, result.n52week_high().unwrap()); + assert_approx_eq!(f64, 164.075, result.n52week_low().unwrap()); + assert_approx_eq!(f64, 189.92, result.ask_price().unwrap()); + assert_eq!(1, result.ask_size().unwrap()); + assert_eq!( + chrono::DateTime::from_timestamp_millis(1715990363904).unwrap(), + result.ask_time().unwrap() + ); + assert_approx_eq!(f64, 189.9, result.bid_price().unwrap()); + assert_eq!(6, result.bid_size().unwrap()); + assert_eq!( + chrono::DateTime::from_timestamp_millis(1715990363904).unwrap(), + result.bid_time().unwrap() + ); + assert_approx_eq!(f64, 189.84, result.close_price()); + assert_approx_eq!(f64, 190.81, result.high_price().unwrap()); + assert_approx_eq!(f64, 189.9, result.last_price().unwrap()); + assert_eq!(2, result.last_size().unwrap()); + assert_approx_eq!(f64, 189.18, result.low_price().unwrap()); + assert_approx_eq!(f64, 0.06, result.net_change()); + assert_approx_eq!(f64, 189.51, result.open_price().unwrap()); + assert_eq!( + chrono::DateTime::from_timestamp_millis(1715990363904).unwrap(), + result.quote_time().unwrap() + ); + assert_eq!( + chrono::DateTime::from_timestamp_millis(1715990395834).unwrap(), + result.trade_time() + ); + assert_eq!(41282925, result.total_volume().unwrap()); } }