use nautilus_model::enums::{
AggressorSide, GreeksConvention, LiquiditySide, OptionKind, OrderSide, OrderSideSpecified,
OrderStatus, OrderType, PositionSide, TriggerType,
};
use serde::{Deserialize, Serialize};
use strum::{AsRefStr, Display, EnumIter, EnumString};
use crate::common::consts::{OKX_ADVANCE_ALGO_ORDER_TYPES, OKX_CONDITIONAL_ORDER_TYPES};
#[derive(
Copy,
Clone,
Debug,
Display,
PartialEq,
Eq,
Hash,
AsRefStr,
EnumIter,
EnumString,
Serialize,
Deserialize,
)]
#[serde(rename_all = "lowercase")]
pub enum OKXBookAction {
Update,
Snapshot,
}
#[derive(
Copy,
Clone,
Debug,
Display,
PartialEq,
Eq,
Hash,
AsRefStr,
EnumIter,
EnumString,
Serialize,
Deserialize,
)]
pub enum OKXCandleConfirm {
#[serde(rename = "0")]
Partial,
#[serde(rename = "1")]
Closed,
}
#[derive(
Copy,
Clone,
Debug,
Display,
PartialEq,
Eq,
Hash,
AsRefStr,
EnumIter,
EnumString,
Serialize,
Deserialize,
)]
#[serde(rename_all = "snake_case")]
pub enum OKXSide {
Buy,
Sell,
}
impl From<OrderSideSpecified> for OKXSide {
fn from(value: OrderSideSpecified) -> Self {
match value {
OrderSideSpecified::Buy => Self::Buy,
OrderSideSpecified::Sell => Self::Sell,
}
}
}
impl From<OKXSide> for AggressorSide {
fn from(value: OKXSide) -> Self {
match value {
OKXSide::Buy => Self::Buyer,
OKXSide::Sell => Self::Seller,
}
}
}
#[derive(
Copy,
Clone,
Debug,
Display,
PartialEq,
Eq,
Hash,
AsRefStr,
EnumIter,
EnumString,
Serialize,
Deserialize,
)]
#[serde(rename_all = "snake_case")]
pub enum OKXOrderType {
Market,
Limit,
#[serde(alias = "elp")]
Rpi,
PostOnly, Fok, Ioc, OptimalLimitIoc, Mmp, MmpAndPostOnly, OpFok, Trigger, }
#[derive(
Copy,
Clone,
Debug,
Display,
PartialEq,
Eq,
Hash,
AsRefStr,
EnumIter,
EnumString,
Serialize,
Deserialize,
)]
#[serde(rename_all = "snake_case")]
#[cfg_attr(
feature = "python",
pyo3::pyclass(
eq,
eq_int,
module = "nautilus_trader.core.nautilus_pyo3.okx",
from_py_object,
rename_all = "SCREAMING_SNAKE_CASE",
)
)]
#[cfg_attr(
feature = "python",
pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.adapters.okx")
)]
pub enum OKXOrderStatus {
Canceled,
Live,
PartiallyFilled,
Filled,
MmpCanceled,
}
impl TryFrom<OrderStatus> for OKXOrderStatus {
type Error = OrderStatus;
fn try_from(value: OrderStatus) -> Result<Self, Self::Error> {
match value {
OrderStatus::Canceled => Ok(Self::Canceled),
OrderStatus::Accepted => Ok(Self::Live),
OrderStatus::PartiallyFilled => Ok(Self::PartiallyFilled),
OrderStatus::Filled => Ok(Self::Filled),
other => Err(other),
}
}
}
#[derive(
Copy,
Clone,
Debug,
Default,
Display,
PartialEq,
Eq,
Hash,
AsRefStr,
EnumIter,
EnumString,
Serialize,
Deserialize,
)]
pub enum OKXExecType {
#[serde(rename = "")]
#[default]
None,
#[serde(rename = "T")]
Taker,
#[serde(rename = "M")]
Maker,
}
impl From<LiquiditySide> for OKXExecType {
fn from(value: LiquiditySide) -> Self {
match value {
LiquiditySide::NoLiquiditySide => Self::None,
LiquiditySide::Taker => Self::Taker,
LiquiditySide::Maker => Self::Maker,
}
}
}
#[derive(
Copy,
Clone,
Debug,
Display,
Default,
PartialEq,
Eq,
Hash,
AsRefStr,
EnumIter,
EnumString,
Serialize,
Deserialize,
)]
#[serde(rename_all = "UPPERCASE")]
#[cfg_attr(
feature = "python",
pyo3::pyclass(
eq,
eq_int,
module = "nautilus_trader.core.nautilus_pyo3.okx",
from_py_object,
rename_all = "SCREAMING_SNAKE_CASE",
)
)]
#[cfg_attr(
feature = "python",
pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.adapters.okx")
)]
pub enum OKXInstrumentType {
#[default]
Any,
Spot,
Margin,
Swap,
Futures,
Option,
Events,
}
#[derive(
Copy,
Clone,
Debug,
Default,
Display,
PartialEq,
Eq,
Hash,
AsRefStr,
EnumIter,
EnumString,
Serialize,
Deserialize,
)]
pub enum OKXInstrumentCategory {
#[serde(rename = "1")]
#[strum(serialize = "1")]
Crypto,
#[serde(rename = "3")]
#[strum(serialize = "3")]
Equity,
#[serde(rename = "4")]
#[strum(serialize = "4")]
Commodity,
#[serde(rename = "5")]
#[strum(serialize = "5")]
Fx,
#[serde(rename = "6")]
#[strum(serialize = "6")]
Debt,
#[default]
#[serde(other)]
#[strum(serialize = "")]
Unknown,
}
#[derive(
Copy,
Clone,
Debug,
Display,
PartialEq,
Eq,
Hash,
AsRefStr,
EnumIter,
EnumString,
Serialize,
Deserialize,
)]
#[serde(rename_all = "snake_case")]
pub enum OKXInstrumentStatus {
Live,
Suspend,
Preopen,
Test,
PostOnly,
Rebase,
Settling,
#[serde(other)]
Unknown,
}
#[derive(
Copy,
Clone,
Debug,
Display,
PartialEq,
Eq,
Hash,
AsRefStr,
EnumIter,
EnumString,
Serialize,
Deserialize,
)]
#[serde(rename_all = "snake_case")]
pub enum OKXSpreadType {
Linear,
Inverse,
Hybrid,
#[serde(other)]
Unknown,
}
#[derive(
Copy,
Clone,
Debug,
Display,
PartialEq,
Eq,
Hash,
AsRefStr,
EnumIter,
EnumString,
Serialize,
Deserialize,
)]
#[serde(rename_all = "snake_case")]
pub enum OKXSpreadState {
Live,
Suspend,
Expired,
#[serde(other)]
Unknown,
}
#[derive(
Copy,
Clone,
Default,
Debug,
Display,
PartialEq,
Eq,
Hash,
AsRefStr,
EnumIter,
EnumString,
Serialize,
Deserialize,
)]
#[serde(rename_all = "snake_case")]
#[cfg_attr(
feature = "python",
pyo3::pyclass(
eq,
eq_int,
module = "nautilus_trader.core.nautilus_pyo3.okx",
from_py_object,
rename_all = "SCREAMING_SNAKE_CASE",
)
)]
#[cfg_attr(
feature = "python",
pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.adapters.okx")
)]
pub enum OKXContractType {
#[serde(rename = "")]
#[default]
None,
Linear,
Inverse,
}
#[derive(
Copy,
Clone,
Debug,
Display,
PartialEq,
Eq,
Hash,
AsRefStr,
EnumIter,
EnumString,
Serialize,
Deserialize,
)]
pub enum OKXOptionType {
#[serde(rename = "")]
None,
#[serde(rename = "C")]
Call,
#[serde(rename = "P")]
Put,
}
impl TryFrom<OKXOptionType> for OptionKind {
type Error = OKXOptionType;
fn try_from(option_type: OKXOptionType) -> Result<Self, Self::Error> {
match option_type {
OKXOptionType::Call => Ok(Self::Call),
OKXOptionType::Put => Ok(Self::Put),
other => Err(other),
}
}
}
#[derive(
Copy,
Clone,
Debug,
Default,
Display,
PartialEq,
Eq,
Hash,
AsRefStr,
EnumIter,
EnumString,
Serialize,
Deserialize,
)]
#[serde(rename_all = "UPPERCASE")]
#[strum(serialize_all = "UPPERCASE", ascii_case_insensitive)]
#[cfg_attr(
feature = "python",
pyo3::pyclass(
eq,
eq_int,
module = "nautilus_trader.core.nautilus_pyo3.okx",
from_py_object,
rename_all = "SCREAMING_SNAKE_CASE",
)
)]
#[cfg_attr(
feature = "python",
pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.adapters.okx")
)]
pub enum OKXGreeksType {
#[default]
Bs = 0,
Pa = 1,
}
impl From<u8> for OKXGreeksType {
fn from(value: u8) -> Self {
match value {
0 => Self::Bs,
1 => Self::Pa,
_ => {
log::warn!("Invalid OKXGreeksType {value}, defaulting to Bs");
Self::Bs
}
}
}
}
impl From<GreeksConvention> for OKXGreeksType {
fn from(convention: GreeksConvention) -> Self {
match convention {
GreeksConvention::BlackScholes => Self::Bs,
GreeksConvention::PriceAdjusted => Self::Pa,
}
}
}
impl From<OKXGreeksType> for GreeksConvention {
fn from(greeks_type: OKXGreeksType) -> Self {
match greeks_type {
OKXGreeksType::Bs => Self::BlackScholes,
OKXGreeksType::Pa => Self::PriceAdjusted,
}
}
}
#[derive(
Copy,
Clone,
Debug,
Display,
Default,
PartialEq,
Eq,
Hash,
AsRefStr,
EnumIter,
EnumString,
Serialize,
Deserialize,
)]
#[serde(rename_all = "snake_case")]
#[strum(ascii_case_insensitive)]
#[cfg_attr(
feature = "python",
pyo3::pyclass(
eq,
eq_int,
module = "nautilus_trader.core.nautilus_pyo3.okx",
from_py_object,
rename_all = "SCREAMING_SNAKE_CASE",
)
)]
#[cfg_attr(
feature = "python",
pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.adapters.okx")
)]
pub enum OKXTradeMode {
#[default]
Cash,
Isolated,
Cross,
#[strum(serialize = "spot_isolated")]
SpotIsolated,
}
#[derive(
Copy,
Clone,
Debug,
Display,
PartialEq,
Eq,
Hash,
AsRefStr,
EnumIter,
EnumString,
Serialize,
Deserialize,
)]
pub enum OKXAccountMode {
#[serde(rename = "Spot mode")]
Spot,
#[serde(rename = "Spot and futures mode")]
SpotAndFutures,
#[serde(rename = "Multi-currency margin mode")]
MultiCurrencyMarginMode,
#[serde(rename = "Portfolio margin mode")]
PortfolioMarginMode,
}
#[derive(
Copy,
Clone,
Default,
Debug,
Display,
PartialEq,
Eq,
Hash,
AsRefStr,
EnumIter,
EnumString,
Serialize,
Deserialize,
)]
#[serde(rename_all = "snake_case")]
#[cfg_attr(
feature = "python",
pyo3::pyclass(
eq,
eq_int,
module = "nautilus_trader.core.nautilus_pyo3.okx",
from_py_object,
rename_all = "SCREAMING_SNAKE_CASE",
)
)]
#[cfg_attr(
feature = "python",
pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.adapters.okx")
)]
pub enum OKXMarginMode {
#[serde(rename = "")]
#[default]
None,
Isolated,
Cross,
}
#[derive(
Copy,
Clone,
Default,
Debug,
Display,
PartialEq,
Eq,
Hash,
AsRefStr,
EnumIter,
EnumString,
Serialize,
Deserialize,
)]
#[cfg_attr(
feature = "python",
pyo3::pyclass(
eq,
eq_int,
module = "nautilus_trader.core.nautilus_pyo3.okx",
from_py_object,
rename_all = "SCREAMING_SNAKE_CASE",
)
)]
#[cfg_attr(
feature = "python",
pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.adapters.okx")
)]
pub enum OKXPositionMode {
#[default]
#[serde(rename = "net_mode")]
NetMode,
#[serde(rename = "long_short_mode")]
LongShortMode,
}
#[derive(
Copy,
Clone,
Debug,
Display,
PartialEq,
Eq,
Hash,
AsRefStr,
EnumIter,
EnumString,
Serialize,
Deserialize,
)]
#[serde(rename_all = "snake_case")]
pub enum OKXPositionSide {
#[serde(rename = "")]
None,
Net,
Long,
Short,
}
#[derive(
Copy,
Clone,
Debug,
Default,
Display,
PartialEq,
Eq,
Hash,
AsRefStr,
EnumIter,
EnumString,
Serialize,
Deserialize,
)]
#[serde(rename_all = "snake_case")]
pub enum OKXSelfTradePreventionMode {
#[default]
#[serde(rename = "")]
None,
CancelMaker,
CancelTaker,
CancelBoth,
}
#[derive(
Copy,
Clone,
Debug,
Display,
PartialEq,
Eq,
Hash,
AsRefStr,
EnumIter,
EnumString,
Serialize,
Deserialize,
)]
#[serde(rename_all = "snake_case")]
pub enum OKXTakeProfitKind {
#[serde(rename = "")]
None,
Condition,
Limit,
}
#[derive(
Copy,
Clone,
Debug,
Default,
Display,
PartialEq,
Eq,
Hash,
AsRefStr,
EnumIter,
EnumString,
Serialize,
Deserialize,
)]
#[serde(rename_all = "snake_case")]
#[strum(serialize_all = "snake_case", ascii_case_insensitive)]
pub enum OKXTriggerType {
#[default]
#[serde(rename = "")]
None,
Last,
Index,
Mark,
}
impl From<TriggerType> for OKXTriggerType {
fn from(value: TriggerType) -> Self {
match value {
TriggerType::LastPrice => Self::Last,
TriggerType::MarkPrice => Self::Mark,
TriggerType::IndexPrice => Self::Index,
_ => Self::Last,
}
}
}
#[cfg(test)]
mod tests {
use std::str::FromStr;
use nautilus_model::enums::{GreeksConvention, OptionKind, OrderStatus, OrderType};
use rstest::rstest;
use super::{
OKXGreeksType, OKXOptionType, OKXOrderStatus, OKXOrderType, OKXRpiPermission,
OKXTriggerType,
};
#[rstest]
fn test_okx_trigger_type_from_str_accepts_snake_case_values() {
assert_eq!(
OKXTriggerType::from_str("last").unwrap(),
OKXTriggerType::Last
);
assert_eq!(
OKXTriggerType::from_str("mark").unwrap(),
OKXTriggerType::Mark
);
assert_eq!(
OKXTriggerType::from_str("index").unwrap(),
OKXTriggerType::Index
);
}
#[rstest]
#[case(OKXGreeksType::Bs, "\"BS\"")]
#[case(OKXGreeksType::Pa, "\"PA\"")]
fn test_greeks_type_serde_roundtrip(#[case] input: OKXGreeksType, #[case] expected: &str) {
let json = serde_json::to_string(&input).unwrap();
assert_eq!(json, expected);
let parsed: OKXGreeksType = serde_json::from_str(expected).unwrap();
assert_eq!(parsed, input);
}
#[rstest]
fn test_greeks_type_default_is_bs() {
assert_eq!(OKXGreeksType::default(), OKXGreeksType::Bs);
}
#[rstest]
fn test_greeks_type_from_u8() {
assert_eq!(OKXGreeksType::from(0_u8), OKXGreeksType::Bs);
assert_eq!(OKXGreeksType::from(1_u8), OKXGreeksType::Pa);
assert_eq!(OKXGreeksType::from(99_u8), OKXGreeksType::Bs);
}
#[rstest]
#[case(GreeksConvention::BlackScholes, OKXGreeksType::Bs)]
#[case(GreeksConvention::PriceAdjusted, OKXGreeksType::Pa)]
fn test_greeks_type_convention_roundtrip(
#[case] convention: GreeksConvention,
#[case] expected: OKXGreeksType,
) {
let mapped: OKXGreeksType = convention.into();
assert_eq!(mapped, expected);
let back: GreeksConvention = mapped.into();
assert_eq!(back, convention);
}
#[rstest]
fn test_op_fok_serializes_to_snake_case() {
let json = serde_json::to_string(&OKXOrderType::OpFok).unwrap();
assert_eq!(json, "\"op_fok\"");
}
#[rstest]
fn test_op_fok_deserializes_from_snake_case() {
let parsed: OKXOrderType = serde_json::from_str("\"op_fok\"").unwrap();
assert_eq!(parsed, OKXOrderType::OpFok);
}
#[rstest]
fn test_op_fok_converts_to_limit_order_type() {
let order_type: OrderType = OKXOrderType::OpFok.into();
assert_eq!(order_type, OrderType::Limit);
}
#[rstest]
fn test_rpi_order_type_serializes_current_name_and_reads_legacy_alias() {
assert_eq!(
serde_json::to_string(&OKXOrderType::Rpi).unwrap(),
"\"rpi\""
);
assert_eq!(
serde_json::from_str::<OKXOrderType>("\"elp\"").unwrap(),
OKXOrderType::Rpi
);
assert_eq!(OrderType::from(OKXOrderType::Rpi), OrderType::Limit);
}
#[rstest]
#[case("\"0\"", OKXRpiPermission::Disabled)]
#[case("\"1\"", OKXRpiPermission::Enabled)]
#[case("\"2\"", OKXRpiPermission::Permitted)]
fn test_rpi_permission_deserializes_string_codes(
#[case] json: &str,
#[case] expected: OKXRpiPermission,
) {
assert_eq!(
serde_json::from_str::<OKXRpiPermission>(json).unwrap(),
expected
);
}
#[rstest]
#[case::call(OKXOptionType::Call, Ok(OptionKind::Call))]
#[case::put(OKXOptionType::Put, Ok(OptionKind::Put))]
#[case::none(OKXOptionType::None, Err(OKXOptionType::None))]
fn test_try_from_okx_option_type(
#[case] input: OKXOptionType,
#[case] expected: Result<OptionKind, OKXOptionType>,
) {
let actual: Result<OptionKind, OKXOptionType> = input.try_into();
assert_eq!(actual, expected);
}
#[rstest]
#[case::canceled(OrderStatus::Canceled, Ok(OKXOrderStatus::Canceled))]
#[case::accepted(OrderStatus::Accepted, Ok(OKXOrderStatus::Live))]
#[case::partially_filled(OrderStatus::PartiallyFilled, Ok(OKXOrderStatus::PartiallyFilled))]
#[case::filled(OrderStatus::Filled, Ok(OKXOrderStatus::Filled))]
#[case::submitted(OrderStatus::Submitted, Err(OrderStatus::Submitted))]
#[case::pending_update(OrderStatus::PendingUpdate, Err(OrderStatus::PendingUpdate))]
#[case::pending_cancel(OrderStatus::PendingCancel, Err(OrderStatus::PendingCancel))]
#[case::triggered(OrderStatus::Triggered, Err(OrderStatus::Triggered))]
#[case::expired(OrderStatus::Expired, Err(OrderStatus::Expired))]
#[case::rejected(OrderStatus::Rejected, Err(OrderStatus::Rejected))]
fn test_try_from_order_status(
#[case] input: OrderStatus,
#[case] expected: Result<OKXOrderStatus, OrderStatus>,
) {
let actual: Result<OKXOrderStatus, OrderStatus> = input.try_into();
assert_eq!(actual, expected);
}
}
#[derive(
Copy,
Clone,
Debug,
Display,
PartialEq,
Eq,
Hash,
AsRefStr,
EnumIter,
EnumString,
Serialize,
Deserialize,
)]
#[serde(rename_all = "snake_case")]
#[strum(serialize_all = "snake_case")]
pub enum OKXTargetCurrency {
BaseCcy,
QuoteCcy,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum OKXBookChannel {
Book,
BookL2Tbt,
Books50L2Tbt,
BooksRpi,
SprdBooks5,
}
#[derive(
Copy,
Clone,
Debug,
Display,
PartialEq,
Eq,
Hash,
AsRefStr,
EnumIter,
EnumString,
Serialize,
Deserialize,
)]
pub enum OKXRpiPermission {
#[serde(rename = "0")]
Disabled,
#[serde(rename = "1")]
Enabled,
#[serde(rename = "2")]
Permitted,
}
#[derive(
Copy,
Clone,
Debug,
Display,
PartialEq,
Eq,
PartialOrd,
Ord,
Hash,
AsRefStr,
EnumIter,
EnumString,
Serialize,
Deserialize,
)]
#[cfg_attr(
feature = "python",
pyo3::pyclass(
module = "nautilus_trader.core.nautilus_pyo3.okx",
from_py_object,
rename_all = "SCREAMING_SNAKE_CASE",
)
)]
#[cfg_attr(
feature = "python",
pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.adapters.okx")
)]
pub enum OKXVipLevel {
#[serde(rename = "0")]
#[strum(serialize = "0")]
Vip0 = 0,
#[serde(rename = "1")]
#[strum(serialize = "1")]
Vip1 = 1,
#[serde(rename = "2")]
#[strum(serialize = "2")]
Vip2 = 2,
#[serde(rename = "3")]
#[strum(serialize = "3")]
Vip3 = 3,
#[serde(rename = "4")]
#[strum(serialize = "4")]
Vip4 = 4,
#[serde(rename = "5")]
#[strum(serialize = "5")]
Vip5 = 5,
#[serde(rename = "6")]
#[strum(serialize = "6")]
Vip6 = 6,
#[serde(rename = "7")]
#[strum(serialize = "7")]
Vip7 = 7,
#[serde(rename = "8")]
#[strum(serialize = "8")]
Vip8 = 8,
#[serde(rename = "9")]
#[strum(serialize = "9")]
Vip9 = 9,
}
impl From<u8> for OKXVipLevel {
fn from(value: u8) -> Self {
match value {
0 => Self::Vip0,
1 => Self::Vip1,
2 => Self::Vip2,
3 => Self::Vip3,
4 => Self::Vip4,
5 => Self::Vip5,
6 => Self::Vip6,
7 => Self::Vip7,
8 => Self::Vip8,
9 => Self::Vip9,
_ => {
log::warn!("Invalid VIP level {value}, defaulting to Vip0");
Self::Vip0
}
}
}
}
impl From<OKXSide> for OrderSide {
fn from(side: OKXSide) -> Self {
match side {
OKXSide::Buy => Self::Buy,
OKXSide::Sell => Self::Sell,
}
}
}
impl From<OKXExecType> for LiquiditySide {
fn from(exec: OKXExecType) -> Self {
match exec {
OKXExecType::Maker => Self::Maker,
OKXExecType::Taker => Self::Taker,
OKXExecType::None => Self::NoLiquiditySide,
}
}
}
impl From<OKXPositionSide> for PositionSide {
fn from(side: OKXPositionSide) -> Self {
match side {
OKXPositionSide::Long => Self::Long,
OKXPositionSide::Short => Self::Short,
_ => Self::Flat,
}
}
}
impl From<OKXOrderStatus> for OrderStatus {
fn from(status: OKXOrderStatus) -> Self {
match status {
OKXOrderStatus::Live => Self::Accepted,
OKXOrderStatus::PartiallyFilled => Self::PartiallyFilled,
OKXOrderStatus::Filled => Self::Filled,
OKXOrderStatus::Canceled | OKXOrderStatus::MmpCanceled => Self::Canceled,
}
}
}
impl From<OKXAlgoOrderStatus> for OrderStatus {
fn from(status: OKXAlgoOrderStatus) -> Self {
match status {
OKXAlgoOrderStatus::Live | OKXAlgoOrderStatus::Pause => Self::Accepted,
OKXAlgoOrderStatus::Effective
| OKXAlgoOrderStatus::OrderPlaced
| OKXAlgoOrderStatus::PartiallyEffective => Self::Triggered,
OKXAlgoOrderStatus::Filled => Self::Filled,
OKXAlgoOrderStatus::Canceled => Self::Canceled,
OKXAlgoOrderStatus::OrderFailed | OKXAlgoOrderStatus::PartiallyFailed => Self::Rejected,
}
}
}
impl From<OKXOrderType> for OrderType {
fn from(ord_type: OKXOrderType) -> Self {
match ord_type {
OKXOrderType::Market => Self::Market,
OKXOrderType::Limit
| OKXOrderType::Rpi
| OKXOrderType::PostOnly
| OKXOrderType::OptimalLimitIoc
| OKXOrderType::Mmp
| OKXOrderType::MmpAndPostOnly
| OKXOrderType::Fok
| OKXOrderType::OpFok
| OKXOrderType::Ioc => Self::Limit,
OKXOrderType::Trigger => Self::StopMarket,
}
}
}
impl From<OrderType> for OKXOrderType {
fn from(value: OrderType) -> Self {
match value {
OrderType::Market => Self::Market,
OrderType::Limit => Self::Limit,
OrderType::MarketToLimit => Self::Ioc,
OrderType::StopMarket
| OrderType::StopLimit
| OrderType::MarketIfTouched
| OrderType::LimitIfTouched
| OrderType::TrailingStopMarket => {
panic!("Conditional order types must use OKXAlgoOrderType")
}
_ => panic!("Invalid `OrderType` cannot be represented on OKX: {value:?}"),
}
}
}
impl From<PositionSide> for OKXPositionSide {
fn from(value: PositionSide) -> Self {
match value {
PositionSide::Long => Self::Long,
PositionSide::Short => Self::Short,
_ => Self::None,
}
}
}
#[derive(
Copy,
Clone,
Debug,
Display,
PartialEq,
Eq,
Hash,
AsRefStr,
EnumIter,
EnumString,
Serialize,
Deserialize,
)]
#[serde(rename_all = "snake_case")]
pub enum OKXAlgoOrderType {
Conditional,
Oco,
Trigger,
MoveOrderStop,
Iceberg,
Twap,
}
pub fn is_conditional_order(order_type: OrderType) -> bool {
OKX_CONDITIONAL_ORDER_TYPES.contains(&order_type)
}
pub fn is_advance_algo_order(order_type: OrderType) -> bool {
OKX_ADVANCE_ALGO_ORDER_TYPES.contains(&order_type)
}
pub fn conditional_order_to_algo_type(order_type: OrderType) -> anyhow::Result<OKXAlgoOrderType> {
match order_type {
OrderType::StopMarket
| OrderType::StopLimit
| OrderType::MarketIfTouched
| OrderType::LimitIfTouched => Ok(OKXAlgoOrderType::Trigger),
OrderType::TrailingStopMarket => Ok(OKXAlgoOrderType::MoveOrderStop),
_ => anyhow::bail!("Not a conditional order type: {order_type:?}"),
}
}
#[derive(
Copy,
Clone,
Debug,
Display,
PartialEq,
Eq,
Hash,
AsRefStr,
EnumIter,
EnumString,
Serialize,
Deserialize,
)]
#[serde(rename_all = "snake_case")]
#[cfg_attr(
feature = "python",
pyo3::pyclass(
eq,
eq_int,
module = "nautilus_trader.core.nautilus_pyo3.okx",
from_py_object,
rename_all = "SCREAMING_SNAKE_CASE",
)
)]
#[cfg_attr(
feature = "python",
pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.adapters.okx")
)]
pub enum OKXAlgoOrderStatus {
Live,
Pause,
Effective,
OrderPlaced,
PartiallyEffective,
Canceled,
Filled,
OrderFailed,
PartiallyFailed,
}
#[derive(
Copy,
Clone,
Debug,
Display,
PartialEq,
Eq,
Hash,
AsRefStr,
EnumIter,
EnumString,
Serialize,
Deserialize,
)]
#[serde(rename_all = "snake_case")]
pub enum OKXOrderCategory {
Normal,
FullLiquidation,
PartialLiquidation,
Adl,
Twap,
Iceberg,
Oco,
Conditional,
MoveOrderStop,
Ddh,
Delivery,
#[serde(other)]
Other,
}
#[derive(
Copy,
Clone,
Debug,
Display,
PartialEq,
Eq,
Hash,
AsRefStr,
EnumIter,
EnumString,
Serialize,
Deserialize,
)]
pub enum OKXBarSize {
#[serde(rename = "1s")]
Second1,
#[serde(rename = "1m")]
Minute1,
#[serde(rename = "3m")]
Minute3,
#[serde(rename = "5m")]
Minute5,
#[serde(rename = "15m")]
Minute15,
#[serde(rename = "30m")]
Minute30,
#[serde(rename = "1H")]
Hour1,
#[serde(rename = "2H")]
Hour2,
#[serde(rename = "4H")]
Hour4,
#[serde(rename = "6H")]
Hour6,
#[serde(rename = "12H")]
Hour12,
#[serde(rename = "1D")]
Day1,
#[serde(rename = "2D")]
Day2,
#[serde(rename = "3D")]
Day3,
#[serde(rename = "5D")]
Day5,
#[serde(rename = "1W")]
Week1,
#[serde(rename = "1M")]
Month1,
#[serde(rename = "3M")]
Month3,
}
#[derive(
Copy,
Clone,
Debug,
Default,
Display,
PartialEq,
Eq,
Hash,
AsRefStr,
EnumIter,
EnumString,
Serialize,
Deserialize,
)]
#[serde(rename_all = "snake_case")]
pub enum OKXPriceType {
#[default]
#[serde(rename = "")]
None,
Px,
Usd,
Vol,
}
#[derive(
Copy,
Clone,
Debug,
Default,
Display,
PartialEq,
Eq,
Hash,
AsRefStr,
EnumIter,
EnumString,
Serialize,
Deserialize,
)]
#[serde(rename_all = "snake_case")]
pub enum OKXSettlementState {
#[default]
#[serde(rename = "")]
None,
Processing,
Settled,
}
#[derive(
Copy,
Clone,
Debug,
Default,
Display,
PartialEq,
Eq,
Hash,
AsRefStr,
EnumIter,
EnumString,
Serialize,
Deserialize,
)]
#[serde(rename_all = "snake_case")]
pub enum OKXQuickMarginType {
#[default]
#[serde(rename = "")]
None,
Manual,
AutoBorrow,
AutoRepay,
}
#[derive(
Copy,
Clone,
Debug,
Default,
Display,
PartialEq,
Eq,
Hash,
AsRefStr,
EnumIter,
EnumString,
Serialize,
Deserialize,
)]
#[serde(rename_all = "lowercase")]
#[strum(ascii_case_insensitive, serialize_all = "lowercase")]
#[cfg_attr(
feature = "python",
pyo3::pyclass(
eq,
eq_int,
module = "nautilus_trader.core.nautilus_pyo3.okx",
from_py_object,
rename_all = "SCREAMING_SNAKE_CASE",
)
)]
#[cfg_attr(
feature = "python",
pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.adapters.okx")
)]
pub enum OKXEnvironment {
#[default]
Live,
Demo,
}
#[derive(
Copy,
Clone,
Debug,
Default,
Display,
PartialEq,
Eq,
Hash,
AsRefStr,
EnumIter,
EnumString,
Serialize,
Deserialize,
)]
#[serde(rename_all = "lowercase")]
#[strum(ascii_case_insensitive, serialize_all = "lowercase")]
#[cfg_attr(
feature = "python",
pyo3::pyclass(
eq,
eq_int,
module = "nautilus_trader.core.nautilus_pyo3.okx",
from_py_object,
rename_all = "SCREAMING_SNAKE_CASE",
)
)]
#[cfg_attr(
feature = "python",
pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.adapters.okx")
)]
pub enum OKXRegion {
#[default]
Global,
Eea,
Us,
}