use serde::{Deserialize, Serialize};
use crate::client::Client;
use crate::error::Error;
use crate::models::transaction::{
MarketOrderRejectTransaction, MarketOrderTransaction, OrderCancelTransaction,
OrderFillTransaction,
};
use crate::models::{AccountId, ClientExtensions, InstrumentName, Position, TransactionId};
impl Client {
pub async fn list_positions(
&self,
account_id: impl Into<AccountId>,
) -> Result<ListPositionsResponse, Error> {
let account_id = account_id.into();
self.execute(self.get(&["accounts", account_id.as_str(), "positions"]))
.await
}
pub async fn list_open_positions(
&self,
account_id: impl Into<AccountId>,
) -> Result<ListPositionsResponse, Error> {
let account_id = account_id.into();
self.execute(self.get(&["accounts", account_id.as_str(), "openPositions"]))
.await
}
pub async fn position(
&self,
account_id: impl Into<AccountId>,
instrument: impl Into<InstrumentName>,
) -> Result<PositionResponse, Error> {
let account_id = account_id.into();
let instrument = instrument.into();
self.execute(self.get(&[
"accounts",
account_id.as_str(),
"positions",
instrument.as_str(),
]))
.await
}
pub fn close_position(
&self,
account_id: impl Into<AccountId>,
instrument: impl Into<InstrumentName>,
) -> ClosePositionRequest {
ClosePositionRequest {
client: self.clone(),
account_id: account_id.into(),
instrument: instrument.into(),
body: ClosePositionBody {
long_units: None,
long_client_extensions: None,
short_units: None,
short_client_extensions: None,
},
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[non_exhaustive]
pub struct ListPositionsResponse {
#[serde(rename = "positions", default, skip_serializing_if = "Vec::is_empty")]
pub positions: Vec<Position>,
#[serde(rename = "lastTransactionID", skip_serializing_if = "Option::is_none")]
pub last_transaction_id: Option<TransactionId>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[non_exhaustive]
pub struct PositionResponse {
#[serde(rename = "position")]
pub position: Position,
#[serde(rename = "lastTransactionID", skip_serializing_if = "Option::is_none")]
pub last_transaction_id: Option<TransactionId>,
}
#[derive(Debug)]
pub struct ClosePositionRequest {
client: Client,
account_id: AccountId,
instrument: InstrumentName,
body: ClosePositionBody,
}
#[derive(Debug, Serialize)]
struct ClosePositionBody {
#[serde(rename = "longUnits", skip_serializing_if = "Option::is_none")]
long_units: Option<String>,
#[serde(
rename = "longClientExtensions",
skip_serializing_if = "Option::is_none"
)]
long_client_extensions: Option<ClientExtensions>,
#[serde(rename = "shortUnits", skip_serializing_if = "Option::is_none")]
short_units: Option<String>,
#[serde(
rename = "shortClientExtensions",
skip_serializing_if = "Option::is_none"
)]
short_client_extensions: Option<ClientExtensions>,
}
impl ClosePositionRequest {
pub fn long_units(mut self, units: impl Into<String>) -> Self {
self.body.long_units = Some(units.into());
self
}
pub fn long_client_extensions(mut self, extensions: ClientExtensions) -> Self {
self.body.long_client_extensions = Some(extensions);
self
}
pub fn short_units(mut self, units: impl Into<String>) -> Self {
self.body.short_units = Some(units.into());
self
}
pub fn short_client_extensions(mut self, extensions: ClientExtensions) -> Self {
self.body.short_client_extensions = Some(extensions);
self
}
pub async fn send(self) -> Result<ClosePositionResponse, Error> {
let request = self
.client
.put(&[
"accounts",
self.account_id.as_str(),
"positions",
self.instrument.as_str(),
"close",
])
.json(&self.body);
self.client.execute(request).await
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[non_exhaustive]
pub struct ClosePositionResponse {
#[serde(
rename = "longOrderCreateTransaction",
skip_serializing_if = "Option::is_none"
)]
pub long_order_create_transaction: Option<MarketOrderTransaction>,
#[serde(
rename = "longOrderFillTransaction",
skip_serializing_if = "Option::is_none"
)]
pub long_order_fill_transaction: Option<OrderFillTransaction>,
#[serde(
rename = "longOrderCancelTransaction",
skip_serializing_if = "Option::is_none"
)]
pub long_order_cancel_transaction: Option<OrderCancelTransaction>,
#[serde(
rename = "shortOrderCreateTransaction",
skip_serializing_if = "Option::is_none"
)]
pub short_order_create_transaction: Option<MarketOrderTransaction>,
#[serde(
rename = "shortOrderFillTransaction",
skip_serializing_if = "Option::is_none"
)]
pub short_order_fill_transaction: Option<OrderFillTransaction>,
#[serde(
rename = "shortOrderCancelTransaction",
skip_serializing_if = "Option::is_none"
)]
pub short_order_cancel_transaction: Option<OrderCancelTransaction>,
#[serde(
rename = "relatedTransactionIDs",
default,
skip_serializing_if = "Vec::is_empty"
)]
pub related_transaction_ids: Vec<TransactionId>,
#[serde(rename = "lastTransactionID", skip_serializing_if = "Option::is_none")]
pub last_transaction_id: Option<TransactionId>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[non_exhaustive]
pub struct ClosePositionRejectBody {
#[serde(
rename = "longOrderRejectTransaction",
skip_serializing_if = "Option::is_none"
)]
pub long_order_reject_transaction: Option<MarketOrderRejectTransaction>,
#[serde(
rename = "shortOrderRejectTransaction",
skip_serializing_if = "Option::is_none"
)]
pub short_order_reject_transaction: Option<MarketOrderRejectTransaction>,
#[serde(
rename = "relatedTransactionIDs",
default,
skip_serializing_if = "Vec::is_empty"
)]
pub related_transaction_ids: Vec<TransactionId>,
#[serde(rename = "lastTransactionID", skip_serializing_if = "Option::is_none")]
pub last_transaction_id: Option<TransactionId>,
}