deribit_http/model/request/
position.rs1use pretty_simple_display::{DebugPretty, DisplaySimple};
9use serde::{Deserialize, Serialize};
10use serde_with::skip_serializing_none;
11
12#[skip_serializing_none]
16#[derive(DebugPretty, DisplaySimple, Clone, PartialEq, Serialize, Deserialize)]
17pub struct MovePositionTrade {
18 pub instrument_name: String,
20 pub amount: f64,
22 pub price: Option<f64>,
24}
25
26impl MovePositionTrade {
27 pub fn new(instrument_name: impl Into<String>, amount: f64) -> Self {
29 Self {
30 instrument_name: instrument_name.into(),
31 amount,
32 price: None,
33 }
34 }
35
36 pub fn with_price(instrument_name: impl Into<String>, amount: f64, price: f64) -> Self {
38 Self {
39 instrument_name: instrument_name.into(),
40 amount,
41 price: Some(price),
42 }
43 }
44
45 #[must_use]
47 pub fn price(mut self, price: f64) -> Self {
48 self.price = Some(price);
49 self
50 }
51}
52
53#[derive(DebugPretty, DisplaySimple, Clone, PartialEq, Serialize, Deserialize)]
57pub struct MovePositionsRequest {
58 pub currency: String,
60 pub source_uid: i64,
62 pub target_uid: i64,
64 pub trades: Vec<MovePositionTrade>,
66}
67
68impl MovePositionsRequest {
69 pub fn new(
71 currency: impl Into<String>,
72 source_uid: i64,
73 target_uid: i64,
74 trades: Vec<MovePositionTrade>,
75 ) -> Self {
76 Self {
77 currency: currency.into(),
78 source_uid,
79 target_uid,
80 trades,
81 }
82 }
83
84 pub fn add_trade(&mut self, trade: MovePositionTrade) {
86 self.trades.push(trade);
87 }
88
89 pub fn trade_count(&self) -> usize {
91 self.trades.len()
92 }
93
94 pub fn has_trades(&self) -> bool {
96 !self.trades.is_empty()
97 }
98}
99
100#[cfg(test)]
101mod tests {
102 use super::*;
103
104 #[test]
105 fn test_move_position_trade_new() {
106 let trade = MovePositionTrade::new("BTC-PERPETUAL", 100.0);
107 assert_eq!(trade.instrument_name, "BTC-PERPETUAL");
108 assert_eq!(trade.amount, 100.0);
109 assert!(trade.price.is_none());
110 }
111
112 #[test]
113 fn test_move_position_trade_with_price() {
114 let trade = MovePositionTrade::with_price("BTC-PERPETUAL", 100.0, 35800.0);
115 assert_eq!(trade.instrument_name, "BTC-PERPETUAL");
116 assert_eq!(trade.amount, 100.0);
117 assert_eq!(trade.price, Some(35800.0));
118 }
119
120 #[test]
121 fn test_move_positions_request_new() {
122 let trades = vec![MovePositionTrade::new("BTC-PERPETUAL", 100.0)];
123 let request = MovePositionsRequest::new("BTC", 3, 23, trades);
124 assert_eq!(request.currency, "BTC");
125 assert_eq!(request.source_uid, 3);
126 assert_eq!(request.target_uid, 23);
127 assert_eq!(request.trade_count(), 1);
128 }
129
130 #[test]
131 fn test_move_positions_request_serialization() {
132 let trades = vec![
133 MovePositionTrade::with_price("BTC-PERPETUAL", 110.0, 35800.0),
134 MovePositionTrade::new("BTC-28JAN22-32500-C", 0.1),
135 ];
136 let request = MovePositionsRequest::new("BTC", 3, 23, trades);
137
138 let json = serde_json::to_string(&request).unwrap();
139 assert!(json.contains("BTC-PERPETUAL"));
140 assert!(json.contains("source_uid"));
141 assert!(json.contains("target_uid"));
142 }
143}