|
@@ -0,0 +1,187 @@
|
|
|
|
|
+use std::collections::BTreeMap;
|
|
|
|
|
+use std::sync::Arc;
|
|
|
|
|
+use std::sync::atomic::AtomicBool;
|
|
|
|
|
+use rust_decimal::Decimal;
|
|
|
|
|
+use tokio::spawn;
|
|
|
|
|
+use tokio::sync::Mutex;
|
|
|
|
|
+use tracing::{error, info};
|
|
|
|
|
+use exchanges::bitmart_swap_ws::{BitMartSwapLogin, BitMartSwapSubscribeType, BitMartSwapWs, BitMartSwapWsType};
|
|
|
|
|
+use exchanges::response_base::ResponseData;
|
|
|
|
|
+use global::trace_stack::TraceStack;
|
|
|
|
|
+use standard::exchange::ExchangeEnum::{BitmartSwap};
|
|
|
|
|
+use standard::{Position, PositionModeEnum};
|
|
|
|
|
+use crate::core::Core;
|
|
|
|
|
+use crate::exchange_disguise::on_special_depth;
|
|
|
|
|
+use crate::model::OrderInfo;
|
|
|
|
|
+
|
|
|
|
|
+pub async fn bitmart_usdt_swap_run(is_shutdown_arc :Arc<AtomicBool>,
|
|
|
|
|
+ is_trade: bool,
|
|
|
|
|
+ core_arc: Arc<Mutex<Core>>,
|
|
|
|
|
+ name: String,
|
|
|
|
|
+ symbols: Vec<String>,
|
|
|
|
|
+ _is_colo: bool,
|
|
|
|
|
+ exchange_params: BTreeMap<String, String>) {
|
|
|
|
|
+ // 开启公共频道
|
|
|
|
|
+ let (write_tx_public, write_rx_public) = futures_channel::mpsc::unbounded();
|
|
|
|
|
+
|
|
|
|
|
+ // 开启公共连接
|
|
|
|
|
+ let is_shutdown_arc_c1 = is_shutdown_arc.clone();
|
|
|
|
|
+ let write_tx_am_public = Arc::new(Mutex::new(write_tx_public));
|
|
|
|
|
+ let name_clone = name.clone();
|
|
|
|
|
+ let core_arc_clone = core_arc.clone();
|
|
|
|
|
+ let symbols_clone = symbols.clone();
|
|
|
|
|
+ spawn(async move {
|
|
|
|
|
+ // 构建链接ws
|
|
|
|
|
+ let mut bg_public = BitMartSwapWs::new_label(name_clone.clone(),
|
|
|
|
|
+ None,
|
|
|
|
|
+ BitMartSwapWsType::Public);
|
|
|
|
|
+
|
|
|
|
|
+ // 消费数据的函数
|
|
|
|
|
+ let mut update_flag_u = Decimal::ZERO;
|
|
|
|
|
+ let fun = move |data: ResponseData| {
|
|
|
|
|
+ let core_arc_cc = core_arc_clone.clone();
|
|
|
|
|
+
|
|
|
|
|
+ async move {
|
|
|
|
|
+ on_public_data(core_arc_cc, &mut update_flag_u, data).await
|
|
|
|
|
+ }
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ // 准备链接
|
|
|
|
|
+ bg_public.set_subscribe(vec![BitMartSwapSubscribeType::PuFuturesTicker]); // 只用订阅ticker数据
|
|
|
|
|
+ bg_public.set_symbols(symbols_clone);
|
|
|
|
|
+ bg_public.ws_connect_async(is_shutdown_arc_c1, fun, &write_tx_am_public, write_rx_public).await.expect("bitmart_usdt_swap 链接有异常")
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // 不需要交易就不用开启私有频道了
|
|
|
|
|
+ if !is_trade {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 开启私有频道
|
|
|
|
|
+ let (write_tx_private, write_rx_private) = futures_channel::mpsc::unbounded();
|
|
|
|
|
+
|
|
|
|
|
+ // 开启公共连接
|
|
|
|
|
+ let is_shutdown_arc_c1 = is_shutdown_arc.clone();
|
|
|
|
|
+ let write_tx_am_private = Arc::new(Mutex::new(write_tx_private));
|
|
|
|
|
+ spawn(async move {
|
|
|
|
|
+ // 构建链接ws
|
|
|
|
|
+ let mut bg_private = BitMartSwapWs::new_label(name.clone(),
|
|
|
|
|
+ Some(parse_btree_map_to_bitmart_swap_login(exchange_params)),
|
|
|
|
|
+ BitMartSwapWsType::Private);
|
|
|
|
|
+
|
|
|
|
|
+ // 消费数据的函数
|
|
|
|
|
+ let core_arc_clone = core_arc.clone();
|
|
|
|
|
+ let run_symbol = symbols[0].clone();
|
|
|
|
|
+ let ct_val = core_arc_clone.lock().await.platform_rest.get_self_market().ct_val;
|
|
|
|
|
+ let fun = move |data: ResponseData| {
|
|
|
|
|
+ let core_arc_cc = core_arc_clone.clone();
|
|
|
|
|
+ let run_symbol_c = run_symbol.clone();
|
|
|
|
|
+
|
|
|
|
|
+ async move {
|
|
|
|
|
+ on_private_data(core_arc_cc, ct_val, data, &run_symbol_c).await
|
|
|
|
|
+ }
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ // 准备链接
|
|
|
|
|
+ bg_private.set_subscribe(vec![
|
|
|
|
|
+ BitMartSwapSubscribeType::PrFuturesOrders,
|
|
|
|
|
+ BitMartSwapSubscribeType::PrFuturesBalances,
|
|
|
|
|
+ BitMartSwapSubscribeType::PrFuturesPositions
|
|
|
|
|
+ ]);
|
|
|
|
|
+ bg_private.set_symbols(symbols.clone());
|
|
|
|
|
+ bg_private.ws_connect_async(is_shutdown_arc_c1, fun, &write_tx_am_private, write_rx_private).await.expect("bitmart_usdt_swap 链接有异常")
|
|
|
|
|
+ });
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+async fn on_private_data(core_arc_clone: Arc<Mutex<Core>>,
|
|
|
|
|
+ ct_val: Decimal,
|
|
|
|
|
+ response: ResponseData,
|
|
|
|
|
+ run_symbol: &String) {
|
|
|
|
|
+ let mut trace_stack = TraceStack::new(response.time, response.ins);
|
|
|
|
|
+ trace_stack.on_after_span_line();
|
|
|
|
|
+
|
|
|
|
|
+ // public类型,目前只考虑订单流数据
|
|
|
|
|
+ match response.channel.as_str() {
|
|
|
|
|
+ "account" => {
|
|
|
|
|
+ let account = standard::handle_info::HandleSwapInfo::handle_account_info(BitmartSwap, &response, run_symbol);
|
|
|
|
|
+ let mut core = core_arc_clone.lock().await;
|
|
|
|
|
+ core.update_equity(account).await;
|
|
|
|
|
+ },
|
|
|
|
|
+ "positions" => {
|
|
|
|
|
+ let mut positions = standard::handle_info::HandleSwapInfo::handle_position(BitmartSwap, &response, &ct_val);
|
|
|
|
|
+
|
|
|
|
|
+ // bitmart如果没有仓位不会给0,会给个空数组
|
|
|
|
|
+ if positions.is_empty() {
|
|
|
|
|
+ positions.push(Position {
|
|
|
|
|
+ symbol: run_symbol.replace("_", "").to_uppercase(),
|
|
|
|
|
+ margin_level: Default::default(),
|
|
|
|
|
+ amount: Default::default(),
|
|
|
|
|
+ frozen_amount: Default::default(),
|
|
|
|
|
+ price: Default::default(),
|
|
|
|
|
+ profit: Default::default(),
|
|
|
|
|
+ position_mode: PositionModeEnum::Both,
|
|
|
|
|
+ margin: Default::default(),
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ let mut core = core_arc_clone.lock().await;
|
|
|
|
|
+ core.update_position(positions).await;
|
|
|
|
|
+ },
|
|
|
|
|
+ "orders" => {
|
|
|
|
|
+ trace_stack.set_source("gate_swap.orders".to_string());
|
|
|
|
|
+ let orders = standard::handle_info::HandleSwapInfo::handle_order(BitmartSwap, response.clone(), ct_val.clone());
|
|
|
|
|
+
|
|
|
|
|
+ let mut order_infos:Vec<OrderInfo> = Vec::new();
|
|
|
|
|
+ for mut order in orders.order {
|
|
|
|
|
+ if order.status == "NULL" {
|
|
|
|
|
+ error!("bitmart_usdt_swap 未识别的订单状态:{:?}", response);
|
|
|
|
|
+
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ let order_info = OrderInfo::parse_order_to_order_info(&mut order);
|
|
|
|
|
+ order_infos.push(order_info);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ {
|
|
|
|
|
+ let mut core = core_arc_clone.lock().await;
|
|
|
|
|
+ core.update_order(order_infos, trace_stack).await;
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ "pong" => {}
|
|
|
|
|
+ _ => {
|
|
|
|
|
+ info!("bitmart_usdt_swap 113 未知的订阅数据: {:?}", response);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+async fn on_public_data(core_arc_clone: Arc<Mutex<Core>>,
|
|
|
|
|
+ update_flag_u: &mut Decimal,
|
|
|
|
|
+ response: ResponseData) {
|
|
|
|
|
+ let mut trace_stack = TraceStack::new(response.time, response.ins);
|
|
|
|
|
+ trace_stack.on_after_span_line();
|
|
|
|
|
+
|
|
|
|
|
+ // public类型,目前只考虑订单流数据
|
|
|
|
|
+ match response.channel.as_str() {
|
|
|
|
|
+ "books1" => {
|
|
|
|
|
+ trace_stack.set_source("bitmart_usdt_swap.books1".to_string());
|
|
|
|
|
+ let special_depth = standard::handle_info::HandleSwapInfo::handle_special_depth(BitmartSwap, &response);
|
|
|
|
|
+ trace_stack.on_after_format();
|
|
|
|
|
+
|
|
|
|
|
+ on_special_depth(core_arc_clone, update_flag_u, &response.label, &mut trace_stack, &special_depth).await;
|
|
|
|
|
+ },
|
|
|
|
|
+ "pong" => {},
|
|
|
|
|
+ _ => {
|
|
|
|
|
+ info!("bitmart_usdt_swap 125 未知的订阅数据");
|
|
|
|
|
+ info!(?response)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+fn parse_btree_map_to_bitmart_swap_login(exchange_params: BTreeMap<String, String>) -> BitMartSwapLogin {
|
|
|
|
|
+ BitMartSwapLogin {
|
|
|
|
|
+ api_key: exchange_params.get("access_key").unwrap().clone(),
|
|
|
|
|
+ secret: exchange_params.get("secret_key").unwrap().clone(),
|
|
|
|
|
+ api_memo: exchange_params.get("pass_key").unwrap().clone(),
|
|
|
|
|
+ }
|
|
|
|
|
+}
|