Skip to main content

nautilus_okx/common/
models.rs

1// -------------------------------------------------------------------------------------------------
2//  Copyright (C) 2015-2026 Nautech Systems Pty Ltd. All rights reserved.
3//  https://nautechsystems.io
4//
5//  Licensed under the GNU Lesser General Public License Version 3.0 (the "License");
6//  You may not use this file except in compliance with the License.
7//  You may obtain a copy of the License at https://www.gnu.org/licenses/lgpl-3.0.en.html
8//
9//  Unless required by applicable law or agreed to in writing, software
10//  distributed under the License is distributed on an "AS IS" BASIS,
11//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//  See the License for the specific language governing permissions and
13//  limitations under the License.
14// -------------------------------------------------------------------------------------------------
15
16//! Data models representing OKX API payloads consumed by the adapter.
17
18use nautilus_core::serialization::{
19    deserialize_decimal_from_str, deserialize_optional_decimal_from_str, deserialize_string_to_u64,
20    serialize_decimal_as_str, serialize_optional_decimal_as_str,
21};
22use rust_decimal::Decimal;
23use serde::{Deserialize, Serialize, Serializer};
24use ustr::Ustr;
25
26use super::enums::{OKXOptionType, OKXTriggerType};
27use crate::common::{
28    enums::{
29        OKXContractType, OKXInstrumentCategory, OKXInstrumentStatus, OKXInstrumentType,
30        OKXRpiPermission,
31    },
32    parse::{deserialize_empty_ustr_as_none, deserialize_optional_string_to_u64},
33};
34
35/// Attached TP/SL child order metadata returned by OKX on parent orders.
36#[derive(Clone, Debug, Default, Serialize, Deserialize)]
37#[serde(rename_all = "camelCase")]
38pub struct OKXAttachedAlgoOrd {
39    /// Attached algo order ID, if assigned by OKX.
40    #[serde(default)]
41    pub attach_algo_id: String,
42    /// Attached child client order ID.
43    #[serde(default)]
44    pub attach_algo_cl_ord_id: String,
45    /// Stop-loss trigger price.
46    #[serde(default)]
47    pub sl_trigger_px: String,
48    /// Stop-loss order price.
49    #[serde(default)]
50    pub sl_ord_px: String,
51    /// Stop-loss trigger price type.
52    #[serde(default)]
53    pub sl_trigger_px_type: Option<OKXTriggerType>,
54    /// Take-profit trigger price.
55    #[serde(default)]
56    pub tp_trigger_px: String,
57    /// Take-profit order price.
58    #[serde(default)]
59    pub tp_ord_px: String,
60    /// Take-profit trigger price type.
61    #[serde(default)]
62    pub tp_trigger_px_type: Option<OKXTriggerType>,
63    /// Callback ratio for attached trailing stop orders.
64    #[serde(default)]
65    pub callback_ratio: String,
66    /// Callback spread for attached trailing stop orders.
67    #[serde(default)]
68    pub callback_spread: String,
69    /// Activation price for attached trailing stop orders.
70    #[serde(default)]
71    pub active_px: String,
72}
73
74/// Represents a Retail Price Improvement order book level.
75#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
76pub struct OKXRpiBookLevel(
77    /// Price.
78    #[serde(
79        serialize_with = "serialize_decimal_as_str",
80        deserialize_with = "deserialize_decimal_from_str"
81    )]
82    pub Decimal,
83    /// Total quantity, including RPI liquidity.
84    #[serde(
85        serialize_with = "serialize_decimal_as_str",
86        deserialize_with = "deserialize_decimal_from_str"
87    )]
88    pub Decimal,
89    /// Quantity excluding RPI liquidity.
90    #[serde(
91        serialize_with = "serialize_decimal_as_str",
92        deserialize_with = "deserialize_decimal_from_str"
93    )]
94    pub Decimal,
95    /// Number of orders at this price.
96    #[serde(
97        serialize_with = "serialize_u64_as_str",
98        deserialize_with = "deserialize_string_to_u64"
99    )]
100    pub u64,
101);
102
103fn serialize_u64_as_str<S>(value: &u64, serializer: S) -> Result<S::Ok, S::Error>
104where
105    S: Serializer,
106{
107    serializer.serialize_str(&value.to_string())
108}
109
110/// Represents an instrument on the OKX exchange.
111#[derive(Clone, Debug, Serialize, Deserialize)]
112#[serde(rename_all = "camelCase")]
113pub struct OKXInstrument {
114    /// Product type (SPOT, MARGIN, SWAP, FUTURES, OPTION).
115    pub inst_type: OKXInstrumentType,
116    /// Instrument ID, e.g. "BTC-USD-SWAP".
117    pub inst_id: Ustr,
118    /// Instrument ID code (numeric). Required for WebSocket order operations.
119    /// E.g., 10458 for BTC-USD-SWAP.
120    #[serde(default)]
121    pub inst_id_code: Option<u64>,
122    /// Underlying of the instrument, e.g. "BTC-USD". Only applicable to FUTURES/SWAP/OPTION.
123    pub uly: Ustr,
124    /// Instrument family, e.g. "BTC-USD". Only applicable to FUTURES/SWAP/OPTION.
125    pub inst_family: Ustr,
126    /// Event contract series ID. Only applicable to EVENTS.
127    #[serde(default, deserialize_with = "deserialize_empty_ustr_as_none")]
128    pub series_id: Option<Ustr>,
129    /// Instrument category (the OKX `instCategory` field; the deprecated, distinct
130    /// `category` field is intentionally ignored).
131    #[serde(default)]
132    pub inst_category: Option<OKXInstrumentCategory>,
133    /// Initial price-limit band for newly listed contracts.
134    #[serde(default)]
135    pub init_px_lmt_pct: String,
136    /// Floating price-limit band during normal trading.
137    #[serde(default)]
138    pub float_px_lmt_pct: String,
139    /// Maximum price-limit cap.
140    #[serde(default)]
141    pub max_px_lmt_pct: String,
142    /// Base currency, e.g. "BTC" in BTC-USDT. Applicable to SPOT/MARGIN.
143    pub base_ccy: Ustr,
144    /// Quote currency, e.g. "USDT" in BTC-USDT.
145    pub quote_ccy: Ustr,
146    /// Settlement currency, e.g. "BTC" for BTC-USD-SWAP.
147    pub settle_ccy: Ustr,
148    /// Contract value. Only applicable to FUTURES/SWAP/OPTION.
149    pub ct_val: String,
150    /// Contract multiplier. Only applicable to FUTURES/SWAP/OPTION.
151    pub ct_mult: String,
152    /// Contract value currency. Only applicable to FUTURES/SWAP/OPTION.
153    pub ct_val_ccy: String,
154    /// Option type, "C" for call options, "P" for put options. Only applicable to OPTION.
155    pub opt_type: OKXOptionType,
156    /// Strike price. Only applicable to OPTION.
157    pub stk: String,
158    /// Listing time, Unix timestamp format in milliseconds, e.g. "1597026383085".
159    #[serde(deserialize_with = "deserialize_optional_string_to_u64")]
160    pub list_time: Option<u64>,
161    /// Expiry time, Unix timestamp format in milliseconds, e.g. "1597026383085".
162    #[serde(deserialize_with = "deserialize_optional_string_to_u64")]
163    pub exp_time: Option<u64>,
164    /// Leverage. Not applicable to SPOT.
165    pub lever: String,
166    /// Tick size, e.g. "0.1".
167    pub tick_sz: String,
168    /// Lot size, e.g. "1".
169    pub lot_sz: String,
170    /// Minimum order size.
171    pub min_sz: String,
172    /// Contract type. linear: "linear", inverse: "inverse". Only applicable to FUTURES/SWAP.
173    pub ct_type: OKXContractType,
174    /// Instrument status.
175    pub state: OKXInstrumentStatus,
176    /// Rule type, e.g. "DynamicPL", "CT", etc.
177    pub rule_type: String,
178    /// Maximum limit order size.
179    #[serde(default)]
180    pub max_lmt_sz: String,
181    /// Maximum market order size.
182    #[serde(default)]
183    pub max_mkt_sz: String,
184    /// Maximum limit order amount.
185    #[serde(default)]
186    pub max_lmt_amt: String,
187    /// Maximum market order amount.
188    #[serde(default)]
189    pub max_mkt_amt: String,
190    /// Maximum TWAP order size.
191    #[serde(default)]
192    pub max_twap_sz: String,
193    /// Maximum iceberg order size.
194    #[serde(default)]
195    pub max_iceberg_sz: String,
196    /// Maximum trigger order size.
197    #[serde(default)]
198    pub max_trigger_sz: String,
199    /// Maximum stop order size.
200    #[serde(default)]
201    pub max_stop_sz: String,
202    /// RPI maker permission: 0 disabled, 1 enabled without permission, 2 permitted.
203    #[serde(default, alias = "elp")]
204    pub rpi: Option<OKXRpiPermission>,
205    /// Minimum number of price levels between RPI buy and sell orders.
206    #[serde(default, deserialize_with = "deserialize_optional_string_to_u64")]
207    pub rpi_min_level: Option<u64>,
208    /// Minimum distance from the opposite organic best price, in basis points.
209    #[serde(
210        default,
211        serialize_with = "serialize_optional_decimal_as_str",
212        deserialize_with = "deserialize_optional_decimal_from_str"
213    )]
214    pub rpi_min_px_band: Option<Decimal>,
215}