Skip to main content

ccxt_exchanges/binance/parser/
funding.rs

1#![allow(dead_code)]
2
3use super::{parse_decimal, parse_f64};
4use ccxt_core::{
5    Result,
6    error::{Error, ParseError},
7    types::{
8        FeeFundingRate, FeeFundingRateHistory, FundingFee, FundingHistory, Market, NextFundingRate,
9    },
10};
11use serde_json::Value;
12
13/// Parse funding rate data from Binance futures API.
14pub fn parse_funding_rate(data: &Value, market: Option<&Market>) -> Result<FeeFundingRate> {
15    let symbol = if let Some(m) = market {
16        m.symbol.clone()
17    } else {
18        data["symbol"]
19            .as_str()
20            .ok_or_else(|| Error::from(ParseError::missing_field("symbol")))?
21            .to_string()
22    };
23
24    let funding_rate =
25        parse_decimal(data, "lastFundingRate").or_else(|| parse_decimal(data, "fundingRate"));
26
27    let mark_price = parse_decimal(data, "markPrice");
28    let index_price = parse_decimal(data, "indexPrice");
29    let interest_rate = parse_decimal(data, "interestRate");
30
31    let next_funding_time = data["nextFundingTime"].as_i64();
32    let funding_timestamp = next_funding_time.or_else(|| data["fundingTime"].as_i64());
33
34    Ok(FeeFundingRate {
35        info: data.clone(),
36        symbol,
37        mark_price,
38        index_price,
39        interest_rate,
40        estimated_settle_price: None,
41        funding_rate,
42        funding_timestamp,
43        funding_datetime: funding_timestamp
44            .and_then(|t| chrono::DateTime::from_timestamp(t / 1000, 0).map(|dt| dt.to_rfc3339())),
45        next_funding_rate: None,
46        next_funding_timestamp: None,
47        next_funding_datetime: None,
48        previous_funding_rate: None,
49        previous_funding_timestamp: None,
50        previous_funding_datetime: None,
51        timestamp: None,
52        datetime: None,
53        interval: None,
54    })
55}
56
57/// Parse funding rate history data from Binance futures API.
58pub fn parse_funding_rate_history(
59    data: &Value,
60    market: Option<&Market>,
61) -> Result<FeeFundingRateHistory> {
62    let symbol = if let Some(m) = market {
63        m.symbol.clone()
64    } else {
65        data["symbol"]
66            .as_str()
67            .ok_or_else(|| Error::from(ParseError::missing_field("symbol")))?
68            .to_string()
69    };
70
71    let funding_rate = parse_decimal(data, "fundingRate");
72    let funding_time = data["fundingTime"].as_i64();
73
74    Ok(FeeFundingRateHistory {
75        info: data.clone(),
76        symbol,
77        funding_rate,
78        funding_timestamp: funding_time,
79        funding_datetime: funding_time
80            .and_then(|t| chrono::DateTime::from_timestamp(t / 1000, 0).map(|dt| dt.to_rfc3339())),
81        timestamp: funding_time,
82        datetime: funding_time
83            .and_then(|t| chrono::DateTime::from_timestamp(t / 1000, 0).map(|dt| dt.to_rfc3339())),
84    })
85}
86
87/// Parse funding fee history data from Binance futures API.
88pub fn parse_funding_history(data: &Value, market: Option<&Market>) -> Result<FundingHistory> {
89    let symbol = if let Some(m) = market {
90        m.symbol.clone()
91    } else {
92        data["symbol"]
93            .as_str()
94            .ok_or_else(|| Error::from(ParseError::missing_field("symbol")))?
95            .to_string()
96    };
97
98    let id = data["tranId"]
99        .as_u64()
100        .or_else(|| data["id"].as_u64())
101        .map(|v| v.to_string());
102
103    let amount = parse_f64(data, "income");
104    let code = data["asset"].as_str().map(ToString::to_string);
105    let timestamp = data["time"].as_i64();
106
107    Ok(FundingHistory {
108        info: data.clone(),
109        id,
110        symbol,
111        code,
112        amount,
113        timestamp,
114        datetime: timestamp.map(|t| {
115            chrono::DateTime::from_timestamp(t / 1000, 0)
116                .map(|dt| dt.to_rfc3339())
117                .unwrap_or_default()
118        }),
119    })
120}
121
122/// Parse funding fee data from Binance futures API.
123pub fn parse_funding_fee(data: &Value, market: Option<&Market>) -> Result<FundingFee> {
124    let symbol = if let Some(m) = market {
125        m.symbol.clone()
126    } else {
127        data["symbol"]
128            .as_str()
129            .ok_or_else(|| Error::from(ParseError::missing_field("symbol")))?
130            .to_string()
131    };
132
133    let income = parse_f64(data, "income").unwrap_or(0.0);
134    let asset = data["asset"]
135        .as_str()
136        .ok_or_else(|| Error::from(ParseError::missing_field("asset")))?
137        .to_string();
138
139    let time = data["time"]
140        .as_i64()
141        .ok_or_else(|| Error::from(ParseError::missing_field("time")))?;
142
143    let funding_rate = parse_f64(data, "fundingRate");
144    let mark_price = parse_f64(data, "markPrice");
145
146    let datetime = Some(
147        chrono::DateTime::from_timestamp(time / 1000, 0)
148            .map(|dt| dt.to_rfc3339())
149            .unwrap_or_default(),
150    );
151
152    Ok(FundingFee {
153        info: data.clone(),
154        symbol,
155        income,
156        asset,
157        time,
158        datetime,
159        funding_rate,
160        mark_price,
161    })
162}
163
164/// Parse next funding rate data from Binance premium index.
165pub fn parse_next_funding_rate(data: &Value, market: &Market) -> Result<NextFundingRate> {
166    let symbol = market.symbol.clone();
167
168    let mark_price = parse_f64(data, "markPrice")
169        .ok_or_else(|| Error::from(ParseError::missing_field("markPrice")))?;
170
171    let index_price = parse_f64(data, "indexPrice");
172
173    let current_funding_rate = parse_f64(data, "lastFundingRate").unwrap_or(0.0);
174
175    let next_funding_rate = parse_f64(data, "interestRate")
176        .or_else(|| parse_f64(data, "estimatedSettlePrice"))
177        .unwrap_or(current_funding_rate);
178
179    let next_funding_time = data["nextFundingTime"]
180        .as_i64()
181        .ok_or_else(|| Error::from(ParseError::missing_field("nextFundingTime")))?;
182
183    let next_funding_datetime = Some(
184        chrono::DateTime::from_timestamp(next_funding_time / 1000, 0)
185            .map(|dt| dt.to_rfc3339())
186            .unwrap_or_default(),
187    );
188
189    Ok(NextFundingRate {
190        info: data.clone(),
191        symbol,
192        mark_price,
193        index_price,
194        current_funding_rate,
195        next_funding_rate,
196        next_funding_time,
197        next_funding_datetime,
198    })
199}