1use serde::{Deserialize, Serialize};
4
5use crate::client::Client;
6use crate::error::Error;
7use crate::models::transaction::{
8 MarketOrderRejectTransaction, MarketOrderTransaction, OrderCancelTransaction,
9 OrderFillTransaction,
10};
11use crate::models::{AccountId, ClientExtensions, InstrumentName, Position, TransactionId};
12
13impl Client {
14 pub async fn list_positions(
20 &self,
21 account_id: impl Into<AccountId>,
22 ) -> Result<ListPositionsResponse, Error> {
23 let account_id = account_id.into();
24 self.execute(self.get(&["accounts", account_id.as_str(), "positions"]))
25 .await
26 }
27
28 pub async fn list_open_positions(
33 &self,
34 account_id: impl Into<AccountId>,
35 ) -> Result<ListPositionsResponse, Error> {
36 let account_id = account_id.into();
37 self.execute(self.get(&["accounts", account_id.as_str(), "openPositions"]))
38 .await
39 }
40
41 pub async fn position(
45 &self,
46 account_id: impl Into<AccountId>,
47 instrument: impl Into<InstrumentName>,
48 ) -> Result<PositionResponse, Error> {
49 let account_id = account_id.into();
50 let instrument = instrument.into();
51 self.execute(self.get(&[
52 "accounts",
53 account_id.as_str(),
54 "positions",
55 instrument.as_str(),
56 ]))
57 .await
58 }
59
60 pub fn close_position(
83 &self,
84 account_id: impl Into<AccountId>,
85 instrument: impl Into<InstrumentName>,
86 ) -> ClosePositionRequest {
87 ClosePositionRequest {
88 client: self.clone(),
89 account_id: account_id.into(),
90 instrument: instrument.into(),
91 body: ClosePositionBody {
92 long_units: None,
93 long_client_extensions: None,
94 short_units: None,
95 short_client_extensions: None,
96 },
97 }
98 }
99}
100
101#[derive(Debug, Clone, Serialize, Deserialize)]
104#[non_exhaustive]
105pub struct ListPositionsResponse {
106 #[serde(rename = "positions", default, skip_serializing_if = "Vec::is_empty")]
108 pub positions: Vec<Position>,
109 #[serde(rename = "lastTransactionID", skip_serializing_if = "Option::is_none")]
111 pub last_transaction_id: Option<TransactionId>,
112}
113
114#[derive(Debug, Clone, Serialize, Deserialize)]
116#[non_exhaustive]
117pub struct PositionResponse {
118 #[serde(rename = "position")]
120 pub position: Position,
121 #[serde(rename = "lastTransactionID", skip_serializing_if = "Option::is_none")]
123 pub last_transaction_id: Option<TransactionId>,
124}
125
126#[derive(Debug)]
128pub struct ClosePositionRequest {
129 client: Client,
130 account_id: AccountId,
131 instrument: InstrumentName,
132 body: ClosePositionBody,
133}
134
135#[derive(Debug, Serialize)]
136struct ClosePositionBody {
137 #[serde(rename = "longUnits", skip_serializing_if = "Option::is_none")]
138 long_units: Option<String>,
139 #[serde(
140 rename = "longClientExtensions",
141 skip_serializing_if = "Option::is_none"
142 )]
143 long_client_extensions: Option<ClientExtensions>,
144 #[serde(rename = "shortUnits", skip_serializing_if = "Option::is_none")]
145 short_units: Option<String>,
146 #[serde(
147 rename = "shortClientExtensions",
148 skip_serializing_if = "Option::is_none"
149 )]
150 short_client_extensions: Option<ClientExtensions>,
151}
152
153impl ClosePositionRequest {
154 pub fn long_units(mut self, units: impl Into<String>) -> Self {
157 self.body.long_units = Some(units.into());
158 self
159 }
160
161 pub fn long_client_extensions(mut self, extensions: ClientExtensions) -> Self {
164 self.body.long_client_extensions = Some(extensions);
165 self
166 }
167
168 pub fn short_units(mut self, units: impl Into<String>) -> Self {
171 self.body.short_units = Some(units.into());
172 self
173 }
174
175 pub fn short_client_extensions(mut self, extensions: ClientExtensions) -> Self {
178 self.body.short_client_extensions = Some(extensions);
179 self
180 }
181
182 pub async fn send(self) -> Result<ClosePositionResponse, Error> {
184 let request = self
185 .client
186 .put(&[
187 "accounts",
188 self.account_id.as_str(),
189 "positions",
190 self.instrument.as_str(),
191 "close",
192 ])
193 .json(&self.body);
194 self.client.execute(request).await
195 }
196}
197
198#[derive(Debug, Clone, Serialize, Deserialize)]
200#[non_exhaustive]
201pub struct ClosePositionResponse {
202 #[serde(
204 rename = "longOrderCreateTransaction",
205 skip_serializing_if = "Option::is_none"
206 )]
207 pub long_order_create_transaction: Option<MarketOrderTransaction>,
208 #[serde(
210 rename = "longOrderFillTransaction",
211 skip_serializing_if = "Option::is_none"
212 )]
213 pub long_order_fill_transaction: Option<OrderFillTransaction>,
214 #[serde(
216 rename = "longOrderCancelTransaction",
217 skip_serializing_if = "Option::is_none"
218 )]
219 pub long_order_cancel_transaction: Option<OrderCancelTransaction>,
220 #[serde(
222 rename = "shortOrderCreateTransaction",
223 skip_serializing_if = "Option::is_none"
224 )]
225 pub short_order_create_transaction: Option<MarketOrderTransaction>,
226 #[serde(
228 rename = "shortOrderFillTransaction",
229 skip_serializing_if = "Option::is_none"
230 )]
231 pub short_order_fill_transaction: Option<OrderFillTransaction>,
232 #[serde(
234 rename = "shortOrderCancelTransaction",
235 skip_serializing_if = "Option::is_none"
236 )]
237 pub short_order_cancel_transaction: Option<OrderCancelTransaction>,
238 #[serde(
240 rename = "relatedTransactionIDs",
241 default,
242 skip_serializing_if = "Vec::is_empty"
243 )]
244 pub related_transaction_ids: Vec<TransactionId>,
245 #[serde(rename = "lastTransactionID", skip_serializing_if = "Option::is_none")]
247 pub last_transaction_id: Option<TransactionId>,
248}
249
250#[derive(Debug, Clone, Serialize, Deserialize)]
254#[non_exhaustive]
255pub struct ClosePositionRejectBody {
256 #[serde(
258 rename = "longOrderRejectTransaction",
259 skip_serializing_if = "Option::is_none"
260 )]
261 pub long_order_reject_transaction: Option<MarketOrderRejectTransaction>,
262 #[serde(
264 rename = "shortOrderRejectTransaction",
265 skip_serializing_if = "Option::is_none"
266 )]
267 pub short_order_reject_transaction: Option<MarketOrderRejectTransaction>,
268 #[serde(
270 rename = "relatedTransactionIDs",
271 default,
272 skip_serializing_if = "Vec::is_empty"
273 )]
274 pub related_transaction_ids: Vec<TransactionId>,
275 #[serde(rename = "lastTransactionID", skip_serializing_if = "Option::is_none")]
277 pub last_transaction_id: Option<TransactionId>,
278}