gepangpang 1 рік тому
батько
коміт
c2a036aaa1

+ 117 - 0
derive/src/bybit_swap_export.rs

@@ -0,0 +1,117 @@
+use std::collections::BTreeMap;
+use async_trait::async_trait;
+use chrono::{FixedOffset, NaiveDateTime, TimeZone};
+use serde::{Deserialize, Serialize};
+use tracing::warn;
+use exchanges::bybit_swap_rest::BybitSwapRest;
+use standard::utils;
+use crate::ExportConnector;
+
+pub struct BybitSwapExport {
+    request: BybitSwapRest,
+}
+
+impl BybitSwapExport {
+    pub async fn new(is_colo: bool, params: BTreeMap<String, String>) -> BybitSwapExport {
+        BybitSwapExport {
+            request: BybitSwapRest::new(is_colo, params.clone())
+        }
+    }
+}
+
+/// TradesSwap
+/// - `symbol`: String, 合约名称
+/// - `order_type`: String, 订单类型
+/// - `underlying_price`: String, 成交执行时,该 symbol 当时的底层资產价格,仅期权有效
+/// - `order_link_id`: String, 用户自定义订单id. 普通帐户不支持该字段查询
+/// - `side`: String, 订单方向
+/// - `index_price`: String, 成交执行时,该 symbol 当时的指数价格,目前仅对期权业务有效
+/// - `order_id`: String, 订单Id
+/// - `stop_order_type`: String, 条件单的订单类型。
+/// - `leaves_qty`: String, 剩余委托未成交数量
+/// - `exec_time`: String, 成交时间(毫秒)
+/// - `is_maker`: bool, 是否是 Maker 订单, true 为 maker 订单, false 为 taker 订单
+/// - `exec_fee`: String, 交易手续费. 您可以从 这里了解现货手续费币种信息
+/// - `fee_rate`: String, 手续费率. 普通帐户现货交易不支持
+/// - `exec_id`: String, 成交Id
+/// - `trade_iv`: String, 隐含波动率,仅期权有效
+/// - `block_trade_id`: String, 大宗交易时生成的 ID
+/// - `mark_price`: String, 成交执行时,该 symbol 当时的标记价格. 普通帐户现货交易不支持
+/// - `exec_price`: String, 成交价格
+/// - `mark_iv`: String, 标记价格的隐含波动率,仅期权有效
+/// - `order_qty`: String, 订单数量
+/// - `order_price`: String, 订单价格
+/// - `exec_value`: String, 成交价值. 普通帐户现货交易不支持
+/// - `exec_type`: String, 交易类型. 普通帐户现货交易不支持
+/// - `exec_qty`: String, 成交数量
+/// - `closed_size`: String, 平仓数量
+/// - `seq`: i64, 序列号, 用于关联成交和仓位的更新
+#[derive(Debug, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+struct TradesSwap {
+    symbol: String,
+    order_type: String,
+    underlying_price: String,
+    order_link_id: String,
+    side: String,
+    index_price: String,
+    order_id: String,
+    stop_order_type: String,
+    leaves_qty: String,
+    exec_time: String,
+    is_maker: bool,
+    exec_fee: String,
+    fee_rate: String,
+    exec_id: String,
+    trade_iv: String,
+    block_trade_id: String,
+    mark_price: String,
+    exec_price: String,
+    mark_iv: String,
+    order_qty: String,
+    order_price: String,
+    exec_value: String,
+    exec_type: String,
+    exec_qty: String,
+    closed_size: String,
+    seq: i64,
+}
+
+#[async_trait]
+impl ExportConnector for BybitSwapExport {
+    async fn export_trades(&mut self, prefix_name: &str, symbol: String, start_time: i64, end_time: i64, limit: i64) -> String {
+        let symbol_format = utils::format_symbol(symbol.clone(), "");
+        let limit_params = if limit > 100 {
+            warn!("查询条数最大为100条,已修改为100条!");
+            100
+        } else { limit };
+        let res_data = self.request.get_execution_list(symbol_format, "".to_string(), start_time, end_time, limit_params).await;
+        if res_data.code == "200" {
+            let data_json: serde_json::Value = serde_json::from_str(&res_data.data).unwrap();
+            let trades_info: Vec<TradesSwap> = serde_json::from_str(&data_json["list"].to_string()).unwrap();
+            let header_array = vec!["交易编号", "订单编号", "交易币对", "买卖方向", "成交价格", "成交数量", "成交价值", "交易费用", "交易时间"];
+
+            let mut data_array: Vec<Vec<String>> = Vec::new();
+            for (index, value) in trades_info.iter().enumerate() {
+                if index >= data_array.len() {
+                    data_array.push(Vec::new());
+                }
+                let time = FixedOffset::east_opt(8 * 3600).unwrap().from_utc_datetime(&NaiveDateTime::from_timestamp_millis(value.exec_time.parse::<i64>().unwrap()).unwrap()).format("%Y-%m-%d %H:%M:%S%.3f").to_string();
+                data_array[index] = vec![
+                    value.exec_id.clone(),
+                    value.order_id.clone(),
+                    value.symbol.clone(),
+                    value.side.clone(),
+                    value.exec_price.clone(),
+                    value.exec_qty.clone(),
+                    value.exec_value.clone(),
+                    value.exec_fee.clone(),
+                    time,
+                ];
+            }
+            global::export_utils::export_excel(header_array, data_array, prefix_name)
+        } else {
+            res_data.to_string()
+        }
+    }
+}

