Skip to main content

bybit_api/api/
position.rs

1//! Position API endpoints.
2
3use crate::client::BybitClient;
4use crate::error::Result;
5use crate::models::position::*;
6use crate::models::*;
7
8impl BybitClient {
9    /// Get position list.
10    ///
11    /// # Arguments
12    /// * `category` - Product category
13    /// * `symbol` - Optional symbol filter
14    /// * `settle_coin` - Optional settle coin filter (e.g., "USDT")
15    pub async fn get_positions(
16        &self,
17        category: Category,
18        symbol: Option<&str>,
19        settle_coin: Option<&str>,
20    ) -> Result<PositionList> {
21        let cat_str = category.to_string();
22        let mut params = vec![("category", cat_str.as_str())];
23
24        if let Some(s) = symbol {
25            params.push(("symbol", s));
26        }
27        if let Some(sc) = settle_coin {
28            params.push(("settleCoin", sc));
29        }
30
31        self.get("/v5/position/list", &params).await
32    }
33
34    /// Set leverage.
35    ///
36    /// # Arguments
37    /// * `category` - Product category
38    /// * `symbol` - Symbol name
39    /// * `buy_leverage` - Buy leverage
40    /// * `sell_leverage` - Sell leverage
41    pub async fn set_leverage(
42        &self,
43        category: Category,
44        symbol: &str,
45        buy_leverage: &str,
46        sell_leverage: &str,
47    ) -> Result<serde_json::Value> {
48        let params = SetLeverageParams {
49            category,
50            symbol: symbol.to_string(),
51            buy_leverage: buy_leverage.to_string(),
52            sell_leverage: sell_leverage.to_string(),
53        };
54
55        self.post("/v5/position/set-leverage", &params).await
56    }
57
58    /// Set trading stop (TP/SL).
59    ///
60    /// # Arguments
61    /// * `params` - Trading stop parameters
62    pub async fn set_trading_stop(&self, params: TradingStopParams) -> Result<serde_json::Value> {
63        self.post("/v5/position/trading-stop", &params).await
64    }
65
66    /// Switch position mode.
67    ///
68    /// # Arguments
69    /// * `category` - Product category
70    /// * `mode` - Position mode (0=merged, 3=both sides)
71    pub async fn switch_position_mode(
72        &self,
73        category: Category,
74        mode: PositionMode,
75    ) -> Result<serde_json::Value> {
76        let params = SwitchPositionModeParams {
77            category,
78            symbol: None,
79            coin: None,
80            mode: mode as i32,
81        };
82
83        self.post("/v5/position/switch-mode", &params).await
84    }
85
86    /// Set risk limit.
87    ///
88    /// # Arguments
89    /// * `category` - Product category
90    /// * `symbol` - Symbol name
91    /// * `risk_id` - Risk limit ID
92    pub async fn set_risk_limit(
93        &self,
94        category: Category,
95        symbol: &str,
96        risk_id: i32,
97    ) -> Result<serde_json::Value> {
98        let params = SetRiskLimitParams {
99            category,
100            symbol: symbol.to_string(),
101            risk_id,
102            position_idx: None,
103        };
104
105        self.post("/v5/position/set-risk-limit", &params).await
106    }
107
108    /// Add or reduce margin.
109    ///
110    /// # Arguments
111    /// * `category` - Product category
112    /// * `symbol` - Symbol name
113    /// * `margin` - Margin amount (positive to add, negative to reduce)
114    pub async fn add_margin(
115        &self,
116        category: Category,
117        symbol: &str,
118        margin: &str,
119    ) -> Result<serde_json::Value> {
120        let params = AddMarginParams {
121            category,
122            symbol: symbol.to_string(),
123            margin: margin.to_string(),
124            position_idx: None,
125        };
126
127        self.post("/v5/position/add-margin", &params).await
128    }
129
130    /// Get closed PnL history.
131    ///
132    /// # Arguments
133    /// * `category` - Product category
134    /// * `symbol` - Optional symbol filter
135    /// * `limit` - Optional limit (default 20)
136    pub async fn get_closed_pnl(
137        &self,
138        category: Category,
139        symbol: Option<&str>,
140        limit: Option<u32>,
141    ) -> Result<ClosedPnlList> {
142        let cat_str = category.to_string();
143        let limit_str = limit.unwrap_or(20).to_string();
144        let mut params = vec![
145            ("category", cat_str.as_str()),
146            ("limit", limit_str.as_str()),
147        ];
148
149        if let Some(s) = symbol {
150            params.push(("symbol", s));
151        }
152
153        self.get("/v5/position/closed-pnl", &params).await
154    }
155
156    /// Get execution list (trade history).
157    ///
158    /// # Arguments
159    /// * `category` - Product category
160    /// * `symbol` - Optional symbol filter
161    /// * `limit` - Optional limit (default 50)
162    pub async fn get_executions(
163        &self,
164        category: Category,
165        symbol: Option<&str>,
166        limit: Option<u32>,
167    ) -> Result<ExecutionList> {
168        let cat_str = category.to_string();
169        let limit_str = limit.unwrap_or(50).to_string();
170        let mut params = vec![
171            ("category", cat_str.as_str()),
172            ("limit", limit_str.as_str()),
173        ];
174
175        if let Some(s) = symbol {
176            params.push(("symbol", s));
177        }
178
179        self.get("/v5/execution/list", &params).await
180    }
181}