|
|
@@ -1,6 +1,7 @@
|
|
|
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;
|
|
|
@@ -12,22 +13,24 @@ use crate::{Account, Depth, Order, OrderBook, Position, PositionModeEnum, Record
|
|
|
// 处理账号信息
|
|
|
pub fn handle_account_info(res_data: &ResponseData, symbol: &String) -> Account {
|
|
|
let symbol_format = utils::format_symbol(symbol.clone(), "");
|
|
|
- let res_data_json = res_data.data.as_array().unwrap();
|
|
|
+ let res_data_json = res_data.data["a"]["B"].as_array().unwrap();
|
|
|
|
|
|
-
|
|
|
- let balance_info = res_data_json.iter().find(|&item| item["result"].as_str().unwrap().contains(&symbol_format));
|
|
|
+ let balance_info = res_data_json.iter().find(|&item| symbol_format.ends_with(item["a"].as_str().unwrap()));
|
|
|
match balance_info {
|
|
|
None => {
|
|
|
error!("Gate:格式化账号信息错误!\nformat_account_info: data={:?}", res_data_json);
|
|
|
panic!("Gate:格式化账号信息错误!\nformat_account_info: data={:?}", res_data_json)
|
|
|
}
|
|
|
Some(value) => {
|
|
|
- let balance = Decimal::from_str(&value["balance"].as_f64().unwrap().to_string()).unwrap();
|
|
|
+ let coin = value["a"].as_str().unwrap().to_string();
|
|
|
+ let balance = Decimal::from_str(&value["wb"].as_str().unwrap()).unwrap();
|
|
|
+ let available_balance = Decimal::from_str(&value["cw"].as_str().unwrap()).unwrap();
|
|
|
+ let frozen_balance = balance - available_balance;
|
|
|
Account {
|
|
|
- coin: symbol_format,
|
|
|
+ coin,
|
|
|
balance,
|
|
|
- available_balance: Decimal::ZERO,
|
|
|
- frozen_balance: Decimal::ZERO,
|
|
|
+ available_balance,
|
|
|
+ frozen_balance,
|
|
|
stocks: Decimal::ZERO,
|
|
|
available_stocks: Decimal::ZERO,
|
|
|
frozen_stocks: Decimal::ZERO,
|
|
|
@@ -38,20 +41,20 @@ pub fn handle_account_info(res_data: &ResponseData, symbol: &String) -> Account
|
|
|
|
|
|
// 处理position信息
|
|
|
pub fn handle_position(res_data: &ResponseData, mul: &Decimal) -> Vec<Position> {
|
|
|
- let res_data_json = res_data.data.as_array().unwrap();
|
|
|
+ let res_data_json = res_data.data["a"]["P"].as_array().unwrap();
|
|
|
res_data_json.iter().map(|item| { format_position_item(item, mul) }).collect()
|
|
|
}
|
|
|
pub fn format_position_item(position: &Value, ct_val: &Decimal) -> Position {
|
|
|
- let mut position_mode = match position["mode"].as_str().unwrap_or("") {
|
|
|
- "single" => PositionModeEnum::Both,
|
|
|
- "dual_long" => PositionModeEnum::Long,
|
|
|
- "dual_short" => PositionModeEnum::Short,
|
|
|
+ let mut position_mode = match position["ps"].as_str().unwrap_or("") {
|
|
|
+ "BOTH" => PositionModeEnum::Both,
|
|
|
+ "LONG" => PositionModeEnum::Long,
|
|
|
+ "SHORT" => PositionModeEnum::Short,
|
|
|
_ => {
|
|
|
error!("Gate:格式化持仓模式错误!\nformat_position_item:position={:?}", position);
|
|
|
panic!("Gate:格式化持仓模式错误!\nformat_position_item:position={:?}", position)
|
|
|
}
|
|
|
};
|
|
|
- let size = Decimal::from_str(&position["size"].as_f64().unwrap().to_string()).unwrap();
|
|
|
+ let size = Decimal::from_str(&position["pa"].as_str().unwrap()).unwrap();
|
|
|
let amount = size * ct_val;
|
|
|
match position_mode {
|
|
|
PositionModeEnum::Both => {
|
|
|
@@ -64,24 +67,22 @@ pub fn format_position_item(position: &Value, ct_val: &Decimal) -> Position {
|
|
|
_ => {}
|
|
|
}
|
|
|
Position {
|
|
|
- symbol: position["contract"].as_str().unwrap().to_string(),
|
|
|
- margin_level: Decimal::from_str(&position["leverage"].as_f64().unwrap().to_string()).unwrap(),
|
|
|
+ symbol: position["s"].as_str().unwrap().to_string(),
|
|
|
+ margin_level: dec!(-1),
|
|
|
amount,
|
|
|
frozen_amount: Decimal::ZERO,
|
|
|
- price: Decimal::from_str(&position["entry_price"].as_f64().unwrap().to_string()).unwrap(),
|
|
|
- profit: Decimal::from_str(&position["realised_pnl"].as_f64().unwrap().to_string()).unwrap(),
|
|
|
+ price: Decimal::from_str(&position["ep"].as_str().unwrap()).unwrap(),
|
|
|
+ profit: Decimal::from_str(&position["up"].as_str().unwrap()).unwrap(),
|
|
|
position_mode,
|
|
|
- margin: Decimal::from_str(&position["margin"].as_f64().unwrap().to_string()).unwrap(),
|
|
|
+ margin: Decimal::from_str(&position["iw"].as_str().unwrap()).unwrap(),
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 处理order信息
|
|
|
pub fn handle_order(res_data: &ResponseData, ct_val: &Decimal) -> SpecialOrder {
|
|
|
- let res_data_json = res_data.data.as_array().unwrap();
|
|
|
- let mut order_info = Vec::new();
|
|
|
- for item in res_data_json.iter() {
|
|
|
- order_info.push(format_order_item(item.clone(), ct_val));
|
|
|
- };
|
|
|
+ let res_data_json = res_data.data["o"].clone();
|
|
|
+ let order_info = vec![format_order_item(res_data_json.clone(), ct_val)];
|
|
|
+
|
|
|
|
|
|
SpecialOrder {
|
|
|
name: res_data.label.clone(),
|
|
|
@@ -99,7 +100,7 @@ pub fn format_order_item(order: Value, ct_val: &Decimal) -> Order {
|
|
|
|
|
|
let status = order["X"].as_str().unwrap();
|
|
|
|
|
|
- let custom_status = if vec!["FILLED", "CANCELED", "REJECTED", "EXPIRED"].contains(&status) { "REMOVE".to_string() } else if ["NEW", "PARTIALLY_FILLED "].contains(&status) { "NEW".to_string() } else {
|
|
|
+ let custom_status = if vec!["FILLED", "CANCELED", "REJECTED", "EXPIRED"].contains(&status) { "REMOVE".to_string() } else if ["NEW", "PARTIALLY_FILLED"].contains(&status) { "NEW".to_string() } else {
|
|
|
error!("Gate:格式化订单状态错误!\nformat_order_item:order={:?}", order);
|
|
|
panic!("Gate:格式化订单状态错误!\nformat_order_item:order={:?}", order)
|
|
|
};
|
|
|
@@ -112,7 +113,7 @@ pub fn format_order_item(order: Value, ct_val: &Decimal) -> Order {
|
|
|
avg_price,
|
|
|
status: custom_status,
|
|
|
order_type: "limit".to_string(),
|
|
|
- trace_stack: TraceStack::new(0, Instant::now()).on_special("120 binance_handle".to_string()),
|
|
|
+ trace_stack: TraceStack::new(0, Instant::now()).on_special("115 binance_handle".to_string()),
|
|
|
};
|
|
|
|
|
|
return rst_order;
|
|
|
@@ -121,11 +122,11 @@ pub fn format_order_item(order: Value, ct_val: &Decimal) -> Order {
|
|
|
// 处理特殊Ticket信息
|
|
|
pub fn handle_book_ticker(res_data: &ResponseData, mul: &Decimal) -> Depth {
|
|
|
let bid_price = Decimal::from_str(res_data.data["b"].as_str().unwrap()).unwrap();
|
|
|
- let bid_amount = Decimal::from_f64(res_data.data["B"].as_f64().unwrap()).unwrap();
|
|
|
+ let bid_amount = Decimal::from_str(res_data.data["B"].as_str().unwrap()).unwrap();
|
|
|
let ask_price = Decimal::from_str(res_data.data["a"].as_str().unwrap()).unwrap();
|
|
|
- let ask_amount = Decimal::from_f64(res_data.data["A"].as_f64().unwrap()).unwrap();
|
|
|
+ let ask_amount = Decimal::from_str(res_data.data["A"].as_str().unwrap()).unwrap();
|
|
|
// let u = Decimal::from_u64((*res_data).data["u"].as_u64().unwrap()).unwrap();
|
|
|
- let t = Decimal::from_i64(res_data.data["t"].as_i64().unwrap()).unwrap();
|
|
|
+ let t = Decimal::from_i64(res_data.data["T"].as_i64().unwrap()).unwrap();
|
|
|
let s = res_data.data["s"].as_str().unwrap().replace("USDT", "_USDT");
|
|
|
|
|
|
let asks = vec![
|