|
|
@@ -0,0 +1,99 @@
|
|
|
+use std::collections::BTreeMap;
|
|
|
+use async_trait::async_trait;
|
|
|
+use chrono::{FixedOffset, NaiveDateTime, TimeZone};
|
|
|
+use serde::{Deserialize, Serialize};
|
|
|
+use exchanges::kucoin_spot_rest::KucoinSpotRest;
|
|
|
+use standard::exchange::ExchangeEnum;
|
|
|
+use standard::utils;
|
|
|
+use crate::ExportConnector;
|
|
|
+
|
|
|
+pub struct KucoinSpotExport {
|
|
|
+ request: KucoinSpotRest,
|
|
|
+}
|
|
|
+
|
|
|
+impl KucoinSpotExport {
|
|
|
+ pub async fn new(is_colo: bool, params: BTreeMap<String, String>) -> KucoinSpotExport {
|
|
|
+ KucoinSpotExport {
|
|
|
+ request: KucoinSpotRest::new(is_colo, params.clone())
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/// TradesSwap
|
|
|
+/// - `symbol`: String, 合約編號
|
|
|
+/// - `trade_id`: String, 交易編號
|
|
|
+/// - `order_id`: String, 訂單編號
|
|
|
+/// - `counter_order_id`: String, 對手方訂單Id
|
|
|
+/// - `side`: String, 買賣方向
|
|
|
+/// - `liquidity`: String,流動性類型 taker or maker
|
|
|
+/// - `force_taker`: bool, 是否強製作爲taker處理
|
|
|
+/// - `price`: String, 成交價格
|
|
|
+/// - `size`: i64, 成交數量
|
|
|
+/// - `funds`: String, 成交額
|
|
|
+/// - `fee`: String, 交易費用
|
|
|
+/// - `fee_currency`: String, 收費幣種
|
|
|
+/// - `stop`: String, 止損單類型標記
|
|
|
+/// - `fee_rate`: String, 費率
|
|
|
+/// - `order_type`: String, 訂單類型
|
|
|
+/// - `created_at`: i64, 創建時間
|
|
|
+/// - `trade_type`: String, 交易類型: trade, liquidation, ADL or settlement
|
|
|
+#[derive(Debug, Deserialize, Serialize)]
|
|
|
+#[serde(rename_all = "camelCase")]
|
|
|
+struct TradesSpot {
|
|
|
+ symbol: String,
|
|
|
+ trade_id: String,
|
|
|
+ order_id: String,
|
|
|
+ counter_order_id: String,
|
|
|
+ side: String,
|
|
|
+ liquidity: String,
|
|
|
+ force_taker: bool,
|
|
|
+ price: String,
|
|
|
+ size: i64,
|
|
|
+ funds: String,
|
|
|
+ fee: String,
|
|
|
+ fee_rate: String,
|
|
|
+ fee_currency: String,
|
|
|
+ stop: String,
|
|
|
+ #[serde(rename = "type")]
|
|
|
+ order_type: String,
|
|
|
+ created_at: i64,
|
|
|
+ trade_type: String,
|
|
|
+}
|
|
|
+
|
|
|
+#[async_trait]
|
|
|
+impl ExportConnector for KucoinSpotExport {
|
|
|
+ async fn export_trades(&mut self, prefix_name: &str, symbol: String, start_time: i64, end_time: i64, limit: i64) -> String {
|
|
|
+ let symbol_mapper = utils::symbol_enter_mapper(ExchangeEnum::KucoinSwap, symbol.as_str());
|
|
|
+ let symbol_format = format!("{}M", utils::format_symbol(symbol_mapper.clone(), ""));
|
|
|
+ let res_data = self.request.get_fills(symbol_format, "".to_string(), "".to_string(), start_time, end_time, limit).await;
|
|
|
+ if res_data.code == "200" {
|
|
|
+ let res_data_json: serde_json::Value = serde_json::from_str(&res_data.data).unwrap();
|
|
|
+ let trades_info: Vec<TradesSpot> = serde_json::from_str(&res_data_json["items"].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 created_at = FixedOffset::east_opt(8 * 3600).unwrap().from_utc_datetime(&NaiveDateTime::from_timestamp_millis(value.created_at.clone()).unwrap()).format("%Y-%m-%d %T").to_string();
|
|
|
+
|
|
|
+ data_array[index] = vec![
|
|
|
+ value.trade_id.clone(),
|
|
|
+ value.order_id.clone(),
|
|
|
+ value.symbol.clone(),
|
|
|
+ value.side.clone(),
|
|
|
+ value.price.clone(),
|
|
|
+ value.size.to_string(),
|
|
|
+ value.funds.clone(),
|
|
|
+ value.fee.clone(),
|
|
|
+ value.fee_rate.clone(),
|
|
|
+ value.order_type.clone(),
|
|
|
+ created_at,
|
|
|
+ ];
|
|
|
+ }
|
|
|
+ global::export_utils::export_excel(header_array, data_array, prefix_name)
|
|
|
+ } else {
|
|
|
+ res_data.to_string()
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|