+ 5 - 0
derive/src/export_excel.rs

@@ -1,6 +1,7 @@
 use std::collections::BTreeMap;
 use crate::binance_swap_export::BinanceSwapExport;
 use crate::bitget_spot_export::BitgetSpotExport;
+use crate::bybit_swap_export::BybitSwapExport;
 use crate::ExportConnector;
 use crate::gate_swap_export::GateSwapExport;
 use crate::kucoin_spot_export::KucoinSpotExport;
@@ -15,6 +16,7 @@ pub enum ExportEnum {
     GateSwap,
     BitgetSpot,
     OkxSwap,
+    BybitSwap
 }
 
 #[derive(Debug, Clone)]
@@ -41,6 +43,9 @@ impl ExportExcel {
             ExportEnum::OkxSwap => {
                 Box::new(OkxSwapExport::new(is_colo, params).await)
             }
+            ExportEnum::BybitSwap => {
+                Box::new( BybitSwapExport::new(is_colo, params).await)
+            }
         }
     }
 }

+ 1 - 0
derive/src/lib.rs

@@ -7,6 +7,7 @@ mod kucoin_spot_export;
 mod gate_swap_export;
 mod bitget_spot_export;
 mod okx_swap_export;
+mod bybit_swap_export;
 
 #[async_trait]
 pub trait ExportConnector {

+ 18 - 0
derive/tests/bybit_swap_export_test.rs

@@ -0,0 +1,18 @@
+mod export_excel_test;
+
+use tracing::{instrument, trace};
+use derive::export_excel::ExportEnum;
+use crate::export_excel_test::test_new_export;
+
+
+const SYMBOL: &str = "";
+// 测试获取Exchange实体
+#[tokio::test]
+#[instrument(level = "TRACE")]
+async fn test_get_self_exchange() {
+    global::log_utils::init_log_with_trace();
+
+    let mut export = test_new_export(ExportEnum::BybitSwap).await;
+    let export_trades = export.export_trades("bybit_swap",SYMBOL.to_string(), 0, 0, 100).await;
+    trace!(?export_trades);
+}

+ 8 - 0
derive/tests/export_excel_test.rs

@@ -73,5 +73,13 @@ pub async fn test_new_export(export_enum: ExportEnum) -> Box<dyn ExportConnector
             params.insert("pass_key".to_string(), pass_key);
             ExportExcel::new(ExportEnum::OkxSwap, false, params).await
         }
+        ExportEnum::BybitSwap => {
+            let mut params: BTreeMap<String, String> = BTreeMap::new();
+            let access_key = account_info.bybit_access_key;
+            let secret_key = account_info.bybit_secret_key;
+            params.insert("access_key".to_string(), access_key);
+            params.insert("secret_key".to_string(), secret_key);
+            ExportExcel::new(ExportEnum::BybitSwap, false, params).await
+        }
     }
 }

+ 23 - 0
exchanges/src/bybit_swap_rest.rs

@@ -165,6 +165,29 @@ impl BybitSwapRest {
         data
     }
 
+    //获取成交记录
+    pub async fn get_execution_list(&mut self,
+                                    symbol: String,
+                                    order_id: String,
+                                    start_at: i64,
+                                    end_at: i64,
+                                    limit: i64, ) -> ResponseData {
+        let mut params = serde_json::json!({
+             "category": "linear",
+             "startTime": start_at,
+             "endTime": end_at,
+             "limit": limit
+         });
+        if symbol != "".to_string() { params["symbol"] = serde_json::json!(symbol); }
+        if order_id != "".to_string() { params["orderId"] = serde_json::json!(order_id); }
+        let data = self.request("GET".to_string(),
+                                "/v5".to_string(),
+                                "/execution/list".to_string(),
+                                true,
+                                params.to_string(),
+        ).await;
+        data
+    }
     //設置槓桿
     pub async fn set_leverage(&mut self, symbol: String,
                               lever: String) -> ResponseData {

+ 4 - 0
global/src/account_info.rs

@@ -19,6 +19,8 @@ pub struct AccountInfo {
     pub bitget_access_key: String,
     pub bitget_secret_key: String,
     pub bitget_pass: String,
+    pub bybit_access_key: String,
+    pub bybit_secret_key: String,
 }
 
 impl AccountInfo {
@@ -37,6 +39,8 @@ impl AccountInfo {
             bitget_access_key: "".to_string(),
             bitget_secret_key: "".to_string(),
             bitget_pass: "".to_string(),
+            bybit_access_key: "".to_string(),
+            bybit_secret_key: "".to_string(),
         }
     }
 }