use crate::{
Client, Result,
endpoints::{
EndpointSpec, QueryEncoder, QueryParameters,
metadata::{
DelayScope, EndpointMetadata, GeographicAvailability, MarketDataDelay, RealtimeAccess,
UserDeclarationRequirement,
},
},
responses::quote::{AftermarketQuote, AftermarketTrade, Quote, QuoteShort, StockPriceChange},
types::{ExchangeCode, Ticker, TickerList},
};
macro_rules! symbol_query {
($docs:literal, $query:ident) => {
#[doc = $docs]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct $query {
symbol: Ticker,
}
impl $query {
pub fn new(symbol: Ticker) -> Self {
Self { symbol }
}
pub fn symbol(&self) -> &Ticker {
&self.symbol
}
}
impl From<Ticker> for $query {
fn from(symbol: Ticker) -> Self {
Self::new(symbol)
}
}
impl From<&Ticker> for $query {
fn from(symbol: &Ticker) -> Self {
Self::new(symbol.clone())
}
}
impl QueryParameters for $query {
fn encode(&self, encoder: &mut QueryEncoder<'_>) {
encoder.required("symbol", &self.symbol);
}
}
};
}
symbol_query!(
"Required query parameters for the detailed stock-quote endpoint.",
QuoteQuery
);
symbol_query!(
"Required query parameters for the compact stock-quote endpoint.",
QuoteShortQuery
);
symbol_query!(
"Required query parameters for the US aftermarket-trade endpoint.",
AftermarketTradeQuery
);
symbol_query!(
"Required query parameters for the US aftermarket-quote endpoint.",
AftermarketQuoteQuery
);
symbol_query!(
"Required query parameters for the worldwide stock-price-change endpoint.",
StockPriceChangeQuery
);
macro_rules! symbols_query {
($docs:literal, $query:ident) => {
#[doc = $docs]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct $query {
symbols: TickerList,
}
impl $query {
pub fn new(symbols: TickerList) -> Self {
Self { symbols }
}
pub fn symbols(&self) -> &TickerList {
&self.symbols
}
}
impl From<TickerList> for $query {
fn from(symbols: TickerList) -> Self {
Self::new(symbols)
}
}
impl From<&TickerList> for $query {
fn from(symbols: &TickerList) -> Self {
Self::new(symbols.clone())
}
}
impl QueryParameters for $query {
fn encode(&self, encoder: &mut QueryEncoder<'_>) {
encoder.required("symbols", &self.symbols);
}
}
};
}
symbols_query!(
"Required query parameters for the worldwide detailed stock batch-quote endpoint.",
BatchQuoteQuery
);
symbols_query!(
"Required query parameters for the worldwide compact stock batch-quote endpoint.",
BatchQuoteShortQuery
);
symbols_query!(
"Required query parameters for the US batch aftermarket-trade endpoint.",
BatchAftermarketTradeQuery
);
symbols_query!(
"Required query parameters for the US batch aftermarket-quote endpoint.",
BatchAftermarketQuoteQuery
);
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ExchangeQuotesQuery {
exchange: ExchangeCode,
}
impl ExchangeQuotesQuery {
pub fn new(exchange: ExchangeCode) -> Self {
Self { exchange }
}
pub fn exchange(&self) -> &ExchangeCode {
&self.exchange
}
}
impl From<ExchangeCode> for ExchangeQuotesQuery {
fn from(exchange: ExchangeCode) -> Self {
Self::new(exchange)
}
}
impl From<&ExchangeCode> for ExchangeQuotesQuery {
fn from(exchange: &ExchangeCode) -> Self {
Self::new(exchange.clone())
}
}
impl QueryParameters for ExchangeQuotesQuery {
fn encode(&self, encoder: &mut QueryEncoder<'_>) {
encoder.required("exchange", &self.exchange);
encoder.required("short", true);
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct ShortOnlyQuery;
impl ShortOnlyQuery {
pub const fn new() -> Self {
Self
}
}
impl QueryParameters for ShortOnlyQuery {
fn encode(&self, encoder: &mut QueryEncoder<'_>) {
encoder.required("short", true);
}
}
const NASDAQ_DELAYED_REALTIME: RealtimeAccess = RealtimeAccess::new(
Some(MarketDataDelay::new(15, DelayScope::Nasdaq)),
Some(UserDeclarationRequirement::RequiredForRealtime),
);
const WORLDWIDE_REALTIME: EndpointMetadata = EndpointMetadata::new()
.with_geography(GeographicAvailability::Worldwide)
.with_realtime(NASDAQ_DELAYED_REALTIME);
const US_REALTIME: EndpointMetadata = EndpointMetadata::new()
.with_geography(GeographicAvailability::UsOnly)
.with_realtime(NASDAQ_DELAYED_REALTIME);
const WORLDWIDE: EndpointMetadata =
EndpointMetadata::new().with_geography(GeographicAvailability::Worldwide);
const US_ONLY: EndpointMetadata =
EndpointMetadata::new().with_geography(GeographicAvailability::UsOnly);
const UNSPECIFIED: EndpointMetadata = EndpointMetadata::new();
pub fn quote(query: QuoteQuery) -> EndpointSpec<QuoteQuery, Vec<Quote>> {
EndpointSpec::get("quote", "quote", query).with_metadata(WORLDWIDE_REALTIME)
}
pub fn quote_short(query: QuoteShortQuery) -> EndpointSpec<QuoteShortQuery, Vec<QuoteShort>> {
EndpointSpec::get("quote-short", "quote-short", query).with_metadata(WORLDWIDE_REALTIME)
}
pub fn aftermarket_trade(
query: AftermarketTradeQuery,
) -> EndpointSpec<AftermarketTradeQuery, Vec<AftermarketTrade>> {
EndpointSpec::get("aftermarket-trade", "aftermarket-trade", query).with_metadata(US_REALTIME)
}
pub fn aftermarket_quote(
query: AftermarketQuoteQuery,
) -> EndpointSpec<AftermarketQuoteQuery, Vec<AftermarketQuote>> {
EndpointSpec::get("aftermarket-quote", "aftermarket-quote", query).with_metadata(US_REALTIME)
}
pub fn stock_price_change(
query: StockPriceChangeQuery,
) -> EndpointSpec<StockPriceChangeQuery, Vec<StockPriceChange>> {
EndpointSpec::get("stock-price-change", "stock-price-change", query).with_metadata(WORLDWIDE)
}
pub fn batch_quote(query: BatchQuoteQuery) -> EndpointSpec<BatchQuoteQuery, Vec<Quote>> {
EndpointSpec::get("batch-quote", "batch-quote", query).with_metadata(WORLDWIDE_REALTIME)
}
pub fn batch_quote_short(
query: BatchQuoteShortQuery,
) -> EndpointSpec<BatchQuoteShortQuery, Vec<QuoteShort>> {
EndpointSpec::get("batch-quote-short", "batch-quote-short", query)
.with_metadata(WORLDWIDE_REALTIME)
}
pub fn batch_aftermarket_trade(
query: BatchAftermarketTradeQuery,
) -> EndpointSpec<BatchAftermarketTradeQuery, Vec<AftermarketTrade>> {
EndpointSpec::get("batch-aftermarket-trade", "batch-aftermarket-trade", query)
.with_metadata(US_REALTIME)
}
pub fn batch_aftermarket_quote(
query: BatchAftermarketQuoteQuery,
) -> EndpointSpec<BatchAftermarketQuoteQuery, Vec<AftermarketQuote>> {
EndpointSpec::get("batch-aftermarket-quote", "batch-aftermarket-quote", query)
.with_metadata(US_REALTIME)
}
pub fn exchange_quotes(
query: ExchangeQuotesQuery,
) -> EndpointSpec<ExchangeQuotesQuery, Vec<QuoteShort>> {
EndpointSpec::get("batch-exchange-quote", "batch-exchange-quote", query)
.with_metadata(WORLDWIDE_REALTIME)
}
pub fn mutual_fund_quotes() -> EndpointSpec<ShortOnlyQuery, Vec<QuoteShort>> {
EndpointSpec::get(
"batch-mutualfund-quotes",
"batch-mutualfund-quotes",
ShortOnlyQuery::new(),
)
.with_metadata(US_ONLY)
}
pub fn etf_quotes() -> EndpointSpec<ShortOnlyQuery, Vec<QuoteShort>> {
EndpointSpec::get(
"batch-etf-quotes",
"batch-etf-quotes",
ShortOnlyQuery::new(),
)
.with_metadata(WORLDWIDE)
}
pub fn commodity_quotes() -> EndpointSpec<ShortOnlyQuery, Vec<QuoteShort>> {
EndpointSpec::get(
"batch-commodity-quotes",
"batch-commodity-quotes",
ShortOnlyQuery::new(),
)
.with_metadata(UNSPECIFIED)
}
pub fn cryptocurrency_quotes() -> EndpointSpec<ShortOnlyQuery, Vec<QuoteShort>> {
EndpointSpec::get(
"batch-crypto-quotes",
"batch-crypto-quotes",
ShortOnlyQuery::new(),
)
.with_metadata(UNSPECIFIED)
}
pub fn forex_quotes() -> EndpointSpec<ShortOnlyQuery, Vec<QuoteShort>> {
EndpointSpec::get(
"batch-forex-quotes",
"batch-forex-quotes",
ShortOnlyQuery::new(),
)
.with_metadata(UNSPECIFIED)
}
pub fn index_quotes() -> EndpointSpec<ShortOnlyQuery, Vec<QuoteShort>> {
EndpointSpec::get(
"batch-index-quotes",
"batch-index-quotes",
ShortOnlyQuery::new(),
)
.with_metadata(UNSPECIFIED)
}
impl Client {
pub async fn quote(&self, query: impl Into<QuoteQuery>) -> Result<Vec<Quote>> {
self.execute("e(query.into())).await
}
pub async fn quote_short(&self, query: impl Into<QuoteShortQuery>) -> Result<Vec<QuoteShort>> {
self.execute("e_short(query.into())).await
}
pub async fn aftermarket_trade(
&self,
query: impl Into<AftermarketTradeQuery>,
) -> Result<Vec<AftermarketTrade>> {
self.execute(&aftermarket_trade(query.into())).await
}
pub async fn aftermarket_quote(
&self,
query: impl Into<AftermarketQuoteQuery>,
) -> Result<Vec<AftermarketQuote>> {
self.execute(&aftermarket_quote(query.into())).await
}
pub async fn stock_price_change(
&self,
query: impl Into<StockPriceChangeQuery>,
) -> Result<Vec<StockPriceChange>> {
self.execute(&stock_price_change(query.into())).await
}
pub async fn batch_quote(&self, query: impl Into<BatchQuoteQuery>) -> Result<Vec<Quote>> {
self.execute(&batch_quote(query.into())).await
}
pub async fn batch_quote_short(
&self,
query: impl Into<BatchQuoteShortQuery>,
) -> Result<Vec<QuoteShort>> {
self.execute(&batch_quote_short(query.into())).await
}
pub async fn batch_aftermarket_trade(
&self,
query: impl Into<BatchAftermarketTradeQuery>,
) -> Result<Vec<AftermarketTrade>> {
self.execute(&batch_aftermarket_trade(query.into())).await
}
pub async fn batch_aftermarket_quote(
&self,
query: impl Into<BatchAftermarketQuoteQuery>,
) -> Result<Vec<AftermarketQuote>> {
self.execute(&batch_aftermarket_quote(query.into())).await
}
pub async fn exchange_quotes(
&self,
query: impl Into<ExchangeQuotesQuery>,
) -> Result<Vec<QuoteShort>> {
self.execute(&exchange_quotes(query.into())).await
}
pub async fn mutual_fund_quotes(&self) -> Result<Vec<QuoteShort>> {
self.execute(&mutual_fund_quotes()).await
}
pub async fn etf_quotes(&self) -> Result<Vec<QuoteShort>> {
self.execute(&etf_quotes()).await
}
pub async fn commodity_quotes(&self) -> Result<Vec<QuoteShort>> {
self.execute(&commodity_quotes()).await
}
pub async fn cryptocurrency_quotes(&self) -> Result<Vec<QuoteShort>> {
self.execute(&cryptocurrency_quotes()).await
}
pub async fn forex_quotes(&self) -> Result<Vec<QuoteShort>> {
self.execute(&forex_quotes()).await
}
pub async fn index_quotes(&self) -> Result<Vec<QuoteShort>> {
self.execute(&index_quotes()).await
}
}