deribit_fix/client/
mod.rs1use crate::{
4 config::Config,
5 connection::Connection,
6 error::{DeribitFixError, Result},
7 message::{FixMessage, MessageBuilder},
8 session::Session,
9 types::*,
10};
11use std::sync::Arc;
12use tokio::sync::Mutex;
13use tracing::{debug, error, info, warn};
14
15pub struct DeribitFixClient {
17 config: Config,
18 connection: Option<Arc<Mutex<Connection>>>,
19 session: Option<Arc<Mutex<Session>>>,
20}
21
22impl DeribitFixClient {
23 pub async fn new(config: Config) -> Result<Self> {
25 config.validate()?;
26
27 Ok(Self {
28 config,
29 connection: None,
30 session: None,
31 })
32 }
33
34 pub async fn connect(&mut self) -> Result<()> {
36 info!("Connecting to Deribit FIX server at {}", self.config.connection_url());
37
38 let connection = Connection::new(&self.config).await?;
40 self.connection = Some(Arc::new(Mutex::new(connection)));
41
42 let session = Session::new(&self.config)?;
44 self.session = Some(Arc::new(Mutex::new(session)));
45
46 self.logon().await?;
48
49 info!("Successfully connected to Deribit FIX server");
50 Ok(())
51 }
52
53 pub async fn disconnect(&mut self) -> Result<()> {
55 if let Some(session) = &self.session {
56 let mut session_guard = session.lock().await;
57 session_guard.logout().await?;
58 }
59
60 if let Some(connection) = &self.connection {
61 let mut conn_guard = connection.lock().await;
62 conn_guard.close().await?;
63 }
64
65 self.connection = None;
66 self.session = None;
67
68 info!("Disconnected from Deribit FIX server");
69 Ok(())
70 }
71
72 pub fn is_connected(&self) -> bool {
74 self.connection.is_some() && self.session.is_some()
75 }
76
77 async fn logon(&self) -> Result<()> {
79 let session = self.session.as_ref()
80 .ok_or_else(|| DeribitFixError::Session("Session not initialized".to_string()))?;
81
82 let mut session_guard = session.lock().await;
83 session_guard.logon().await?;
84
85 Ok(())
86 }
87
88 pub async fn send_order(&self, order: NewOrderRequest) -> Result<String> {
90 let session = self.session.as_ref()
91 .ok_or_else(|| DeribitFixError::Session("Not connected".to_string()))?;
92
93 let mut session_guard = session.lock().await;
94 session_guard.send_new_order(order).await
95 }
96
97 pub async fn cancel_order(&self, order_id: String) -> Result<()> {
99 let session = self.session.as_ref()
100 .ok_or_else(|| DeribitFixError::Session("Not connected".to_string()))?;
101
102 let mut session_guard = session.lock().await;
103 session_guard.cancel_order(order_id).await
104 }
105
106 pub async fn subscribe_market_data(&self, symbol: String) -> Result<()> {
108 let session = self.session.as_ref()
109 .ok_or_else(|| DeribitFixError::Session("Not connected".to_string()))?;
110
111 let mut session_guard = session.lock().await;
112 session_guard.subscribe_market_data(symbol).await
113 }
114
115 pub async fn get_positions(&self) -> Result<Vec<Position>> {
117 let session = self.session.as_ref()
118 .ok_or_else(|| DeribitFixError::Session("Not connected".to_string()))?;
119
120 let mut session_guard = session.lock().await;
121 session_guard.request_positions().await
122 }
123}
124
125#[derive(Debug, Clone)]
127pub struct NewOrderRequest {
128 pub symbol: String,
129 pub side: OrderSide,
130 pub order_type: OrderType,
131 pub quantity: f64,
132 pub price: Option<f64>,
133 pub time_in_force: TimeInForce,
134 pub client_order_id: Option<String>,
135}
136
137#[derive(Debug, Clone, Copy, PartialEq, Eq)]
139pub enum OrderSide {
140 Buy,
141 Sell,
142}
143
144#[derive(Debug, Clone, Copy, PartialEq, Eq)]
146pub enum OrderType {
147 Market,
148 Limit,
149 Stop,
150 StopLimit,
151}
152
153#[derive(Debug, Clone, Copy, PartialEq, Eq)]
155pub enum TimeInForce {
156 Day,
157 GoodTillCancel,
158 ImmediateOrCancel,
159 FillOrKill,
160}
161
162#[derive(Debug, Clone)]
164pub struct Position {
165 pub symbol: String,
166 pub quantity: f64,
167 pub average_price: f64,
168 pub unrealized_pnl: f64,
169 pub realized_pnl: f64,
170}