deribit_fix/client/
mod.rs

1//! Deribit FIX client implementation
2
3use 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
15/// Main Deribit FIX client
16pub struct DeribitFixClient {
17    config: Config,
18    connection: Option<Arc<Mutex<Connection>>>,
19    session: Option<Arc<Mutex<Session>>>,
20}
21
22impl DeribitFixClient {
23    /// Create a new Deribit FIX client
24    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    /// Connect to the Deribit FIX server
35    pub async fn connect(&mut self) -> Result<()> {
36        info!("Connecting to Deribit FIX server at {}", self.config.connection_url());
37        
38        // Create connection
39        let connection = Connection::new(&self.config).await?;
40        self.connection = Some(Arc::new(Mutex::new(connection)));
41
42        // Create session
43        let session = Session::new(&self.config)?;
44        self.session = Some(Arc::new(Mutex::new(session)));
45
46        // Perform logon
47        self.logon().await?;
48
49        info!("Successfully connected to Deribit FIX server");
50        Ok(())
51    }
52
53    /// Disconnect from the server
54    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    /// Check if the client is connected
73    pub fn is_connected(&self) -> bool {
74        self.connection.is_some() && self.session.is_some()
75    }
76
77    /// Perform FIX logon
78    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    /// Send a new order
89    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    /// Cancel an order
98    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    /// Subscribe to market data
107    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    /// Get account positions
116    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/// New order request parameters
126#[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/// Order side enumeration
138#[derive(Debug, Clone, Copy, PartialEq, Eq)]
139pub enum OrderSide {
140    Buy,
141    Sell,
142}
143
144/// Order type enumeration
145#[derive(Debug, Clone, Copy, PartialEq, Eq)]
146pub enum OrderType {
147    Market,
148    Limit,
149    Stop,
150    StopLimit,
151}
152
153/// Time in force enumeration
154#[derive(Debug, Clone, Copy, PartialEq, Eq)]
155pub enum TimeInForce {
156    Day,
157    GoodTillCancel,
158    ImmediateOrCancel,
159    FillOrKill,
160}
161
162/// Position information
163#[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}