Skip to main content

alpaca_data/stocks/
client.rs

1use std::fmt;
2use std::sync::Arc;
3
4use alpaca_http::RequestParts;
5use reqwest::Method;
6use serde::de::DeserializeOwned;
7
8use crate::{Error, client::ClientInner, pagination};
9
10use super::{
11    AuctionsRequest, AuctionsResponse, BarsRequest, BarsResponse, ConditionCodesRequest,
12    ConditionCodesResponse, ExchangeCodesResponse, LatestBarsRequest, LatestBarsResponse,
13    LatestQuotesRequest, LatestQuotesResponse, LatestTradesRequest, LatestTradesResponse,
14    QuotesRequest, QuotesResponse, SnapshotsRequest, SnapshotsResponse, TradesRequest,
15    TradesResponse,
16};
17
18#[derive(Clone)]
19pub struct StocksClient {
20    inner: Arc<ClientInner>,
21}
22
23impl StocksClient {
24    pub(crate) fn new(inner: Arc<ClientInner>) -> Self {
25        Self { inner }
26    }
27
28    pub async fn bars(&self, request: BarsRequest) -> Result<BarsResponse, Error> {
29        request.validate()?;
30        self.get_json("stocks.bars", "/v2/stocks/bars", request.into_query())
31            .await
32    }
33
34    pub async fn bars_all(&self, request: BarsRequest) -> Result<BarsResponse, Error> {
35        let client = self.clone();
36        pagination::collect_all(request, move |request| {
37            let client = client.clone();
38            async move { client.bars(request).await }
39        })
40        .await
41    }
42
43    pub async fn auctions(&self, request: AuctionsRequest) -> Result<AuctionsResponse, Error> {
44        request.validate()?;
45        self.get_json(
46            "stocks.auctions",
47            "/v2/stocks/auctions",
48            request.into_query(),
49        )
50        .await
51    }
52
53    pub async fn auctions_all(&self, request: AuctionsRequest) -> Result<AuctionsResponse, Error> {
54        let client = self.clone();
55        pagination::collect_all(request, move |request| {
56            let client = client.clone();
57            async move { client.auctions(request).await }
58        })
59        .await
60    }
61
62    pub async fn quotes(&self, request: QuotesRequest) -> Result<QuotesResponse, Error> {
63        request.validate()?;
64        self.get_json("stocks.quotes", "/v2/stocks/quotes", request.into_query())
65            .await
66    }
67
68    pub async fn quotes_all(&self, request: QuotesRequest) -> Result<QuotesResponse, Error> {
69        let client = self.clone();
70        pagination::collect_all(request, move |request| {
71            let client = client.clone();
72            async move { client.quotes(request).await }
73        })
74        .await
75    }
76
77    pub async fn trades(&self, request: TradesRequest) -> Result<TradesResponse, Error> {
78        request.validate()?;
79        self.get_json("stocks.trades", "/v2/stocks/trades", request.into_query())
80            .await
81    }
82
83    pub async fn trades_all(&self, request: TradesRequest) -> Result<TradesResponse, Error> {
84        let client = self.clone();
85        pagination::collect_all(request, move |request| {
86            let client = client.clone();
87            async move { client.trades(request).await }
88        })
89        .await
90    }
91
92    pub async fn latest_bars(
93        &self,
94        request: LatestBarsRequest,
95    ) -> Result<LatestBarsResponse, Error> {
96        request.validate()?;
97        self.get_json(
98            "stocks.latest_bars",
99            "/v2/stocks/bars/latest",
100            request.into_query(),
101        )
102        .await
103    }
104
105    pub async fn latest_quotes(
106        &self,
107        request: LatestQuotesRequest,
108    ) -> Result<LatestQuotesResponse, Error> {
109        request.validate()?;
110        self.get_json(
111            "stocks.latest_quotes",
112            "/v2/stocks/quotes/latest",
113            request.into_query(),
114        )
115        .await
116    }
117
118    pub async fn latest_trades(
119        &self,
120        request: LatestTradesRequest,
121    ) -> Result<LatestTradesResponse, Error> {
122        request.validate()?;
123        self.get_json(
124            "stocks.latest_trades",
125            "/v2/stocks/trades/latest",
126            request.into_query(),
127        )
128        .await
129    }
130
131    pub async fn snapshots(&self, request: SnapshotsRequest) -> Result<SnapshotsResponse, Error> {
132        request.validate()?;
133        self.get_json(
134            "stocks.snapshots",
135            "/v2/stocks/snapshots",
136            request.into_query(),
137        )
138        .await
139    }
140
141    pub async fn condition_codes(
142        &self,
143        request: ConditionCodesRequest,
144    ) -> Result<ConditionCodesResponse, Error> {
145        let path = format!("/v2/stocks/meta/conditions/{}", request.ticktype.as_str());
146        self.get_json("stocks.condition_codes", path, request.into_query())
147            .await
148    }
149
150    pub async fn exchange_codes(&self) -> Result<ExchangeCodesResponse, Error> {
151        self.get_json(
152            "stocks.exchange_codes",
153            "/v2/stocks/meta/exchanges",
154            Vec::new(),
155        )
156        .await
157    }
158
159    #[allow(dead_code)]
160    #[must_use]
161    pub(crate) fn inner(&self) -> &Arc<ClientInner> {
162        &self.inner
163    }
164
165    async fn get_json<Response>(
166        &self,
167        operation: &'static str,
168        path: impl Into<String>,
169        query: Vec<(String, String)>,
170    ) -> Result<Response, Error>
171    where
172        Response: DeserializeOwned,
173    {
174        let request = RequestParts::new(Method::GET, path.into())
175            .with_operation(operation)
176            .with_query(query);
177
178        self.inner
179            .send_json::<Response>(request)
180            .await
181            .map(|response| response.into_body())
182    }
183}
184
185impl fmt::Debug for StocksClient {
186    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
187        f.debug_struct("StocksClient").finish()
188    }
189}