|
|
@@ -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()
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|