|
|
@@ -1,13 +1,15 @@
|
|
|
-use std::collections::{BTreeMap};
|
|
|
+use std::collections::{BTreeMap, HashMap};
|
|
|
use std::io::{Error, ErrorKind};
|
|
|
use std::str::FromStr;
|
|
|
use tokio::sync::mpsc::Sender;
|
|
|
use async_trait::async_trait;
|
|
|
+use futures::stream::FuturesUnordered;
|
|
|
+use futures::TryStreamExt;
|
|
|
use rust_decimal::Decimal;
|
|
|
use rust_decimal::prelude::ToPrimitive;
|
|
|
use rust_decimal_macros::dec;
|
|
|
use serde_json::json;
|
|
|
-use tracing::error;
|
|
|
+use tracing::{error, warn};
|
|
|
use exchanges::bitget_spot_rest::BitgetSpotRest;
|
|
|
use global::trace_stack::TraceStack;
|
|
|
use crate::exchange::ExchangeEnum;
|
|
|
@@ -29,7 +31,7 @@ pub struct BitgetSpot {
|
|
|
impl BitgetSpot {
|
|
|
pub async fn new(symbol: String, is_colo: bool, params: BTreeMap<String, String>, order_sender: Sender<Order>, error_sender: Sender<Error>) -> BitgetSpot {
|
|
|
let market = Market::new();
|
|
|
- let bitget_spot = BitgetSpot {
|
|
|
+ let mut bitget_spot = BitgetSpot {
|
|
|
exchange: ExchangeEnum::BitgetSpot,
|
|
|
symbol: symbol.to_uppercase(),
|
|
|
is_colo,
|
|
|
@@ -39,7 +41,7 @@ impl BitgetSpot {
|
|
|
order_sender,
|
|
|
error_sender,
|
|
|
};
|
|
|
- // bitget_spot.market = BitgetSpot::get_market(&mut bitget_spot).await.unwrap_or(bitget_spot.market);
|
|
|
+ bitget_spot.market = BitgetSpot::get_market(&mut bitget_spot).await.unwrap_or(bitget_spot.market);
|
|
|
return bitget_spot;
|
|
|
}
|
|
|
}
|
|
|
@@ -65,7 +67,7 @@ impl Platform for BitgetSpot {
|
|
|
fn get_request_max_delay(&self) -> i64 { self.request.get_max_delay() }
|
|
|
|
|
|
async fn get_server_time(&mut self) -> Result<String, Error> {
|
|
|
- todo!()
|
|
|
+ Err(Error::new(ErrorKind::NotFound, "bitget_spot:该交易所方法未实现".to_string()))
|
|
|
// let res_data = self.request.get().await;
|
|
|
// if res_data.code == "200" {
|
|
|
// let res_data_str = &res_data.data;
|
|
|
@@ -82,6 +84,7 @@ impl Platform for BitgetSpot {
|
|
|
if res_data.code == "200" {
|
|
|
let res_data_str = &res_data.data;
|
|
|
let res_data_json: Vec<serde_json::Value> = serde_json::from_str(res_data_str).unwrap();
|
|
|
+ println!("{:?}", res_data_json);
|
|
|
let account_info = res_data_json[0].clone();
|
|
|
|
|
|
let available_balance = Decimal::from_str(account_info["available"].as_str().unwrap()).unwrap();
|
|
|
@@ -102,9 +105,9 @@ impl Platform for BitgetSpot {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- async fn get_position(&mut self) -> Result<Vec<Position>, Error> { todo!() }
|
|
|
+ async fn get_position(&mut self) -> Result<Vec<Position>, Error> { Err(Error::new(ErrorKind::NotFound, "bitget_spot:该交易所方法未实现".to_string())) }
|
|
|
|
|
|
- async fn get_positions(&mut self) -> Result<Vec<Position>, Error> { todo!() }
|
|
|
+ async fn get_positions(&mut self) -> Result<Vec<Position>, Error> { Err(Error::new(ErrorKind::NotFound, "bitget_spot:该交易所方法未实现".to_string())) }
|
|
|
|
|
|
async fn get_ticker(&mut self) -> Result<Ticker, Error> {
|
|
|
let symbol_format = utils::format_symbol(self.symbol.clone(), "");
|
|
|
@@ -112,15 +115,16 @@ impl Platform for BitgetSpot {
|
|
|
if res_data.code == "200" {
|
|
|
let res_data_str = &res_data.data;
|
|
|
let res_data_json: serde_json::Value = serde_json::from_str(res_data_str).unwrap();
|
|
|
- let time = (Decimal::from_str(&*res_data_json["ts"].as_str().unwrap()).unwrap() / dec!(1000)).floor().to_i64().unwrap();
|
|
|
+ let ticker_info = res_data_json[0].clone();
|
|
|
+ let time = (Decimal::from_str(&*ticker_info["ts"].as_str().unwrap()).unwrap() / dec!(1000)).floor().to_i64().unwrap();
|
|
|
let result = Ticker {
|
|
|
time,
|
|
|
- high: Decimal::from_str(res_data_json["high24h"].as_str().unwrap()).unwrap(),
|
|
|
- low: Decimal::from_str(res_data_json["low24h"].as_str().unwrap()).unwrap(),
|
|
|
- sell: Decimal::from_str(res_data_json["askPr"].as_str().unwrap()).unwrap(),
|
|
|
- buy: Decimal::from_str(res_data_json["bidPr"].as_str().unwrap()).unwrap(),
|
|
|
- last: Decimal::from_str(res_data_json["lastPr"].as_str().unwrap()).unwrap(),
|
|
|
- volume: Decimal::from_str(res_data_json["quoteVolume"].as_str().unwrap()).unwrap(),
|
|
|
+ high: Decimal::from_str(ticker_info["high24h"].as_str().unwrap()).unwrap(),
|
|
|
+ low: Decimal::from_str(ticker_info["low24h"].as_str().unwrap()).unwrap(),
|
|
|
+ sell: Decimal::from_str(ticker_info["askPr"].as_str().unwrap()).unwrap(),
|
|
|
+ buy: Decimal::from_str(ticker_info["bidPr"].as_str().unwrap()).unwrap(),
|
|
|
+ last: Decimal::from_str(ticker_info["lastPr"].as_str().unwrap()).unwrap(),
|
|
|
+ volume: Decimal::from_str(ticker_info["quoteVolume"].as_str().unwrap()).unwrap(),
|
|
|
};
|
|
|
Ok(result)
|
|
|
} else {
|
|
|
@@ -128,21 +132,40 @@ impl Platform for BitgetSpot {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- async fn get_ticker_symbol(&mut self, _symbol: String) -> Result<Ticker, Error> {
|
|
|
- todo!()
|
|
|
+ async fn get_ticker_symbol(&mut self, symbol: String) -> Result<Ticker, Error> {
|
|
|
+ let symbol_format = utils::format_symbol(symbol.clone(), "");
|
|
|
+ let res_data = self.request.get_tickers(symbol_format).await;
|
|
|
+ if res_data.code == "200" {
|
|
|
+ let res_data_str = &res_data.data;
|
|
|
+ let res_data_json: serde_json::Value = serde_json::from_str(res_data_str).unwrap();
|
|
|
+ let ticker_info = res_data_json[0].clone();
|
|
|
+ let time = (Decimal::from_str(&*ticker_info["ts"].as_str().unwrap()).unwrap() / dec!(1000)).floor().to_i64().unwrap();
|
|
|
+ let result = Ticker {
|
|
|
+ time,
|
|
|
+ high: Decimal::from_str(ticker_info["high24h"].as_str().unwrap()).unwrap(),
|
|
|
+ low: Decimal::from_str(ticker_info["low24h"].as_str().unwrap()).unwrap(),
|
|
|
+ sell: Decimal::from_str(ticker_info["askPr"].as_str().unwrap()).unwrap(),
|
|
|
+ buy: Decimal::from_str(ticker_info["bidPr"].as_str().unwrap()).unwrap(),
|
|
|
+ last: Decimal::from_str(ticker_info["lastPr"].as_str().unwrap()).unwrap(),
|
|
|
+ volume: Decimal::from_str(ticker_info["quoteVolume"].as_str().unwrap()).unwrap(),
|
|
|
+ };
|
|
|
+ Ok(result)
|
|
|
+ } else {
|
|
|
+ Err(Error::new(ErrorKind::Other, res_data.to_string()))
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
async fn get_market(&mut self) -> Result<Market, Error> {
|
|
|
let symbol_format = utils::format_symbol(self.symbol.clone(), "");
|
|
|
- let res_data = self.request.get_market_fills("".to_string(), "".to_string()).await;
|
|
|
+ let res_data = self.request.get_symbols(symbol_format.clone()).await;
|
|
|
if res_data.code == "200" {
|
|
|
let res_data_str = &res_data.data;
|
|
|
let res_data_json: Vec<serde_json::Value> = serde_json::from_str(res_data_str).unwrap();
|
|
|
- let market_info = res_data_json.iter().find(|item| item["symbol"].as_str().unwrap() == symbol_format);
|
|
|
+ let market_info = res_data_json.iter().find(|&item| item["symbol"].as_str().unwrap() == symbol_format.clone());
|
|
|
match market_info {
|
|
|
None => {
|
|
|
- error!("Gate:获取Market信息错误!\nget_market:market_info={:?}", market_info);
|
|
|
- panic!("Gate:获取Market信息错误!\nget_market:market_info={:?}", market_info)
|
|
|
+ error!("Bitget:获取Market信息错误!\nget_market:market_info={:?}", market_info);
|
|
|
+ panic!("Bitget:获取Market信息错误!\nget_market:market_info={:?}", market_info)
|
|
|
}
|
|
|
Some(value) => {
|
|
|
let base_asset = value["baseCoin"].as_str().unwrap().to_string();
|
|
|
@@ -174,14 +197,51 @@ impl Platform for BitgetSpot {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- async fn get_market_symbol(&mut self, _symbol: String) -> Result<Market, Error> {
|
|
|
- todo!()
|
|
|
+ async fn get_market_symbol(&mut self, symbol: String) -> Result<Market, Error> {
|
|
|
+ let symbol_format = utils::format_symbol(symbol.clone(), "");
|
|
|
+ let res_data = self.request.get_symbols(symbol_format.clone()).await;
|
|
|
+ if res_data.code == "200" {
|
|
|
+ let res_data_str = &res_data.data;
|
|
|
+ let res_data_json: Vec<serde_json::Value> = serde_json::from_str(res_data_str).unwrap();
|
|
|
+ let market_info = res_data_json.iter().find(|&item| item["symbol"].as_str().unwrap() == symbol_format.clone());
|
|
|
+ match market_info {
|
|
|
+ None => {
|
|
|
+ error!("Bitget:获取Market信息错误!\nget_market:market_info={:?}", market_info);
|
|
|
+ panic!("Bitget:获取Market信息错误!\nget_market:market_info={:?}", market_info)
|
|
|
+ }
|
|
|
+ Some(value) => {
|
|
|
+ let base_asset = value["baseCoin"].as_str().unwrap().to_string();
|
|
|
+ let quote_asset = value["quoteCoin"].as_str().unwrap().to_string();
|
|
|
+ let price_precision = Decimal::from_str(value["pricePrecision"].as_str().unwrap()).unwrap();
|
|
|
+ let amount_precision = Decimal::from_str(value["quantityPrecision"].as_str().unwrap()).unwrap();
|
|
|
+ let tick_size = Decimal::from_str(&format!("0.{}", "0".repeat(usize::try_from(price_precision).unwrap()))).unwrap();
|
|
|
+ let amount_size = Decimal::from_str(&format!("0.{}", "0".repeat(usize::try_from(amount_precision).unwrap()))).unwrap();
|
|
|
+
|
|
|
+ let result = Market {
|
|
|
+ symbol: format!("{}_{}", base_asset, quote_asset),
|
|
|
+ base_asset,
|
|
|
+ quote_asset,
|
|
|
+ tick_size,
|
|
|
+ amount_size,
|
|
|
+ price_precision,
|
|
|
+ amount_precision,
|
|
|
+ min_qty: Decimal::from_str(&value["minTradeAmount"].as_str().unwrap()).unwrap(),
|
|
|
+ max_qty: Decimal::from_str(&value["maxTradeAmount"].as_str().unwrap()).unwrap(),
|
|
|
+ min_notional: Default::default(),
|
|
|
+ max_notional: Default::default(),
|
|
|
+ ct_val: Default::default(),
|
|
|
+ };
|
|
|
+ Ok(result)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ Err(Error::new(ErrorKind::Other, res_data.to_string()))
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
async fn get_order_detail(&mut self, order_id: &str, custom_id: &str) -> Result<Order, Error> {
|
|
|
let amount_size = self.market.amount_size;
|
|
|
- let id = if order_id.eq("") { custom_id.to_string() } else { order_id.to_string() };
|
|
|
- let res_data = self.request.get_order(id, "".to_string()).await;
|
|
|
+ let res_data = self.request.get_order(order_id.to_string(), custom_id.to_string()).await;
|
|
|
if res_data.code == "200" {
|
|
|
let res_data_str = &res_data.data;
|
|
|
let res_data_json: Vec<serde_json::Value> = serde_json::from_str(res_data_str).unwrap();
|
|
|
@@ -193,15 +253,14 @@ impl Platform for BitgetSpot {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- async fn get_orders_list(&mut self, status: &str) -> Result<Vec<Order>, Error> {
|
|
|
+ async fn get_orders_list(&mut self, _status: &str) -> Result<Vec<Order>, Error> {
|
|
|
let symbol_format = utils::format_symbol(self.symbol.clone(), "");
|
|
|
let amount_size = self.market.amount_size;
|
|
|
- let res_data = self.request.get_unfilled_orders(status.to_string(), symbol_format.to_string(), "".to_string(), "".to_string(), "".to_string(), "".to_string()).await;
|
|
|
+ let res_data = self.request.get_unfilled_orders(symbol_format.to_string(), "".to_string(), "".to_string(), "".to_string(), "100".to_string(), "".to_string()).await;
|
|
|
if res_data.code == "200" {
|
|
|
let res_data_str = &res_data.data;
|
|
|
let res_data_json: Vec<serde_json::Value> = serde_json::from_str(res_data_str).unwrap();
|
|
|
- let order_info: Vec<_> = res_data_json.iter().filter(|item| item["symbol"].as_str().unwrap_or("") == symbol_format.to_lowercase()).collect();
|
|
|
- let result = order_info.iter().map(|&item| bitget_spot_handle::format_order_item(item.clone(), amount_size)).collect();
|
|
|
+ let result = res_data_json.iter().map(|item| bitget_spot_handle::format_order_item(item.clone(), amount_size)).collect();
|
|
|
Ok(result)
|
|
|
} else {
|
|
|
Err(Error::new(ErrorKind::Other, res_data.to_string()))
|
|
|
@@ -218,22 +277,19 @@ impl Platform for BitgetSpot {
|
|
|
"force": "gtc"
|
|
|
});
|
|
|
let size = amount;
|
|
|
+ params["size"] = json!(size);
|
|
|
match origin_side {
|
|
|
"kd" => {
|
|
|
params["side"] = json!("buy");
|
|
|
- params["size"] = json!(size);
|
|
|
}
|
|
|
"pd" => {
|
|
|
- params["side"] = json!(true);
|
|
|
- params["size"] = json!(size);
|
|
|
+ params["side"] = json!("sell");
|
|
|
}
|
|
|
"kk" => {
|
|
|
- params["side"] = json!(false);
|
|
|
- params["size"] = json!(size);
|
|
|
+ params["side"] = json!("sell");
|
|
|
}
|
|
|
"pk" => {
|
|
|
- params["side"] = json!(true);
|
|
|
- params["size"] = json!(size);
|
|
|
+ params["side"] = json!("buy");
|
|
|
}
|
|
|
_ => { error!("下单参数错误"); }
|
|
|
};
|
|
|
@@ -250,7 +306,7 @@ impl Platform for BitgetSpot {
|
|
|
avg_price: dec!(0),
|
|
|
status: "NEW".to_string(),
|
|
|
order_type: "".to_string(),
|
|
|
- trace_stack: TraceStack::default().on_special("245 bitget_spot".to_string()),
|
|
|
+ trace_stack: TraceStack::default().on_special("308 bitget_spot".to_string()),
|
|
|
};
|
|
|
Ok(result)
|
|
|
} else {
|
|
|
@@ -268,22 +324,19 @@ impl Platform for BitgetSpot {
|
|
|
"force": "gtc"
|
|
|
});
|
|
|
let size = amount;
|
|
|
+ params["size"] = json!(size);
|
|
|
match origin_side {
|
|
|
"kd" => {
|
|
|
params["side"] = json!("buy");
|
|
|
- params["size"] = json!(size);
|
|
|
}
|
|
|
"pd" => {
|
|
|
- params["side"] = json!(true);
|
|
|
- params["size"] = json!(size);
|
|
|
+ params["side"] = json!("sell");
|
|
|
}
|
|
|
"kk" => {
|
|
|
- params["side"] = json!(false);
|
|
|
- params["size"] = json!(size);
|
|
|
+ params["side"] = json!("sell");
|
|
|
}
|
|
|
"pk" => {
|
|
|
- params["side"] = json!(true);
|
|
|
- params["size"] = json!(size);
|
|
|
+ params["side"] = json!("buy");
|
|
|
}
|
|
|
_ => { error!("下单参数错误"); }
|
|
|
};
|
|
|
@@ -300,7 +353,7 @@ impl Platform for BitgetSpot {
|
|
|
avg_price: dec!(0),
|
|
|
status: "NEW".to_string(),
|
|
|
order_type: "".to_string(),
|
|
|
- trace_stack: TraceStack::default().on_special("295 bitget_spot".to_string()),
|
|
|
+ trace_stack: TraceStack::default().on_special("355 bitget_spot".to_string()),
|
|
|
};
|
|
|
Ok(result)
|
|
|
} else {
|
|
|
@@ -309,9 +362,8 @@ impl Platform for BitgetSpot {
|
|
|
}
|
|
|
|
|
|
async fn cancel_order(&mut self, order_id: &str, custom_id: &str) -> Result<Order, Error> {
|
|
|
- // let symbol_format = utils::format_symbol(self.symbol.clone(), "");
|
|
|
- // let id = if order_id.eq("") { custom_id.to_string() } else { order_id.to_string() };
|
|
|
- let res_data = self.request.cancel_plan_order(order_id.to_string(), custom_id.to_string()).await;
|
|
|
+ let symbol_format = utils::format_symbol(self.symbol.clone(), "");
|
|
|
+ let res_data = self.request.spot_cancel_order(symbol_format.clone(), order_id.to_string(), custom_id.to_string()).await;
|
|
|
if res_data.code == "200" {
|
|
|
let res_data_str = &res_data.data;
|
|
|
let res_data_json: serde_json::Value = serde_json::from_str(res_data_str).unwrap();
|
|
|
@@ -324,7 +376,7 @@ impl Platform for BitgetSpot {
|
|
|
avg_price: dec!(0),
|
|
|
status: "REMOVE".to_string(),
|
|
|
order_type: "".to_string(),
|
|
|
- trace_stack: TraceStack::default().on_special("319 bitget_spot".to_string()),
|
|
|
+ trace_stack: TraceStack::default().on_special("379 bitget_spot".to_string()),
|
|
|
};
|
|
|
Ok(result)
|
|
|
} else {
|
|
|
@@ -334,7 +386,7 @@ impl Platform for BitgetSpot {
|
|
|
|
|
|
async fn cancel_orders(&mut self) -> Result<Vec<Order>, Error> {
|
|
|
let symbol_format = utils::format_symbol(self.symbol.clone(), "");
|
|
|
- let res_data = self.request.cancel_plan_orders(symbol_format.clone()).await;
|
|
|
+ let res_data = self.request.spot_cancel_symbol_orders(symbol_format.to_string()).await;
|
|
|
if res_data.code == "200" {
|
|
|
let res_data_str = &res_data.data;
|
|
|
let res_data_json: serde_json::Value = serde_json::from_str(res_data_str).unwrap();
|
|
|
@@ -349,7 +401,7 @@ impl Platform for BitgetSpot {
|
|
|
avg_price: dec!(0),
|
|
|
status: "REMOVE".to_string(),
|
|
|
order_type: "".to_string(),
|
|
|
- trace_stack: TraceStack::default().on_special("344 bitget_spot".to_string()),
|
|
|
+ trace_stack: TraceStack::default().on_special("404 bitget_spot".to_string()),
|
|
|
}
|
|
|
).collect();
|
|
|
Ok(result)
|
|
|
@@ -358,26 +410,129 @@ impl Platform for BitgetSpot {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- async fn cancel_orders_all(&mut self) -> Result<Vec<Order>, Error> { todo!() }
|
|
|
+ async fn cancel_orders_all(&mut self) -> Result<Vec<Order>, Error> {
|
|
|
+ Err(Error::new(ErrorKind::NotFound, "bitget_spot:该交易所方法未实现".to_string()))
|
|
|
+ }
|
|
|
|
|
|
async fn set_dual_mode(&mut self, _coin: &str, _is_dual_mode: bool) -> Result<String, Error> {
|
|
|
- todo!()
|
|
|
+ Err(Error::new(ErrorKind::NotFound, "bitget_spot:该交易所方法未实现".to_string()))
|
|
|
}
|
|
|
|
|
|
async fn set_dual_leverage(&mut self, _leverage: &str) -> Result<String, Error> {
|
|
|
- todo!()
|
|
|
+ Err(Error::new(ErrorKind::NotFound, "bitget_spot:该交易所方法未实现".to_string()))
|
|
|
}
|
|
|
|
|
|
async fn set_auto_deposit_status(&mut self, _status: bool) -> Result<String, Error> {
|
|
|
- todo!()
|
|
|
+ Err(Error::new(ErrorKind::NotFound, "bitget_spot:该交易所方法未实现".to_string()))
|
|
|
}
|
|
|
|
|
|
async fn wallet_transfers(&mut self, _coin: &str, _from: &str, _to: &str, _amount: Decimal) -> Result<String, Error> {
|
|
|
- todo!()
|
|
|
+ Err(Error::new(ErrorKind::NotFound, "bitget_spot:该交易所方法未实现".to_string()))
|
|
|
}
|
|
|
|
|
|
- async fn command_order(&mut self, _order_command: OrderCommand, _trace_stack: TraceStack) {
|
|
|
- todo!()
|
|
|
+ async fn command_order(&mut self, order_command: OrderCommand, trace_stack: TraceStack) {
|
|
|
+ let mut handles = vec![];
|
|
|
+ // 撤销订单
|
|
|
+ let cancel = order_command.cancel;
|
|
|
+ for item in cancel.keys() {
|
|
|
+ let mut self_clone = self.clone();
|
|
|
+ let cancel_clone = cancel.clone();
|
|
|
+ let item_clone = item.clone();
|
|
|
+ let order_id = cancel_clone[&item_clone].get(1).unwrap_or(&"".to_string()).clone();
|
|
|
+ let custom_id = cancel_clone[&item_clone].get(0).unwrap_or(&"".to_string()).clone();
|
|
|
+ let result_sd = self.order_sender.clone();
|
|
|
+ let err_sd = self.error_sender.clone();
|
|
|
+ let handle = tokio::spawn(async move {
|
|
|
+ let result = self_clone.cancel_order(&order_id, &custom_id).await;
|
|
|
+ match result {
|
|
|
+ Ok(_) => {
|
|
|
+ // result_sd.send(result).await.unwrap();
|
|
|
+ }
|
|
|
+ Err(error) => {
|
|
|
+ // 取消失败去查订单。
|
|
|
+ let query_rst = self_clone.get_order_detail(&order_id, &custom_id).await;
|
|
|
+ match query_rst {
|
|
|
+ Ok(order) => {
|
|
|
+ result_sd.send(order).await.unwrap();
|
|
|
+ }
|
|
|
+ Err(_) => {
|
|
|
+ error!("撤单失败,而且查单也失败了,gate_io_swap,oid={}, cid={}。", order_id.clone(), custom_id.clone());
|
|
|
+ panic!("撤单失败,而且查单也失败了,gate_io_swap,oid={}, cid={}。", order_id.clone(), custom_id.clone());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ err_sd.send(error).await.unwrap();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ handles.push(handle)
|
|
|
+ }
|
|
|
+ // 下单指令
|
|
|
+ let mut limits = HashMap::new();
|
|
|
+ limits.extend(order_command.limits_open);
|
|
|
+ limits.extend(order_command.limits_close);
|
|
|
+ for item in limits.keys() {
|
|
|
+ let mut self_clone = self.clone();
|
|
|
+ let limits_clone = limits.clone();
|
|
|
+ let item_clone = item.clone();
|
|
|
+ let result_sd = self.order_sender.clone();
|
|
|
+ let err_sd = self.error_sender.clone();
|
|
|
+ let mut ts = trace_stack.clone();
|
|
|
+
|
|
|
+ let handle = tokio::spawn(async move {
|
|
|
+ let value = limits_clone[&item_clone].clone();
|
|
|
+ let amount = Decimal::from_str(value.get(0).unwrap_or(&"0".to_string())).unwrap();
|
|
|
+ let side = value.get(1).unwrap();
|
|
|
+ let price = Decimal::from_str(value.get(2).unwrap_or(&"0".to_string())).unwrap();
|
|
|
+ let cid = value.get(3).unwrap();
|
|
|
+
|
|
|
+ // order_name: [数量,方向,价格,c_id]
|
|
|
+ let result = self_clone.take_order(cid, side, price, amount).await;
|
|
|
+ match result {
|
|
|
+ Ok(mut result) => {
|
|
|
+ // 记录此订单完成时间
|
|
|
+ ts.on_after_send();
|
|
|
+ result.trace_stack = ts;
|
|
|
+
|
|
|
+ result_sd.send(result).await.unwrap();
|
|
|
+ }
|
|
|
+ Err(error) => {
|
|
|
+ let mut err_order = Order::new();
|
|
|
+ err_order.custom_id = cid.clone();
|
|
|
+ err_order.status = "REMOVE".to_string();
|
|
|
+
|
|
|
+ result_sd.send(err_order).await.unwrap();
|
|
|
+ err_sd.send(error).await.unwrap();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ handles.push(handle)
|
|
|
+ }
|
|
|
+ // 检查订单指令
|
|
|
+ let check = order_command.check;
|
|
|
+ for item in check.keys() {
|
|
|
+ let mut self_clone = self.clone();
|
|
|
+ let check_clone = check.clone();
|
|
|
+ let item_clone = item.clone();
|
|
|
+ let order_id = check_clone[&item_clone].get(1).unwrap_or(&"".to_string()).clone();
|
|
|
+ let custom_id = check_clone[&item_clone].get(0).unwrap_or(&"".to_string()).clone();
|
|
|
+ let result_sd = self.order_sender.clone();
|
|
|
+ let err_sd = self.error_sender.clone();
|
|
|
+ let handle = tokio::spawn(async move {
|
|
|
+ let result = self_clone.get_order_detail(&order_id, &custom_id).await;
|
|
|
+ match result {
|
|
|
+ Ok(result) => {
|
|
|
+ result_sd.send(result).await.unwrap();
|
|
|
+ }
|
|
|
+ Err(error) => {
|
|
|
+ err_sd.send(error).await.unwrap();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ handles.push(handle)
|
|
|
+ }
|
|
|
+
|
|
|
+ let futures = FuturesUnordered::from_iter(handles);
|
|
|
+ let _: Result<Vec<_>, _> = futures.try_collect().await;
|
|
|
}
|
|
|
}
|
|
|
|