use nautilus_model::identifiers::{AccountId, TraderId};
use crate::common::{
credential::credential_env_vars,
enums::{OKXContractType, OKXInstrumentType, OKXMarginMode, OKXVipLevel},
urls::{
get_http_base_url, get_ws_base_url_business, get_ws_base_url_private,
get_ws_base_url_public,
},
};
#[derive(Clone, Debug, bon::Builder)]
#[cfg_attr(
feature = "python",
pyo3::pyclass(module = "nautilus_trader.core.nautilus_pyo3.okx", from_py_object)
)]
#[cfg_attr(
feature = "python",
pyo3_stub_gen::derive::gen_stub_pyclass(module = "nautilus_trader.okx")
)]
pub struct OKXDataClientConfig {
pub api_key: Option<String>,
pub api_secret: Option<String>,
pub api_passphrase: Option<String>,
#[builder(default = vec![OKXInstrumentType::Spot])]
pub instrument_types: Vec<OKXInstrumentType>,
pub contract_types: Option<Vec<OKXContractType>>,
pub instrument_families: Option<Vec<String>>,
pub base_url_http: Option<String>,
pub base_url_ws_public: Option<String>,
pub base_url_ws_business: Option<String>,
pub http_proxy_url: Option<String>,
pub ws_proxy_url: Option<String>,
#[builder(default)]
pub is_demo: bool,
#[builder(default = 60)]
pub http_timeout_secs: u64,
#[builder(default = 3)]
pub max_retries: u32,
#[builder(default = 1_000)]
pub retry_delay_initial_ms: u64,
#[builder(default = 10_000)]
pub retry_delay_max_ms: u64,
#[builder(default = 60)]
pub update_instruments_interval_mins: u64,
pub vip_level: Option<OKXVipLevel>,
}
impl Default for OKXDataClientConfig {
fn default() -> Self {
Self::builder().build()
}
}
impl OKXDataClientConfig {
#[must_use]
pub fn new() -> Self {
Self::default()
}
#[must_use]
pub fn has_api_credentials(&self) -> bool {
let (key_var, secret_var, passphrase_var) = credential_env_vars();
let has_key = self.api_key.is_some() || std::env::var(key_var).is_ok();
let has_secret = self.api_secret.is_some() || std::env::var(secret_var).is_ok();
let has_passphrase = self.api_passphrase.is_some() || std::env::var(passphrase_var).is_ok();
has_key && has_secret && has_passphrase
}
#[must_use]
pub fn http_base_url(&self) -> String {
self.base_url_http
.clone()
.unwrap_or_else(|| get_http_base_url().to_string())
}
#[must_use]
pub fn ws_public_url(&self) -> String {
self.base_url_ws_public
.clone()
.unwrap_or_else(|| get_ws_base_url_public(self.is_demo).to_string())
}
#[must_use]
pub fn ws_business_url(&self) -> String {
self.base_url_ws_business
.clone()
.unwrap_or_else(|| get_ws_base_url_business(self.is_demo).to_string())
}
#[must_use]
pub fn requires_business_ws(&self) -> bool {
true
}
}
#[derive(Clone, Debug, bon::Builder)]
#[cfg_attr(
feature = "python",
pyo3::pyclass(module = "nautilus_trader.core.nautilus_pyo3.okx", from_py_object)
)]
#[cfg_attr(
feature = "python",
pyo3_stub_gen::derive::gen_stub_pyclass(module = "nautilus_trader.okx")
)]
pub struct OKXExecClientConfig {
#[builder(default = TraderId::from("TRADER-001"))]
pub trader_id: TraderId,
#[builder(default = AccountId::from("OKX-001"))]
pub account_id: AccountId,
pub api_key: Option<String>,
pub api_secret: Option<String>,
pub api_passphrase: Option<String>,
#[builder(default = vec![OKXInstrumentType::Spot])]
pub instrument_types: Vec<OKXInstrumentType>,
pub contract_types: Option<Vec<OKXContractType>>,
pub instrument_families: Option<Vec<String>>,
pub base_url_http: Option<String>,
pub base_url_ws_private: Option<String>,
pub base_url_ws_business: Option<String>,
pub http_proxy_url: Option<String>,
pub ws_proxy_url: Option<String>,
#[builder(default)]
pub is_demo: bool,
#[builder(default = 60)]
pub http_timeout_secs: u64,
#[builder(default)]
pub use_fills_channel: bool,
#[builder(default)]
pub use_mm_mass_cancel: bool,
#[builder(default = 3)]
pub max_retries: u32,
#[builder(default = 1_000)]
pub retry_delay_initial_ms: u64,
#[builder(default = 10_000)]
pub retry_delay_max_ms: u64,
pub margin_mode: Option<OKXMarginMode>,
#[builder(default)]
pub use_spot_margin: bool,
}
impl Default for OKXExecClientConfig {
fn default() -> Self {
Self::builder().build()
}
}
impl OKXExecClientConfig {
#[must_use]
pub fn new() -> Self {
Self::default()
}
#[must_use]
pub fn has_api_credentials(&self) -> bool {
let (key_var, secret_var, passphrase_var) = credential_env_vars();
let has_key = self.api_key.is_some() || std::env::var(key_var).is_ok();
let has_secret = self.api_secret.is_some() || std::env::var(secret_var).is_ok();
let has_passphrase = self.api_passphrase.is_some() || std::env::var(passphrase_var).is_ok();
has_key && has_secret && has_passphrase
}
#[must_use]
pub fn http_base_url(&self) -> String {
self.base_url_http
.clone()
.unwrap_or_else(|| get_http_base_url().to_string())
}
#[must_use]
pub fn ws_private_url(&self) -> String {
self.base_url_ws_private
.clone()
.unwrap_or_else(|| get_ws_base_url_private(self.is_demo).to_string())
}
#[must_use]
pub fn ws_business_url(&self) -> String {
self.base_url_ws_business
.clone()
.unwrap_or_else(|| get_ws_base_url_business(self.is_demo).to_string())
}
}