|
@@ -3,7 +3,8 @@ use rust_decimal::Decimal;
|
|
|
use serde_json::{from_value, Value};
|
|
use serde_json::{from_value, Value};
|
|
|
use tracing::{error};
|
|
use tracing::{error};
|
|
|
use exchanges::response_base::ResponseData;
|
|
use exchanges::response_base::ResponseData;
|
|
|
-use crate::{Account, OrderBook, Order, Position, PositionModeEnum, SpecialOrder};
|
|
|
|
|
|
|
+use rust_decimal::prelude::FromPrimitive;
|
|
|
|
|
+use crate::{Account, OrderBook, Order, Position, PositionModeEnum, SpecialOrder, Record, Trade};
|
|
|
|
|
|
|
|
// 处理账号信息
|
|
// 处理账号信息
|
|
|
pub fn handle_account_info(res_data: &ResponseData, symbol: &String) -> Account {
|
|
pub fn handle_account_info(res_data: &ResponseData, symbol: &String) -> Account {
|
|
@@ -11,13 +12,13 @@ pub fn handle_account_info(res_data: &ResponseData, symbol: &String) -> Account
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
pub fn format_account_info(data: Vec<Value>, symbol: &String) -> Account {
|
|
pub fn format_account_info(data: Vec<Value>, symbol: &String) -> Account {
|
|
|
- let account = data.iter().find(| &item | item["accountType"] == "UNIFIED");
|
|
|
|
|
|
|
+ let account = data.iter().find(|&item| item["accountType"] == "UNIFIED");
|
|
|
match account {
|
|
match account {
|
|
|
None => {
|
|
None => {
|
|
|
error!("Bybit:格式化统一账户信息错误!\nformat_account_info: data={:?}", data);
|
|
error!("Bybit:格式化统一账户信息错误!\nformat_account_info: data={:?}", data);
|
|
|
panic!("Bybit:格式化统一账户信息错误!\nformat_account_info: data={:?}", data)
|
|
panic!("Bybit:格式化统一账户信息错误!\nformat_account_info: data={:?}", data)
|
|
|
}
|
|
}
|
|
|
- Some(val) =>{
|
|
|
|
|
|
|
+ Some(val) => {
|
|
|
let arr: Vec<Value> = from_value(val["coin"].clone()).unwrap();
|
|
let arr: Vec<Value> = from_value(val["coin"].clone()).unwrap();
|
|
|
let upper_str = symbol.to_uppercase();
|
|
let upper_str = symbol.to_uppercase();
|
|
|
let symbol_array: Vec<&str> = upper_str.split("_").collect();
|
|
let symbol_array: Vec<&str> = upper_str.split("_").collect();
|
|
@@ -60,7 +61,7 @@ pub fn format_position_item(position: &Value, ct_val: &Decimal) -> Position {
|
|
|
panic!("bybit_swap:格式化持仓模式错误!\nformat_position_item:position={:?}", position)
|
|
panic!("bybit_swap:格式化持仓模式错误!\nformat_position_item:position={:?}", position)
|
|
|
}
|
|
}
|
|
|
};
|
|
};
|
|
|
- let symbol_mapper = position["symbol"].as_str().unwrap().to_string();
|
|
|
|
|
|
|
+ let symbol_mapper = position["symbol"].as_str().unwrap().to_string();
|
|
|
let currency = "USDT";
|
|
let currency = "USDT";
|
|
|
let coin = &symbol_mapper[..symbol_mapper.find(currency).unwrap_or(0)];
|
|
let coin = &symbol_mapper[..symbol_mapper.find(currency).unwrap_or(0)];
|
|
|
let size_str: String = from_value(position["size"].clone()).unwrap();
|
|
let size_str: String = from_value(position["size"].clone()).unwrap();
|
|
@@ -77,7 +78,7 @@ pub fn format_position_item(position: &Value, ct_val: &Decimal) -> Position {
|
|
|
_ => {}
|
|
_ => {}
|
|
|
}
|
|
}
|
|
|
Position {
|
|
Position {
|
|
|
- symbol: format!{"{}_{}", coin, currency},
|
|
|
|
|
|
|
+ symbol: format! {"{}_{}", coin, currency},
|
|
|
margin_level: Decimal::from_str(position["leverage"].as_str().unwrap()).unwrap(),
|
|
margin_level: Decimal::from_str(position["leverage"].as_str().unwrap()).unwrap(),
|
|
|
amount,
|
|
amount,
|
|
|
frozen_amount: Decimal::ZERO,
|
|
frozen_amount: Decimal::ZERO,
|
|
@@ -126,7 +127,7 @@ pub fn format_order_item(order: Value, ct_val: Decimal) -> Order {
|
|
|
deal_amount,
|
|
deal_amount,
|
|
|
avg_price,
|
|
avg_price,
|
|
|
status: custom_status,
|
|
status: custom_status,
|
|
|
- order_type: "limit".to_string()
|
|
|
|
|
|
|
+ order_type: "limit".to_string(),
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
return rst_order;
|
|
return rst_order;
|
|
@@ -164,4 +165,44 @@ pub fn format_depth_items(value: serde_json::Value) -> Vec<OrderBook> {
|
|
|
})
|
|
})
|
|
|
}
|
|
}
|
|
|
return depth_items;
|
|
return depth_items;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+pub fn handle_records(value: &Value) -> Vec<Record> {
|
|
|
|
|
+ let mut records = vec![];
|
|
|
|
|
+ let s = value["topic"].as_str().unwrap().to_string();
|
|
|
|
|
+ let s_split: Vec<String> = s.split(".").map(|s| s.to_string()).collect();
|
|
|
|
|
+ let symbol = s_split[2].replace("USDT", "_USDT");
|
|
|
|
|
+ let data = value["data"].clone();
|
|
|
|
|
+ for record_value in data.as_array().unwrap() {
|
|
|
|
|
+ records.push(Record {
|
|
|
|
|
+ time: Decimal::from_i64(record_value["timestamp"].as_i64().unwrap()).unwrap(),
|
|
|
|
|
+ open: Decimal::from_str(record_value["open"].as_str().unwrap()).unwrap(),
|
|
|
|
|
+ high: Decimal::from_str(record_value["high"].as_str().unwrap()).unwrap(),
|
|
|
|
|
+ low: Decimal::from_str(record_value["low"].as_str().unwrap()).unwrap(),
|
|
|
|
|
+ close: Decimal::from_str(record_value["close"].as_str().unwrap()).unwrap(),
|
|
|
|
|
+ volume: Decimal::from_str(record_value["volume"].as_str().unwrap()).unwrap(),
|
|
|
|
|
+ symbol: symbol.clone(),
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return records;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+pub fn format_trade_items(res_data: &ResponseData) -> Vec<Trade> {
|
|
|
|
|
+ let result = res_data.data["data"].as_array().unwrap();
|
|
|
|
|
+ let mut trades = vec![];
|
|
|
|
|
+
|
|
|
|
|
+ for item in result {
|
|
|
|
|
+ let side = item["S"].as_str().unwrap();
|
|
|
|
|
+ let size = Decimal::from_str(item["v"].as_str().unwrap()).unwrap();
|
|
|
|
|
+ trades.push(Trade {
|
|
|
|
|
+ id: item["i"].to_string(),
|
|
|
|
|
+ time: Decimal::from_i64(item["T"].as_i64().unwrap()).unwrap(),
|
|
|
|
|
+ size: if side == "Buy" { size } else { -size },
|
|
|
|
|
+ price: Decimal::from_str(item["p"].as_str().unwrap()).unwrap(),
|
|
|
|
|
+ symbol: item["s"].as_str().unwrap().replace("USDT", "_USDT"),
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return trades;
|
|
|
}
|
|
}
|