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