1use std::fmt::Display;
19
20use nautilus_model::enums::{MarketStatusAction, TimeInForce, TriggerType};
21use serde::{Deserialize, Serialize};
22use strum::{AsRefStr, Display as StrumDisplay, EnumIter, EnumString};
23
24#[derive(
26 Clone,
27 Copy,
28 Debug,
29 PartialEq,
30 Eq,
31 Hash,
32 AsRefStr,
33 StrumDisplay,
34 EnumIter,
35 EnumString,
36 Serialize,
37 Deserialize,
38)]
39#[serde(rename_all = "snake_case")]
40#[strum(serialize_all = "snake_case")]
41#[cfg_attr(
42 feature = "python",
43 pyo3::pyclass(
44 eq,
45 eq_int,
46 module = "nautilus_trader.core.nautilus_pyo3.deribit",
47 from_py_object,
48 rename_all = "SCREAMING_SNAKE_CASE",
49 )
50)]
51#[cfg_attr(
52 feature = "python",
53 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.deribit")
54)]
55pub enum DeribitProductType {
56 Future,
58 Option,
60 Spot,
62 #[serde(rename = "future_combo")]
64 FutureCombo,
65 #[serde(rename = "option_combo")]
67 OptionCombo,
68}
69
70#[derive(
72 Clone, Copy, Debug, PartialEq, Eq, Hash, AsRefStr, EnumIter, EnumString, Serialize, Deserialize,
73)]
74#[serde(rename_all = "UPPERCASE")]
75#[strum(serialize_all = "UPPERCASE")]
76#[cfg_attr(
77 feature = "python",
78 pyo3::pyclass(
79 eq,
80 eq_int,
81 module = "nautilus_trader.core.nautilus_pyo3.deribit",
82 from_py_object,
83 rename_all = "SCREAMING_SNAKE_CASE",
84 )
85)]
86#[cfg_attr(
87 feature = "python",
88 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.deribit")
89)]
90pub enum DeribitCurrency {
91 BTC,
93 ETH,
95 USDC,
97 USDT,
99 EURR,
101 #[serde(rename = "any")]
103 ANY,
104}
105
106impl DeribitCurrency {
107 #[must_use]
109 pub fn as_str(&self) -> &'static str {
110 match self {
111 Self::BTC => "BTC",
112 Self::ETH => "ETH",
113 Self::USDC => "USDC",
114 Self::USDT => "USDT",
115 Self::EURR => "EURR",
116 Self::ANY => "any",
117 }
118 }
119}
120
121impl Display for DeribitCurrency {
122 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
123 write!(f, "{}", self.as_str())
124 }
125}
126
127#[derive(
129 Clone,
130 Copy,
131 Debug,
132 PartialEq,
133 Eq,
134 Hash,
135 AsRefStr,
136 StrumDisplay,
137 EnumIter,
138 EnumString,
139 Serialize,
140 Deserialize,
141)]
142#[serde(rename_all = "lowercase")]
143#[strum(serialize_all = "lowercase")]
144pub enum DeribitOptionType {
145 Call,
147 Put,
149}
150
151#[derive(
153 Clone, Copy, Debug, PartialEq, Eq, Hash, AsRefStr, EnumIter, EnumString, Serialize, Deserialize,
154)]
155#[serde(rename_all = "snake_case")]
156#[strum(serialize_all = "snake_case")]
157pub enum DeribitInstrumentState {
158 Created,
160 Started,
162 Settled,
164 Closed,
166 Terminated,
168}
169
170impl Display for DeribitInstrumentState {
171 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
172 match self {
173 Self::Created => write!(f, "created"),
174 Self::Started => write!(f, "started"),
175 Self::Settled => write!(f, "settled"),
176 Self::Closed => write!(f, "closed"),
177 Self::Terminated => write!(f, "terminated"),
178 }
179 }
180}
181
182impl From<DeribitInstrumentState> for MarketStatusAction {
183 fn from(state: DeribitInstrumentState) -> Self {
184 match state {
185 DeribitInstrumentState::Created => Self::PreOpen,
186 DeribitInstrumentState::Started => Self::Trading,
187 DeribitInstrumentState::Settled => Self::Close,
188 DeribitInstrumentState::Closed => Self::Close,
189 DeribitInstrumentState::Terminated => Self::NotAvailableForTrading,
190 }
191 }
192}
193
194#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
196#[serde(rename_all = "snake_case")]
197pub enum DeribitTimeInForce {
198 #[serde(rename = "good_til_cancelled")]
200 GoodTilCancelled,
201 #[serde(rename = "good_til_day")]
203 GoodTilDay,
204 #[serde(rename = "immediate_or_cancel")]
206 ImmediateOrCancel,
207 #[serde(rename = "fill_or_kill")]
209 FillOrKill,
210}
211
212impl DeribitTimeInForce {
213 #[must_use]
215 pub fn as_str(&self) -> &'static str {
216 match self {
217 Self::GoodTilCancelled => "good_til_cancelled",
218 Self::GoodTilDay => "good_til_day",
219 Self::ImmediateOrCancel => "immediate_or_cancel",
220 Self::FillOrKill => "fill_or_kill",
221 }
222 }
223}
224
225impl TryFrom<TimeInForce> for DeribitTimeInForce {
226 type Error = String;
227
228 fn try_from(tif: TimeInForce) -> Result<Self, Self::Error> {
229 match tif {
230 TimeInForce::Gtc => Ok(Self::GoodTilCancelled),
231 TimeInForce::Ioc => Ok(Self::ImmediateOrCancel),
232 TimeInForce::Fok => Ok(Self::FillOrKill),
233 TimeInForce::Gtd => Ok(Self::GoodTilDay),
234 _ => Err(format!(
235 "TimeInForce::{tif} is not supported on Deribit (valid: GTC, IOC, FOK, GTD)"
236 )),
237 }
238 }
239}
240
241#[derive(
243 Copy,
244 Clone,
245 Debug,
246 Default,
247 StrumDisplay,
248 PartialEq,
249 Eq,
250 Hash,
251 AsRefStr,
252 EnumIter,
253 EnumString,
254 Serialize,
255 Deserialize,
256)]
257#[serde(rename_all = "lowercase")]
258#[strum(ascii_case_insensitive, serialize_all = "lowercase")]
259#[cfg_attr(
260 feature = "python",
261 pyo3::pyclass(
262 eq,
263 eq_int,
264 module = "nautilus_trader.core.nautilus_pyo3.deribit",
265 from_py_object,
266 rename_all = "SCREAMING_SNAKE_CASE",
267 )
268)]
269#[cfg_attr(
270 feature = "python",
271 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.deribit")
272)]
273pub enum DeribitEnvironment {
274 #[default]
276 Mainnet,
277 Testnet,
279}
280
281pub fn resolve_trigger_type(trigger_type: Option<TriggerType>) -> Option<String> {
283 trigger_type.and_then(|tt| match tt {
284 TriggerType::LastPrice | TriggerType::Default => Some("last_price".to_string()),
285 TriggerType::MarkPrice => Some("mark_price".to_string()),
286 TriggerType::IndexPrice => Some("index_price".to_string()),
287 _ => None,
288 })
289}
290
291#[cfg(test)]
292mod tests {
293 use rstest::rstest;
294
295 use super::*;
296
297 #[rstest]
298 #[case(DeribitInstrumentState::Created, MarketStatusAction::PreOpen)]
299 #[case(DeribitInstrumentState::Started, MarketStatusAction::Trading)]
300 #[case(DeribitInstrumentState::Settled, MarketStatusAction::Close)]
301 #[case(DeribitInstrumentState::Closed, MarketStatusAction::Close)]
302 #[case(
303 DeribitInstrumentState::Terminated,
304 MarketStatusAction::NotAvailableForTrading
305 )]
306 fn test_deribit_instrument_state_to_market_status_action(
307 #[case] state: DeribitInstrumentState,
308 #[case] expected: MarketStatusAction,
309 ) {
310 assert_eq!(MarketStatusAction::from(state), expected);
311 }
312}