use crypto_market_type::MarketType;
use crate::{MessageType, TradeMsg, TradeSide};
use serde::{Deserialize, Serialize};
use serde_json::{Result, Value};
use std::collections::HashMap;
const EXCHANGE_NAME: &str = "binance";
#[derive(Serialize, Deserialize)]
#[allow(non_snake_case)]
struct AggTradeMsg {
e: String, E: i64, s: String, a: i64, p: String, q: String, f: i64, l: i64, T: i64, m: bool, #[serde(flatten)]
extra: HashMap<String, Value>,
}
#[derive(Serialize, Deserialize)]
#[allow(non_snake_case)]
struct RawTradeMsg {
e: String, E: i64, s: String, t: i64, p: String, q: String, b: i64, a: i64, T: i64, m: bool, #[serde(flatten)]
extra: HashMap<String, Value>,
}
#[derive(Serialize, Deserialize)]
struct WebsocketMsg<T: Sized> {
stream: String,
data: T,
}
fn calc_quantity_and_volume(
market_type: MarketType,
pair: &str,
price: f64,
quantity: f64,
) -> (f64, f64) {
if market_type == MarketType::InverseSwap || market_type == MarketType::InverseFuture {
let contract_value = if pair.starts_with("BTC/") {
100.0
} else {
10.0
};
let volume = quantity * contract_value;
let quantity = volume / price;
(quantity, volume)
} else {
(quantity, quantity * price)
}
}
pub(crate) fn parse_trade(market_type: MarketType, msg: &str) -> Result<Vec<TradeMsg>> {
let obj = serde_json::from_str::<HashMap<String, Value>>(&msg)?;
let data = obj.get("data").unwrap();
let event_type = data.get("e").unwrap().as_str().unwrap();
match event_type {
"aggTrade" => {
let agg_trade: AggTradeMsg = serde_json::from_value(data.clone()).unwrap();
let mut trade = TradeMsg {
exchange: EXCHANGE_NAME.to_string(),
market_type,
symbol: agg_trade.s.clone(),
pair: crypto_pair::normalize_pair(&agg_trade.s, EXCHANGE_NAME).unwrap(),
msg_type: MessageType::Trade,
timestamp: agg_trade.T,
price: agg_trade.p.parse::<f64>().unwrap(),
quantity: agg_trade.q.parse::<f64>().unwrap(),
volume: 0.0,
side: if agg_trade.m {
TradeSide::Sell
} else {
TradeSide::Buy
},
trade_id: agg_trade.a.to_string(),
raw: serde_json::from_str(msg)?,
};
let (quantity, volume) =
calc_quantity_and_volume(market_type, &trade.pair, trade.price, trade.quantity);
trade.quantity = quantity;
trade.volume = volume;
Ok(vec![trade])
}
"trade" => {
let raw_trade: RawTradeMsg = serde_json::from_value(data.clone()).unwrap();
let mut trade = TradeMsg {
exchange: EXCHANGE_NAME.to_string(),
market_type,
symbol: raw_trade.s.clone(),
pair: crypto_pair::normalize_pair(&raw_trade.s, EXCHANGE_NAME).unwrap(),
msg_type: MessageType::Trade,
timestamp: raw_trade.T,
price: raw_trade.p.parse::<f64>().unwrap(),
quantity: raw_trade.q.parse::<f64>().unwrap(),
volume: 0.0,
side: if raw_trade.m {
TradeSide::Sell
} else {
TradeSide::Buy
},
trade_id: raw_trade.t.to_string(),
raw: serde_json::from_str(msg)?,
};
let (quantity, volume) =
calc_quantity_and_volume(market_type, &trade.pair, trade.price, trade.quantity);
trade.quantity = quantity;
trade.volume = volume;
Ok(vec![trade])
}
_ => panic!("Unsupported event type {}", event_type),
}
}