| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270 |
- use std::str::FromStr;
- use rust_decimal::Decimal;
- use rust_decimal::prelude::FromPrimitive;
- use serde_json::Value;
- use tokio::time::Instant;
- use tracing::error;
- use exchanges::response_base::ResponseData;
- use global::trace_stack::TraceStack;
- use crate::{Account, OrderBook, Order, Position, PositionModeEnum, SpecialOrder, Depth, Trade, Record};
- // 处理账号信息
- pub fn handle_account_info(response: &ResponseData, _symbol: &String) -> Account {
- let mut rst = Account::new();
- let data_info = response.data["data"].clone();
- for data in data_info.as_array().unwrap() {
- if data["marginCoin"].as_str().unwrap() != "USDT" {
- continue;
- }
- // 格式化account信息
- let mut account = Account {
- coin: data["marginCoin"].to_string(),
- balance: Decimal::from_str(data["usdtEquity"].as_str().unwrap()).unwrap(),
- available_balance: Decimal::from_str(data["available"].as_str().unwrap()).unwrap(),
- frozen_balance: Decimal::from_str(data["frozen"].as_str().unwrap()).unwrap(),
- stocks: Default::default(),
- available_stocks: Default::default(),
- frozen_stocks: Default::default(),
- };
- account.frozen_balance = account.balance - account.available_balance;
- rst = account
- }
- return rst;
- }
- // 处理order信息
- pub fn handle_order(res_data: &ResponseData, multiplier: &Decimal) -> SpecialOrder {
- let data_info = res_data.data["data"].clone();
- let res_data_json = data_info.as_array().unwrap();
- let mut order_info = Vec::new();
- for item in res_data_json.iter() {
- order_info.push(format_order_item(item.clone(), multiplier.clone()));
- }
- SpecialOrder {
- name: res_data.label.clone(),
- order: order_info,
- }
- }
- // 处理订单信息
- pub fn format_order_item(order: Value, _multiplier: Decimal) -> Order {
- let price = Decimal::from_str(order["price"].as_str().unwrap().to_string().as_str()).unwrap();
- let size = Decimal::from_str(order["size"].as_str().unwrap().to_string().as_str()).unwrap();
- let binding = order["status"].clone().as_str().unwrap().to_string();
- let status = binding.as_str();
- let acc_base_volume = Decimal::from_str(order["accBaseVolume"].as_str().unwrap().to_string().as_str()).unwrap();
- let avg_price = if order["priceAvg"].is_null() || order["priceAvg"].as_str().unwrap().is_empty() {
- Decimal::ZERO
- } else {
- Decimal::from_str(order["priceAvg"].as_str().unwrap().to_string().as_str()).unwrap()
- };
- let c_id = if order["clientOid"].is_null() {
- ""
- } else {
- order["clientOid"].as_str().unwrap()
- };
- let amount = size;
- let deal_amount = acc_base_volume;
- let custom_status = if ["filled", "canceled"].contains(&status) {
- "REMOVE".to_string()
- } else if ["init", "live", "new", "partially_filled"].contains(&status) {
- "NEW".to_string()
- } else {
- "NULL".to_string()
- };
- Order {
- id: order["orderId"].as_str().unwrap().to_string(),
- custom_id: c_id.to_string(),
- price,
- amount,
- deal_amount,
- avg_price,
- status: custom_status,
- order_type: order["orderType"].as_str().unwrap().to_string(),
- trace_stack: TraceStack::new(0, Instant::now()).on_special("86 bitget_swap_handle".to_string()),
- }
- }
- // 格式化深度信息
- pub fn format_depth_items(value: Value, mul: &Decimal) -> Vec<OrderBook> {
- let mut depth_items: Vec<OrderBook> = vec![];
- for value in value.as_array().unwrap() {
- let price = Decimal::from_str(value[0].as_str().unwrap()).unwrap();
- let size = Decimal::from_str(value[1].as_str().unwrap()).unwrap();
- depth_items.push(OrderBook {
- price,
- size,
- value: price * size * mul,
- })
- }
- return depth_items;
- }
- // 处理position信息
- pub fn handle_position(res_data: &ResponseData, multiplier: &Decimal) -> Vec<Position> {
- let data_info = res_data.data["data"].clone();
- let data_info_json = data_info.as_array().unwrap();
- data_info_json.iter().map(|item| { format_position_item(item, multiplier) }).collect()
- }
- pub fn format_position_item(position_json: &Value, _multiplier: &Decimal) -> Position {
- let symbol = position_json["instId"].as_str().unwrap().to_string();
- let margin_level = Decimal::from_i64(position_json["leverage"].as_i64().unwrap()).unwrap();
- let amount = Decimal::from_str(position_json["total"].as_str().unwrap()).unwrap();
- let frozen_amount = Decimal::from_str(position_json["frozen"].as_str().unwrap()).unwrap();
- let price = Decimal::from_str(position_json["openPriceAvg"].as_str().unwrap()).unwrap();
- let profit = Decimal::from_str(position_json["unrealizedPL"].as_str().unwrap()).unwrap();
- let mut position_mode = match position_json["posMode"].as_str().unwrap() {
- "hedge_mode" => {
- match position_json["holdSide"].as_str().unwrap() {
- "short" => {
- PositionModeEnum::Short
- }
- "long" => {
- PositionModeEnum::Long
- }
- _ => {
- panic!("bitget_usdt_swap: 未知的持仓模式与持仓方向: {}, {}",
- position_json["posMode"].as_str().unwrap(), position_json["holdSide"].as_str().unwrap())
- }
- }
- }
- "one_way_mode" => {
- PositionModeEnum::Both
- }
- _ => {
- panic!("bitget_usdt_swap: 未知的持仓模式: {}", position_json["posMode"].as_str().unwrap())
- }
- };
- let margin = Decimal::from_str(position_json["marginSize"].as_str().unwrap()).unwrap();
- let update_time = Decimal::from_str(position_json["uTime"].as_str().unwrap()).unwrap();
- let side = position_json["holdSide"].as_str().unwrap();
- match position_mode {
- PositionModeEnum::Both => {
- position_mode = match side {
- "long" => PositionModeEnum::Long,
- "short" => PositionModeEnum::Short,
- _ => { PositionModeEnum::Both }
- }
- }
- _ => {}
- }
- Position {
- symbol,
- margin_level,
- amount,
- frozen_amount,
- price,
- profit,
- position_mode,
- margin,
- update_time
- }
- }
- pub fn format_trade_items(response: &ResponseData) -> Vec<Trade> {
- let data_info = response.data["data"].clone();
- let result = data_info.as_array().unwrap();
- let mut trades = vec![];
- for item in result {
- // 因为gate的量都是张数,所以要进行真实交易量处理
- let mut size = Decimal::from_str(item["size"].as_str().unwrap()).unwrap();
- let price = Decimal::from_str(item["price"].as_str().unwrap().to_string().as_str()).unwrap();
- let side = item["side"].as_str().unwrap().to_string();
- size = match side.as_str() {
- "buy" => {
- size
- }
- "sell" => {
- -size
- }
- _ => {
- error!("{}", item.to_string());
- panic!("Bitget trade error side(bitget_swap_handle_156)")
- }
- };
- let value = (size * price).abs();
- trades.push(Trade {
- id: item["tradeId"].as_str().unwrap().to_string(),
- time: Decimal::from_str(item["ts"].as_str().unwrap()).unwrap(),
- size,
- price,
- value,
- symbol: response.data["arg"]["instId"].as_str().unwrap().replace("USDT", "_USDT"),
- })
- }
- return trades;
- }
- pub fn handle_book_ticker(res_data: &ResponseData, mul: &Decimal) -> Depth {
- let data_info = res_data.data["data"].clone();
- let asks = format_depth_items(data_info[0]["asks"].clone(), mul);
- let bids = format_depth_items(data_info[0]["bids"].clone(), mul);
- let t = Decimal::from_i64(res_data.reach_time).unwrap();
- let s = res_data.data["arg"]["instId"].as_str().unwrap().replace("USDT", "_USDT");
- Depth {
- time: t,
- symbol: s.to_string(),
- asks,
- bids,
- }
- }
- pub fn handle_records(value: &Value) -> Vec<Record> {
- let data_info = value["data"].clone();
- let mut records = vec![];
- for record_value in data_info.as_array().unwrap() {
- records.push(Record {
- time: Decimal::from_str(record_value[0].as_str().unwrap()).unwrap(),
- open: Decimal::from_str(record_value[1].as_str().unwrap()).unwrap(),
- high: Decimal::from_str(record_value[2].as_str().unwrap()).unwrap(),
- low: Decimal::from_str(record_value[3].as_str().unwrap()).unwrap(),
- close: Decimal::from_str(record_value[4].as_str().unwrap()).unwrap(),
- volume: Decimal::from_str(record_value[5].as_str().unwrap()).unwrap(),
- symbol: value["arg"]["instId"].as_str().unwrap().replace("USDT", "_USDT"),
- });
- }
- return records;
- }
- // 处理特殊深度数据
- // pub fn handle_special_depth(res_data: ResponseData) -> SpecialDepth {
- // HandleSwapInfo::handle_special_depth(ExchangeEnum::BitgetSwap, res_data)
- // }
- // // 处理特殊Ticker信息
- // pub fn handle_special_ticker(res_data: ResponseData) -> SpecialDepth {
- // let res_data_str = res_data.data;
- // let res_data_json: Vec<serde_json::Value> = serde_json::from_str(&*res_data_str).unwrap();
- // format_special_ticker(res_data_json[0].clone(), res_data.label)
- // }
- //
- // pub fn format_special_ticker(data: serde_json::Value, label: String) -> SpecialDepth {
- // let bp = Decimal::from_str(data["bidPr"].as_str().unwrap()).unwrap();
- // let bq = Decimal::from_str(data["bidSz"].as_str().unwrap()).unwrap();
- // let ap = Decimal::from_str(data["askPr"].as_str().unwrap()).unwrap();
- // let aq = Decimal::from_str(data["askSz"].as_str().unwrap()).unwrap();
- // let mp = (bp + ap) * dec!(0.5);
- // let t = Decimal::from_str(data["ts"].as_str().unwrap()).unwrap();
- // let create_at = data["ts"].as_str().unwrap().parse::<i64>().unwrap() * 1000;
- //
- // let ticker_info = SpecialTicker { sell: ap, buy: bp, mid_price: mp, t, create_at };
- // let depth_info = vec![bp, bq, ap, aq];
- // SpecialDepth {
- // name: label,
- // depth: depth_info,
- // ticker: ticker_info,
- // t,
- // create_at,
- // }
- // }
|