Skip to main content

ccxt_exchanges/okx/rest/futures/
margin.rs

1//! Margin mode operations for OKX futures/swap.
2
3use super::super::super::{Okx, signed_request::HttpMethod};
4use ccxt_core::{Error, Result};
5
6impl Okx {
7    /// Set margin mode (cross or isolated) for a symbol.
8    ///
9    /// Uses OKX POST `/api/v5/account/set-position-mode` for position mode,
10    /// and the leverage endpoint implicitly sets margin mode.
11    ///
12    /// Note: OKX sets margin mode per-instrument via the set-leverage endpoint's
13    /// `mgnMode` parameter. This method provides a dedicated interface.
14    pub async fn set_margin_mode_impl(&self, symbol: &str, mode: &str) -> Result<()> {
15        let inst_id = Self::symbol_to_inst_id(symbol);
16
17        let mgn_mode = match mode.to_lowercase().as_str() {
18            "isolated" => "isolated",
19            "cross" | "crossed" => "cross",
20            _ => {
21                return Err(Error::invalid_request(format!(
22                    "Invalid margin mode: {}. Must be 'isolated' or 'cross'",
23                    mode
24                )));
25            }
26        };
27
28        // OKX sets margin mode through the set-leverage endpoint
29        // We need to get current leverage first, then re-set it with the new margin mode
30        let current_leverage = self.get_leverage_impl(symbol).await.unwrap_or(10);
31
32        let mut builder = self
33            .signed_request("/api/v5/account/set-leverage")
34            .method(HttpMethod::Post)
35            .param("instId", &inst_id)
36            .param("lever", current_leverage.to_string())
37            .param("mgnMode", mgn_mode);
38
39        if mgn_mode == "isolated" {
40            builder = builder.param("posSide", "net");
41        }
42
43        let data = builder.execute().await?;
44
45        // Check for nested error
46        if let Some(arr) = data["data"].as_array() {
47            if let Some(first) = arr.first() {
48                if let Some(code) = first["sCode"].as_str() {
49                    if code != "0" {
50                        let msg = first["sMsg"].as_str().unwrap_or("Unknown error");
51                        return Err(Error::exchange(code, msg));
52                    }
53                }
54            }
55        }
56
57        Ok(())
58    }
59}