| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193 |
- use std::str::FromStr;
- use rust_decimal::Decimal;
- use rust_decimal_macros::dec;
- use serde::{Deserialize, Serialize};
- use tracing::trace;
- use exchanges::response_base::ResponseData;
- use global::trace_stack::TraceStack;
- use crate::{Account, MarketOrder, Order, Position, PositionModeEnum, SpecialDepth, SpecialOrder, SpecialTicker};
- use crate::exchange::ExchangeEnum;
- use crate::handle_info::HandleSwapInfo;
- use crate::okx_swap::SwapPosition;
- #[derive(Debug, Deserialize, Serialize)]
- #[serde(rename_all = "camelCase")]
- struct SwapBalanceAndPositionSubscribe {
- pos_data: Vec<SwapBalanceAndPositionPosDataSubscribe>,
- }
- #[derive(Debug, Deserialize, Serialize)]
- #[serde(rename_all = "camelCase")]
- struct SwapBalanceAndPositionPosDataSubscribe {
- pos_id: String,
- trade_id: String,
- inst_id: String,
- inst_type: String,
- mgn_mode: String,
- pos_side: String,
- pos: Decimal,
- ccy: String,
- pos_ccy: String,
- avg_px: Decimal,
- u_time: String,
- }
- #[derive(Debug, Deserialize, Serialize)]
- #[serde(rename_all = "camelCase")]
- struct SwapPositionSubscribe {
- arg: SwapPositionSubscribeArg,
- data: Vec<SwapPosition>,
- }
- #[derive(Debug, Deserialize, Serialize)]
- #[serde(rename_all = "camelCase")]
- struct SwapPositionSubscribeArg {
- channel: String,
- uid: String,
- inst_type: String,
- }
- // 处理账号信息
- pub fn handle_account_info(res_data: ResponseData, symbol: String) -> Account {
- let res_data_str = res_data.data;
- let res_data_json: serde_json::Value = serde_json::from_str(&res_data_str).unwrap();
- let account_info = res_data_json[0]["details"].clone();
- let details = account_info[0].clone();
- format_account_info(details, symbol)
- }
- pub fn format_account_info(data: serde_json::Value, symbol: String) -> Account {
- let symbol_upper = symbol.to_uppercase();
- let symbol_array: Vec<&str> = symbol_upper.split("_").collect();
- Account {
- coin: symbol_array[1].to_string(),
- balance: Decimal::from_str(data["cashBal"].as_str().unwrap()).unwrap(),
- available_balance: Decimal::from_str(data["availBal"].as_str().unwrap()).unwrap(),
- frozen_balance: Decimal::from_str(data["fixedBal"].as_str().unwrap()).unwrap(),
- stocks: Decimal::ZERO,
- available_stocks: Decimal::ZERO,
- frozen_stocks: Decimal::ZERO,
- }
- }
- // 处理order信息
- pub fn handle_order(res_data: ResponseData, ct_val: Decimal) -> SpecialOrder {
- let res_data_str = res_data.data;
- let res_data_json: Vec<serde_json::Value> = serde_json::from_str(&*res_data_str).unwrap();
- trace!(?res_data_json);
- let mut order_info = Vec::new();
- for item in res_data_json.iter() {
- order_info.push(format_order_item(item.clone(), ct_val));
- }
- trace!(?order_info);
- SpecialOrder {
- name: res_data.label,
- order: order_info,
- }
- }
- // 处理订单信息
- pub fn format_order_item(order: serde_json::Value, ct_val: Decimal) -> Order {
- let price = Decimal::from_str(order["px"].as_str().unwrap()).unwrap();
- let size = Decimal::from_str(order["sz"].as_str().unwrap()).unwrap();
- let status = order["state"].as_str().unwrap_or("");
- let filled_size = Decimal::from_str(order["accFillSz"].as_str().unwrap()).unwrap();
- let avg_price = Decimal::from_str(order["avgPx"].as_str().unwrap()).unwrap();
- let amount = size * ct_val;
- let deal_amount = filled_size * ct_val;
- let custom_status = if ["canceled", "filled", "mmp_canceled"].contains(&status) {
- "REMOVE".to_string()
- } else if ["live", "partially_filled"].contains(&status) {
- "NEW".to_string()
- } else {
- "NULL".to_string()
- };
- Order {
- id: order["ordId"].as_str().unwrap().to_string(),
- custom_id: order["clOrdId"].as_str().unwrap().to_string(),
- price,
- amount,
- deal_amount,
- avg_price,
- status: custom_status,
- order_type: order["ordType"].as_str().unwrap().to_string(),
- trace_stack: TraceStack::default().on_special("77 okx_handle".to_string()),
- }
- }
- // 处理特殊深度数据
- pub fn handle_special_depth(res_data: ResponseData) -> SpecialDepth {
- HandleSwapInfo::handle_special_depth(ExchangeEnum::OkxSwap, res_data)
- }
- // 格式化深度信息
- pub fn format_depth_items(value: serde_json::Value) -> Vec<MarketOrder> {
- let mut depth_items: Vec<MarketOrder> = vec![];
- for value in value.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;
- }
- // 处理特殊Ticker信息
- pub fn handle_special_ticker(res_data: ResponseData) -> SpecialDepth {
- let res_data_str = res_data.data;
- let res_data_json: 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 bids = data["bids"][0].as_array().unwrap();
- let asks = data["asks"][0].as_array().unwrap();
- let bp = Decimal::from_str(bids[0].as_str().unwrap()).unwrap();
- let bq = Decimal::from_str(bids[1].as_str().unwrap()).unwrap();
- let ap = Decimal::from_str(asks[0].as_str().unwrap()).unwrap();
- let aq = Decimal::from_str(asks[1].as_str().unwrap()).unwrap();
- let mp = (bp + ap) * dec!(0.5);
- let t = Decimal::from_str(&data["seqId"].to_string()).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,
- }
- }
- // 处理position信息
- pub fn handle_position(res_data: ResponseData, ct_val: Decimal) -> Vec<Position> {
- let res_data_str = res_data.data;
- let data_list: SwapBalanceAndPositionSubscribe = serde_json::from_str(&res_data_str).unwrap();
- let position_data = data_list.pos_data;
- position_data.iter().map(|item| format_position_item(item, ct_val)).collect()
- }
- pub fn format_position_item(value: &SwapBalanceAndPositionPosDataSubscribe, ct_val: Decimal) -> Position {
- let position_mode = match value.pos_side.as_str() {
- "long" => { PositionModeEnum::Long }
- "short" => { PositionModeEnum::Short }
- _ => { PositionModeEnum::Both }
- };
- Position {
- symbol: value.inst_id.replace("-SWAP", ""),
- margin_level: Decimal::ZERO,
- amount: value.pos * ct_val,
- frozen_amount: Decimal::ZERO,
- price: value.avg_px,
- profit: Decimal::ZERO,
- position_mode,
- margin: Decimal::ZERO,
- }
- }
|