deribit_base/model/
funding.rs

1/******************************************************************************
2   Author: Joaquín Béjar García
3   Email: jb@taunais.com
4   Date: 21/7/25
5******************************************************************************/
6use pretty_simple_display::{DebugPretty, DisplaySimple};
7use serde::{Deserialize, Serialize};
8
9/// Funding chart data structure
10#[derive(DebugPretty, DisplaySimple, Clone, Serialize, Deserialize)]
11pub struct FundingChartData {
12    /// Current interest rate
13    pub current_interest: f64,
14    /// 8h interest rate
15    pub interest_8h: f64,
16    /// Historical funding data points
17    pub data: Vec<FundingDataPoint>,
18}
19
20impl FundingChartData {
21    /// Create new funding chart data
22    pub fn new() -> Self {
23        Self {
24            current_interest: 0.0,
25            interest_8h: 0.0,
26            data: Vec::new(),
27        }
28    }
29}
30
31impl Default for FundingChartData {
32    fn default() -> Self {
33        Self::new()
34    }
35}
36
37/// Funding data point structure
38#[derive(DebugPretty, DisplaySimple, Clone, Serialize, Deserialize)]
39pub struct FundingDataPoint {
40    /// Index price at the time
41    pub index_price: f64,
42    /// 8h interest rate
43    pub interest_8h: f64,
44    /// Timestamp of the data point
45    pub timestamp: u64,
46}
47
48impl FundingDataPoint {
49    /// Create new funding data point
50    pub fn new(index_price: f64, interest_8h: f64, timestamp: u64) -> Self {
51        Self {
52            index_price,
53            interest_8h,
54            timestamp,
55        }
56    }
57}
58
59/// Funding rate data structure for historical funding rates
60#[derive(DebugPretty, DisplaySimple, Clone, Serialize, Deserialize)]
61pub struct FundingRateData {
62    /// Timestamp of the funding event
63    pub timestamp: u64,
64    /// Index price at the time
65    pub index_price: f64,
66    /// 8h interest rate
67    pub interest_8h: f64,
68    /// 1h interest rate
69    pub interest_1h: f64,
70    /// Previous index price
71    pub prev_index_price: f64,
72}
73
74impl FundingRateData {
75    /// Create new funding rate data
76    pub fn new(
77        timestamp: u64,
78        index_price: f64,
79        interest_8h: f64,
80        interest_1h: f64,
81        prev_index_price: f64,
82    ) -> Self {
83        Self {
84            timestamp,
85            index_price,
86            interest_8h,
87            interest_1h,
88            prev_index_price,
89        }
90    }
91}
92
93/// TradingView chart data structure
94#[derive(DebugPretty, DisplaySimple, Clone, Serialize, Deserialize)]
95pub struct TradingViewChartData {
96    /// Status of the data
97    pub status: String,
98    /// Array of timestamps
99    pub ticks: Vec<u64>,
100    /// Array of open prices
101    pub open: Vec<f64>,
102    /// Array of high prices
103    pub high: Vec<f64>,
104    /// Array of low prices
105    pub low: Vec<f64>,
106    /// Array of close prices
107    pub close: Vec<f64>,
108    /// Array of volumes
109    pub volume: Vec<f64>,
110    /// Array of costs
111    pub cost: Vec<f64>,
112}
113
114impl TradingViewChartData {
115    /// Create new TradingView chart data
116    pub fn new() -> Self {
117        Self {
118            status: "ok".to_string(),
119            ticks: Vec::new(),
120            open: Vec::new(),
121            high: Vec::new(),
122            low: Vec::new(),
123            close: Vec::new(),
124            volume: Vec::new(),
125            cost: Vec::new(),
126        }
127    }
128
129    /// Add a new candle to the data
130    #[allow(clippy::too_many_arguments)]
131    pub fn add_candle(
132        &mut self,
133        timestamp: u64,
134        open: f64,
135        high: f64,
136        low: f64,
137        close: f64,
138        volume: f64,
139        cost: f64,
140    ) {
141        self.ticks.push(timestamp);
142        self.open.push(open);
143        self.high.push(high);
144        self.low.push(low);
145        self.close.push(close);
146        self.volume.push(volume);
147        self.cost.push(cost);
148    }
149}
150
151impl Default for TradingViewChartData {
152    fn default() -> Self {
153        Self::new()
154    }
155}
156
157#[cfg(test)]
158mod tests {
159    use super::*;
160
161    #[test]
162    fn test_funding_chart_data_creation() {
163        let chart_data = FundingChartData::new();
164        assert_eq!(chart_data.current_interest, 0.0);
165        assert_eq!(chart_data.interest_8h, 0.0);
166        assert!(chart_data.data.is_empty());
167    }
168
169    #[test]
170    fn test_trading_view_chart_data_creation() {
171        let mut chart_data = TradingViewChartData::new();
172        chart_data.add_candle(
173            1640995200000, // timestamp
174            45000.0,       // open
175            45500.0,       // high
176            44800.0,       // low
177            45200.0,       // close
178            100.0,         // volume
179            4520000.0,     // cost
180        );
181
182        assert_eq!(chart_data.ticks.len(), 1);
183        assert_eq!(chart_data.open[0], 45000.0);
184        assert_eq!(chart_data.high[0], 45500.0);
185    }
186
187    #[test]
188    fn test_serde() {
189        let funding_data = FundingRateData::new(
190            1640995200000, // timestamp
191            45000.0,       // index_price
192            0.0001,        // interest_8h
193            0.00001,       // interest_1h
194            44900.0,       // prev_index_price
195        );
196
197        let json = serde_json::to_string(&funding_data).unwrap();
198        let deserialized: FundingRateData = serde_json::from_str(&json).unwrap();
199        assert_eq!(funding_data.timestamp, deserialized.timestamp);
200        assert_eq!(funding_data.index_price, deserialized.index_price);
201    }
202}