Explorar el Código

增加交易量统计接口

JiahengHe hace 8 meses
padre
commit
7ebb1b6ea6

+ 5 - 2
derive/src/gate_swap_export.rs

@@ -6,7 +6,7 @@ use rust_decimal::Decimal;
 use rust_decimal::prelude::{FromPrimitive, ToPrimitive};
 use rust_decimal_macros::dec;
 use serde::{Deserialize, Serialize};
-use tracing::{warn};
+use tracing::{info, warn};
 use exchanges::gate_swap_rest::GateSwapRest;
 use standard::utils;
 use crate::ExportConnector;
@@ -63,6 +63,10 @@ impl ExportConnector for GateSwapExport {
             let res_data = self.request.my_trades("usdt".to_string(), symbol_format.clone(), 1000, last_id.clone()).await;
             if res_data.code == 200 {
                 let trades_info: Vec<TradesSwap> = serde_json::from_str(&res_data.data.to_string()).unwrap();
+                if trades_info.len() == 0 {
+                    break;
+                }
+                let last_time = (trades_info.last().unwrap().create_time * 1000.0).to_i64().unwrap();
                 for value in trades_info.iter() {
                     last_id = value.id.to_string();
                     let size = Decimal::from_i64(value.size).unwrap();
@@ -71,7 +75,6 @@ impl ExportConnector for GateSwapExport {
                     let created_at = FixedOffset::east_opt(8 * 3600).unwrap().from_utc_datetime(&NaiveDateTime::from_timestamp_millis(created_time.to_i64().unwrap()).unwrap()).format("%Y-%m-%d %H:%M:%S%.3f").to_string();
                     let trade_value = Decimal::from_str(&value.price).unwrap() * size.abs();
                     data_array.push(vec![
-                        value.id.to_string(),
                         value.order_id.clone(),
                         value.contract.clone(),
                         side.to_string(),

+ 5 - 0
standard/src/binance_swap.rs

@@ -170,6 +170,11 @@ impl Platform for BinanceSwap {
         }
     }
 
+    async fn get_trade_amount(&mut self, _start_time: i64, _end_time: i64) -> Result<Decimal, Error> {
+        Ok(Decimal::ZERO)
+    }
+
+
     // 获取市场行情
     async fn get_ticker(&mut self) -> Result<Ticker, Error> {
         let symbol_format = utils::format_symbol(self.symbol.clone(), "");

+ 4 - 0
standard/src/bitget_swap.rs

@@ -292,6 +292,10 @@ impl Platform for BitgetSwap {
         Ok(positions)
     }
 
+    async fn get_trade_amount(&mut self, _start_time: i64, _end_time: i64) -> Result<Decimal, Error> {
+        Ok(Decimal::ZERO)
+    }
+
     async fn get_ticker(&mut self) -> Result<Ticker, Error> {
         return self.get_ticker_symbol(self.symbol.clone()).await;
     }

+ 5 - 0
standard/src/bybit_swap.rs

@@ -180,6 +180,11 @@ impl Platform for BybitSwap {
             Err(Error::new(ErrorKind::Other, res_data.to_string()))
         }
     }
+
+    async fn get_trade_amount(&mut self, _start_time: i64, _end_time: i64) -> Result<Decimal, Error> {
+        Ok(Decimal::ZERO)
+    }
+
     // 获取市场行情
     async fn get_ticker(&mut self) -> Result<Ticker, Error> {
         let symbol = self.symbol_uppercase.clone();

+ 69 - 1
standard/src/coinex_swap.rs

@@ -3,14 +3,16 @@ use std::io::{Error, ErrorKind};
 use std::str::FromStr;
 use tokio::sync::mpsc::Sender;
 use async_trait::async_trait;
+use chrono::{FixedOffset, NaiveDateTime};
 use futures::stream::FuturesUnordered;
 use futures::TryStreamExt;
 use rust_decimal::Decimal;
 use rust_decimal::prelude::{FromPrimitive, ToPrimitive};
+use serde::{Deserialize, Serialize};
 use serde_json::{Value};
 use tokio::spawn;
 use tokio::time::Instant;
-use tracing::{error, info, trace};
+use tracing::{error, info, trace, warn};
 use exchanges::coinex_swap_rest::CoinexSwapRest;
 use crate::{Platform, ExchangeEnum, Account, Position, Ticker, Market, Order, OrderCommand, PositionModeEnum, utils, Record};
 use global::trace_stack::TraceStack;
@@ -29,6 +31,39 @@ pub struct CoinexSwap {
     error_sender: Sender<Error>,
 }
 
+/// TradesSwap
+/// - `id`: i64, 成交记录 ID
+/// - `create_time`: i64, 成交时间
+/// - `contract`: String, 合约标识
+/// - `order_id`: String, 成交记录关联订单 ID
+/// - `size`: i64, 成交数量
+/// - `price`: String, 成交价格
+/// - `text`: String, 成交角色, taker - 吃单, maker - 做单
+/// - `fee`: String, 订单的自定义信息
+/// - `point_fee`: String, 成交手续费
+/// - `role`: String, 成交点卡手续费
+#[derive(Debug, Clone, Deserialize, Serialize)]
+struct TradesSwap {
+    order_id: i64,
+    market: String,
+    market_type: String,
+    side: String,
+    #[serde(rename = "type")]
+    trade_type: String,
+    amount: String,
+    price: String,
+    unfilled_amount: String,
+    filled_amount: String,
+    filled_value: String,
+    client_id: String,
+    fee: String,
+    fee_ccy: String,
+    maker_fee_rate: String,
+    taker_fee_rate: String,
+    created_at: i64,
+    updated_at: i64,
+}
+
 impl CoinexSwap {
     pub async fn new(symbol: String, is_colo: bool, params: BTreeMap<String, String>, order_sender: Sender<Order>, error_sender: Sender<Error>) -> CoinexSwap {
         let market = Market::new();
@@ -168,6 +203,39 @@ impl Platform for CoinexSwap {
             Err(Error::new(ErrorKind::Other, res_data.to_string()))
         }
     }
+
+    async fn get_trade_amount(&mut self, start_time: i64, end_time: i64) -> Result<Decimal, Error> {
+        let mut data_array = vec![];
+        let mut page = 1;
+        loop {
+            let res_data = self.request.finished_order("".to_string(), page, 1000).await;
+            if res_data.code == 200 {
+                let trades_info: Vec<TradesSwap> = serde_json::from_str(&res_data.data.to_string()).unwrap();
+                if trades_info.is_empty(){
+                    break;
+                }
+                let last_time = (trades_info.last().unwrap().created_at).to_i64().unwrap();
+                data_array.extend(trades_info);
+
+                if last_time < start_time || last_time > end_time {
+                    data_array = data_array.iter().filter(|item| {
+                        let now_time = item.created_at;
+                        now_time > start_time && now_time < end_time
+                    }).cloned().collect();
+                    break;
+                } else {
+                    page = page + 1;
+                }
+            }
+        }
+        let mut amount = Decimal::ZERO;
+        for item in data_array.iter() {
+            let filled_value = Decimal::from_str(&item.filled_value).unwrap_or(Decimal::ZERO);
+            amount = filled_value + amount;
+        }
+        Ok(Decimal::ZERO)
+    }
+
     // 获取市场行情
     async fn get_ticker(&mut self) -> Result<Ticker, Error> {
         let symbol: String = self.symbol.replace("_", "");

+ 63 - 2
standard/src/gate_swap.rs

@@ -3,15 +3,18 @@ use std::io::{Error, ErrorKind};
 use std::str::FromStr;
 use tokio::sync::mpsc::Sender;
 use async_trait::async_trait;
+use chrono::{FixedOffset, NaiveDateTime};
 use futures::stream::FuturesUnordered;
 use futures::TryStreamExt;
 use rust_decimal::Decimal;
 use rust_decimal::prelude::{FromPrimitive, ToPrimitive};
+use rust_decimal_macros::dec;
+use serde::{Deserialize, Serialize};
 use serde_json::{json, Value};
 use tokio::spawn;
 use tokio::time::Instant;
-use tracing::{error, info};
-use crate::{Platform, ExchangeEnum, Account, Position, Ticker, Market, Order, OrderCommand, PositionModeEnum, Record};
+use tracing::{error, info, warn};
+use crate::{Platform, ExchangeEnum, Account, Position, Ticker, Market, Order, OrderCommand, PositionModeEnum, Record, utils};
 use exchanges::gate_swap_rest::GateSwapRest;
 use global::trace_stack::TraceStack;
 
@@ -28,6 +31,31 @@ pub struct GateSwap {
     error_sender: Sender<Error>,
 }
 
+/// TradesSwap
+/// - `id`: i64, 成交记录 ID
+/// - `create_time`: i64, 成交时间
+/// - `contract`: String, 合约标识
+/// - `order_id`: String, 成交记录关联订单 ID
+/// - `size`: i64, 成交数量
+/// - `price`: String, 成交价格
+/// - `text`: String, 成交角色, taker - 吃单, maker - 做单
+/// - `fee`: String, 订单的自定义信息
+/// - `point_fee`: String, 成交手续费
+/// - `role`: String, 成交点卡手续费
+#[derive(Debug, Clone, Deserialize, Serialize)]
+struct TradesSwap {
+    id: i64,
+    create_time: f64,
+    contract: String,
+    order_id: String,
+    size: i64,
+    price: String,
+    text: String,
+    fee: String,
+    point_fee: String,
+    role: String,
+}
+
 impl GateSwap {
     pub async fn new(symbol: String, is_colo: bool, params: BTreeMap<String, String>, order_sender: Sender<Order>, error_sender: Sender<Error>) -> GateSwap {
         let market = Market::new();
@@ -151,6 +179,39 @@ impl Platform for GateSwap {
             Err(Error::new(ErrorKind::Other, res_data.to_string()))
         }
     }
+
+    async fn get_trade_amount(&mut self, start_time: i64, end_time: i64) -> Result<Decimal, Error> {
+        let mut data_array = vec![];
+        let mut last_id = "".to_string();
+        loop {
+            let res_data = self.request.my_trades("usdt".to_string(), "".to_string(), 1000, last_id.clone()).await;
+            if res_data.code == 200 {
+                let trades_info: Vec<TradesSwap> = serde_json::from_str(&res_data.data.to_string()).unwrap();
+                if trades_info.len() == 0 {
+                    break;
+                }
+                let last_time = (trades_info.last().unwrap().create_time * 1000.0).to_i64().unwrap();
+                last_id = trades_info.last().unwrap().id.to_string();
+                // 写入存储数组中
+                data_array.extend(trades_info);
+                // 当最后一个时间戳小于开始时间或者大于结束时间,则跳出循环
+                if last_time < start_time || last_time > end_time {
+                    data_array = data_array.iter().filter(|item| {
+                        (item.create_time*1000.0).to_i64().unwrap_or(0) > start_time
+                    }).cloned().collect();
+                    break;
+                }
+            }
+        }
+        let mut amount = Decimal::ZERO;
+        for item in data_array.iter() {
+            let filled_price = Decimal::from_str(&item.price).unwrap_or(Decimal::ZERO);
+            let filled_size = Decimal::from_i64(item.size.abs()).unwrap_or(Decimal::ZERO);
+            amount = filled_size * filled_price + amount;
+        }
+        Ok(amount)
+    }
+
     // 获取市场行情
     async fn get_ticker(&mut self) -> Result<Ticker, Error> {
         let symbol_array: Vec<&str> = self.symbol.split("_").collect();

+ 3 - 1
standard/src/lib.rs

@@ -1,5 +1,5 @@
 use std::collections::{BTreeMap, HashMap};
-use std::fmt;
+use std::{fmt, vec};
 use std::fmt::Formatter;
 use std::io::{Error};
 use async_trait::async_trait;
@@ -637,6 +637,8 @@ pub trait Platform {
     async fn get_position(&mut self) -> Result<Vec<Position>, Error>;
     // 获取所有持仓
     async fn get_positions(&mut self) -> Result<Vec<Position>, Error>;
+    // 获取交易量
+    async fn get_trade_amount(&mut self, start_time: i64, end_time: i64) -> Result<Decimal, Error>;
     // 获取市场行情
     async fn get_ticker(&mut self) -> Result<Ticker, Error>;
     // 获取市场行情