| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167 |
- use std::str::FromStr;
- use rust_decimal::Decimal;
- use rust_decimal::prelude::FromPrimitive;
- use rust_decimal_macros::dec;
- use serde_json::Value;
- use tokio::time::Instant;
- use tracing::{error};
- use exchanges::response_base::ResponseData;
- use global::trace_stack::TraceStack;
- use crate::{Account, MarketOrder, Order, Position, PositionModeEnum, SpecialDepth, SpecialOrder, SpecialTicker};
- // 处理账号信息
- pub fn handle_account_info(res_data: &ResponseData, symbol: &String) -> Account {
- let res_data_json = res_data.data.as_array().unwrap();
- format_account_info(res_data_json, symbol)
- }
- pub fn format_account_info(accounts: &Vec<Value>, symbol: &String) -> Account {
- let symbol_upper = symbol.to_uppercase();
- let symbol_array: Vec<&str> = symbol_upper.split("_").collect();
- let balance_info = accounts.iter().find(|&item| item["currency"].as_str().unwrap().contains(symbol_array[1]));
- match balance_info {
- None => {
- error!("Phemex:格式化账号信息错误!\nformat_account_info: accounts={:?}", accounts);
- panic!("Phemex:格式化账号信息错误!\nformat_account_info: accounts={:?}", accounts)
- }
- Some(value) => {
- let coin = value["currency"].as_str().unwrap().to_string();
- let balance = Decimal::from_str(value["accountBalanceRv"].as_str().unwrap()).unwrap();
- let frozen_balance = Decimal::from_str(value["totalUsedBalanceRv"].as_str().unwrap()).unwrap();
- let available_balance = balance - frozen_balance;
- Account {
- coin,
- balance,
- available_balance,
- frozen_balance,
- stocks: Decimal::ZERO,
- available_stocks: Decimal::ZERO,
- frozen_stocks: Decimal::ZERO,
- }
- }
- }
- }
- // 处理position信息
- pub fn handle_position(res_data: &ResponseData, ct_val: &Decimal) -> Vec<Position> {
- let res_data_json = res_data.data.as_array().unwrap();
- return res_data_json.iter().filter_map(|item| {
- let position = format_position_item(item, ct_val);
- if position.amount == Decimal::ZERO {
- None
- } else {
- Some(position)
- }
- }).collect();
- }
- pub fn format_position_item(position: &Value, ct_val: &Decimal) -> Position {
- let symbol = position["symbol"].as_str().unwrap().to_string();
- let margin_level = Decimal::from_str(position["leverageRr"].as_str().unwrap()).unwrap();
- let price = Decimal::from_str(position["avgEntryPriceRp"].as_str().unwrap()).unwrap();
- let profit = Decimal::from_str(position["curTermRealisedPnlRv"].as_str().unwrap()).unwrap();
- let margin = Decimal::from_str(position["positionMarginRv"].as_str().unwrap()).unwrap();
- let position_mode = match position["posSide"].as_str().unwrap_or("") {
- "Long" => PositionModeEnum::Long,
- "Short" => PositionModeEnum::Short,
- _ => {
- error!("phemex_swap:格式化持仓模式错误!\nformat_position_item:position={:?}", position);
- panic!("phemex_swap:格式化持仓模式错误!\nformat_position_item:position={:?}", position)
- }
- };
- let size = Decimal::from_str(&position["size"].as_str().unwrap()).unwrap();
- let amount = size * ct_val;
- Position {
- symbol,
- margin_level,
- amount,
- frozen_amount: Decimal::ZERO,
- price,
- profit,
- position_mode,
- margin,
- }
- }
- // 处理order信息
- pub fn handle_order(res_data: ResponseData, ct_val: Decimal) -> SpecialOrder {
- let orders = res_data.data.as_array().unwrap();
- let order_info = orders.iter().map(|item| format_order_item(item, ct_val)).collect();
- SpecialOrder {
- name: res_data.label,
- order: order_info,
- }
- }
- pub fn format_order_item(order: &Value, ct_val: Decimal) -> Order {
- let id = order["orderID"].as_str().unwrap().to_string();
- let custom_id = order["clOrdID"].as_str().unwrap().to_string();
- let price = Decimal::from_str(order["priceRp"].as_str().unwrap()).unwrap();
- let amount = Decimal::from_str(order["orderQty"].as_str().unwrap()).unwrap() * ct_val;
- let deal_amount = Decimal::from_str(order["cumQty"].as_str().unwrap()).unwrap() * ct_val;
- let avg_price = Decimal::from_str(order["cumValueRv"].as_str().unwrap()).unwrap();
- let status = order["ordStatus"].as_str().unwrap();
- let custom_status;
- if vec!["Rejected", "Filled", "Canceled"].contains(&status) {
- custom_status = "REMOVE".to_string()
- } else if vec!["New", "Init", "Created"].contains(&status) {
- custom_status = "NEW".to_string()
- } else {
- error!("gate_swap:格式化订单状态错误!\nformat_order_item:order={:?}", order);
- panic!("gate_swap:格式化订单状态错误!\nformat_order_item:order={:?}", order)
- };
- let result = Order {
- id,
- custom_id,
- price,
- amount,
- deal_amount,
- avg_price,
- status: custom_status,
- order_type: "limit".to_string(),
- trace_stack: TraceStack::new(0, Instant::now()).on_special("120 trace_stack".to_string()),
- };
- return result;
- }
- // 处理特殊Ticket信息
- pub fn handle_ticker(res_data: &ResponseData) -> SpecialDepth {
- let depth = &res_data.data;
- let bp = Decimal::from_str(depth["orderbook_p"]["bids"][0][0].as_str().unwrap()).unwrap();
- let bq = Decimal::from_str(depth["orderbook_p"]["bids"][0][1].as_str().unwrap()).unwrap();
- let ap = Decimal::from_str(depth["orderbook_p"]["asks"][0][0].as_str().unwrap()).unwrap();
- let aq = Decimal::from_str(depth["orderbook_p"]["asks"][0][1].as_str().unwrap()).unwrap();
- let mp = (bp + ap) * dec!(0.5);
- let t = Decimal::from_i64(depth["timestamp"].as_i64().unwrap() / 1_000_000).unwrap();
- let create_at = depth["timestamp"].as_i64().unwrap() / 1_000_000;
- let ticker_info = SpecialTicker { sell: ap, buy: bp, mid_price: mp, t, create_at };
- let depth_info = vec![bp, bq, ap, aq];
- SpecialDepth {
- name: (*res_data).label.clone(),
- depth: depth_info,
- ticker: ticker_info,
- t,
- create_at,
- }
- }
- pub fn format_depth_items(depth: Value) -> Vec<MarketOrder> {
- if depth.is_null() {
- return vec![];
- }
- let mut depth_items: Vec<MarketOrder> = vec![];
- for values in depth.as_array().unwrap() {
- let value = values.as_array().unwrap();
- depth_items.push(MarketOrder {
- price: Decimal::from_str(value[0].as_str().unwrap()).unwrap(),
- amount: Decimal::from_str(value[1].as_str().unwrap()).unwrap(),
- })
- }
- return depth_items;
- }
|