gepangpang 1 жил өмнө
parent
commit
732775b6c7

+ 7 - 3
src/export_analyze.rs

@@ -6,7 +6,7 @@ use rust_decimal::Decimal;
 use rust_decimal_macros::dec;
 use tracing::{info};
 use crate::export_template;
-use crate::export_ticker::{get_binance_ticker_info, get_gate_ticker_info};
+use crate::export_ticker::{get_binance_ticker_info, get_gate_ticker_info, get_bitget_ticker_info};
 
 #[derive(Debug)]
 pub struct Ticker {
@@ -32,7 +32,7 @@ pub async fn export_analyze(symbol: &str, exchange: &str, range_interval: &str,
     let ticker_info = get_ticker_info(&exchange.to_uppercase(), start_at, end_at, symbol).await;
     let amplitude_map = get_amplitude(ticker_info, range_limit);
 
-    export_template::template_analyze::export_html(&range_interval.interval_text, &symbol.to_uppercase(), amplitude_map.keys().cloned().collect(), amplitude_map.values().cloned().collect())
+    export_template::template_analyze::export_html(&range_interval.interval_text, &symbol.to_uppercase(), amplitude_map.keys().cloned().collect(), amplitude_map.values().cloned().collect(), &exchange.to_uppercase())
 }
 
 pub fn parse_range_interval(range_interval: &str) -> RangeInterval {
@@ -96,8 +96,9 @@ pub fn calc_gate_ticker_amplitude(ticker_map: BTreeMap<u64, Ticker>, limit_range
             }
 
             let prev_ticker = ticker_map.get(&keys[prev_index]).unwrap();
+            let range_time = ticker.create_time - prev_ticker.create_time;
             // 判断该ticker是否是range ms以外
-            if ticker.create_time - prev_ticker.create_time > limit_range {
+            if range_time > limit_range {
                 break;
             }
 
@@ -145,6 +146,9 @@ pub async fn get_ticker_info(exchange: &str, start_at: i64, end_at: i64, symbol:
         "GATE" => {
             trades_list = get_gate_ticker_info(symbol, &start_at.to_string(), &end_at.to_string()).await;
         }
+        "BITGET" => {
+            trades_list = get_bitget_ticker_info(symbol, &start_at.to_string(), &end_at.to_string()).await;
+        }
         _ => {
             panic!("不支持该交易所");
         }

+ 1 - 3
src/export_columnar.rs

@@ -22,7 +22,6 @@ pub async fn export_columnar(config_info: ColumnarConfigInfo) {
     let balance_list = history_balance["balance_list"]["total_balance"].as_array().clone().unwrap();
     let mut time_list = time_slicer.clone();
     let mut over_list = vec![];
-    let mut save_value: Vec<String> = vec![];
     let mut total = dec!(0);
     match config_info.export_mode {
         1 => {
@@ -36,7 +35,6 @@ pub async fn export_columnar(config_info: ColumnarConfigInfo) {
                     over_list.push(new_value.clone());
                     time_list.remove(0);
                 }
-                save_value = item.as_array().unwrap().iter().map(|value| value.as_str().unwrap().to_string()).collect();
                 if index == balance_list.len() - 1 {
                     if time <= time_list[0] {
                         new_value.push(time_list[0].to_string());
@@ -65,7 +63,7 @@ pub async fn export_columnar(config_info: ColumnarConfigInfo) {
                     over_list.push(new_value.clone());
                     time_list.remove(0);
                 }
-                save_value = item.as_array().unwrap().iter().map(|value| value.as_str().unwrap().to_string()).collect();
+                let mut save_value: Vec<String> = item.as_array().unwrap().iter().map(|value| value.as_str().unwrap().to_string()).collect();
                 if index == balance_list.len() - 1 && time <= time_list[0] {
                     new_value.push(time_list[0].to_string());
                     new_value.push((Decimal::from_str(item[4].as_str().unwrap()).unwrap() - total).to_string());

+ 3 - 3
src/export_template/template_analyze.rs

@@ -6,14 +6,14 @@ use tracing::info;
 
 #[allow(dead_code)]
 //生成html
-pub fn export_html(title: &str, symbol: &str, x_values: Vec<Decimal>, y_values: Vec<Decimal>) {
+pub fn export_html(title: &str, symbol: &str, x_values: Vec<Decimal>, y_values: Vec<Decimal>, exchange: &str) {
     info!("正在生成网页,请稍候……");
-    let path = format!("./新版无敌大数据ticker {}.html", symbol);
+    let path = format!("./交易所{} {}.html", exchange, symbol);
     // 创建 Handlebars 实例
     let mut handlebars = Handlebars::new();
 
     let data = serde_json::json!({
-        "chart_title": format!("新版无敌大数据Ticker {}的{}", title, symbol),
+        "chart_title": format!("交易所{} {}的{}",exchange, title, symbol),
         "x_values": x_values,
         "y_values": y_values,
     });

+ 44 - 0
src/export_ticker.rs

@@ -11,6 +11,7 @@ use crate::struct_standard::{AggTrades, Trades};
 use crate::swap_binance::binance_swap_standard;
 use crate::swap_gate::gate_swap_standard;
 use crate::swap_okx::okx_swap_standard;
+use crate::swap_bitget::bitget_swap_standard;
 use crate::utils::utils::TickerConfigInfo;
 
 pub async fn export_ticker(config_info: TickerConfigInfo) {
@@ -74,6 +75,22 @@ pub async fn export_ticker(config_info: TickerConfigInfo) {
                     max_price: max_price.to_string(),
                 }
             }
+            "BITGET" => {
+                let recall_ticker_info = get_bitget_ticker_info(&symbol, &recall_start_at.to_string(), &end_at.to_string()).await;
+                let ticker_info: Vec<Trades> = recall_ticker_info.iter().filter(|item| item.create_time.parse::<i64>().unwrap() >= start_at * 1000).cloned().collect();
+                let mut max_price = Decimal::ZERO;
+                for trades in ticker_info.clone() {
+                    let trades_price = Decimal::from_str(&trades.price).unwrap();
+                    max_price = if trades_price > max_price { trades_price } else { max_price };
+                };
+                let start_index = recall_ticker_info.len().saturating_sub(ticker_info.len()).saturating_sub(config_clone.recall_max_count.to_usize().unwrap());
+                ExportExchangeTickerInfo {
+                    name: exchange.to_string(),
+                    ticker_info,
+                    recall_ticker_info: recall_ticker_info[start_index..].to_vec(),
+                    max_price: max_price.to_string(),
+                }
+            }
             _ => {
                 error!("交易所输入错误!");
                 panic!("交易所输入错误!")
@@ -207,6 +224,33 @@ pub async fn get_okx_ticker_info(symbol: &str, start_at: &str, end_at: &str) ->
     }).collect()
 }
 
+pub async fn get_bitget_ticker_info(symbol: &str, start_at: &str, end_at: &str) -> Vec<Trades> {
+    let market_info = bitget_swap_standard::standard_market(symbol).await;
+    let ct_val = market_info.unwrap().ct_val;
+    let end_time = end_at.to_string();
+    info!("正在查询 Bitget {} 信息,请稍候!", symbol);
+    let ticker_info = bitget_swap_standard::standard_trades(symbol, &format!("{}000",start_at), &format!("{}000",end_time), Option::from(ct_val)).await;
+    let  ticker_info_list: Vec<Trades> = ticker_info.unwrap();
+    // loop {
+    //     let ticker_info = bitget_swap_standard::standard_trades(symbol, start_at, &end_time, Option::from(ct_val)).await;
+    //     // match ticker_info {
+    //     //     Ok(value) => {
+    //     //         ticker_info_list.extend(value.clone());
+    //     //         if value.len() >= 1000 {
+    //     //             end_time = Decimal::from_str(&value[0].create_time).unwrap().ceil().to_string();
+    //     //         } else {
+    //     //             break;
+    //     //         }
+    //     //     }
+    //     //     Err(err) => {
+    //     //         error!("{}", err.to_string());
+    //     //     }
+    //     // };
+    // };
+    let mut set = std::collections::HashSet::new();
+    ticker_info_list.into_iter().filter(|trades| trades.is_effect && set.insert(trades.clone())).collect()
+}
+
 pub async fn get_robot_info(symbol: &str, robot_name: &str, start_at: &str, end_at: &str) -> Vec<Trades> {
     let robot_info = robot_data::robot_data_standard::standard_robot_info(&symbol, robot_name, start_at, end_at).await.unwrap();
     robot_info

+ 2 - 1
src/main.rs

@@ -8,6 +8,7 @@ pub mod swap_binance;
 pub mod swap_gate;
 pub mod swap_okx;
 pub mod swap_bybit;
+pub mod swap_bitget;
 pub mod robot_data;
 pub mod utils;
 pub mod http;
@@ -63,7 +64,7 @@ async fn main() {
     }
 
     if config_obj.analyze_info.is_export {
-        info!("----------正在导出Balance信息----------");
+        info!("----------正在导出Analyze信息----------");
         let config_clone = config_obj.analyze_info.clone();
         if http::proxy::ParsingDetail::http_enable_proxy(config_clone.proxy_address.clone()) {
             info!("检测有代理配置,配置走代理");

+ 25 - 0
src/swap_bitget/bitget_swap_rest.rs

@@ -0,0 +1,25 @@
+use crate::http::request::{get, Response};
+
+pub async fn get_trades(symbol: &str, start_at: &str, end_at: &str) -> Response {
+    let url = "http://dc.skyfffire.com:8888/trades";
+    let mut params = serde_json::json!({
+        "exchange":"bitget_usdt_swap",
+        "symbol": symbol
+    });
+    if start_at.len() > 0 {
+        params["start_time"] = serde_json::Value::from(start_at);
+    }
+    if end_at.len() > 0 {
+        params["end_time"] = serde_json::Value::from(end_at);
+    }
+    get(url, params.to_string(), None).await
+}
+
+pub async fn get_market(symbol: &str) -> Response {
+    let url = "https://api.bitget.com/api/v2/mix/market/contracts";
+    let params = serde_json::json!({
+        "symbol":symbol,
+        "productType": "USDT-FUTURES",
+    });
+    get(url, params.to_string(), None).await
+}

+ 82 - 0
src/swap_bitget/bitget_swap_standard.rs

@@ -0,0 +1,82 @@
+use std::fmt::Debug;
+use std::io::{Error, ErrorKind};
+use std::str::FromStr;
+use rust_decimal::Decimal;
+use rust_decimal::prelude::FromPrimitive;
+use rust_decimal_macros::dec;
+use serde::{Deserialize, Serialize};
+use crate::swap_bitget::bitget_swap_rest::{get_market, get_trades};
+use crate::struct_standard::{Market, Trades};
+use crate::utils::utils::format_symbol;
+
+#[derive(Debug, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+struct BitGetResponse {
+    code: String,
+    msg: String,
+    request_time: String,
+    data: String,
+}
+
+pub(crate) async fn standard_trades(symbol: &str, start_at: &str, end_at: &str, ct_val: Option<Decimal>) -> Result<Vec<Trades>, Error> {
+    let symbol_fmt = format_symbol(symbol, "_");
+    let res_data = get_trades(&symbol_fmt, start_at, end_at).await;
+    if res_data.code == "200" {
+        let res_data_data: serde_json::Value = serde_json::from_str(&res_data.data).unwrap();
+        let mut trades_list = res_data_data["data"].as_array().unwrap_or(&vec![]).clone();
+        trades_list.sort_by(|a, b| (Decimal::from_str(a[0].as_str().unwrap()).unwrap()).cmp(&Decimal::from_str(b[0].as_str().unwrap()).unwrap()));
+        let result = trades_list.iter().map(|item| {
+            Trades {
+                id: item[0].as_str().unwrap().to_string(),
+                data_type: "ticker_bybit".to_string(),
+                symbol: symbol.to_uppercase().to_string(),
+                create_time: item[1].as_str().unwrap().to_string(),
+                size: (Decimal::from_str(item[2].as_str().unwrap()).unwrap() * ct_val.unwrap_or(Decimal::ONE)).to_string(),
+                price: item[3].as_str().unwrap().to_string(),
+                side: if Decimal::from_str(item[3].as_str().unwrap()).unwrap() > dec!(0) { "BUY".to_string() } else { "SELL".to_string() },
+                is_effect: true,
+            }
+        }).collect();
+        Ok(result)
+    } else {
+        Err(Error::new(ErrorKind::Other, res_data.to_string()))
+    }
+}
+
+#[derive(Debug, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+struct SwapMarket {
+    symbol: String,
+    base_coin: String,
+    quote_coin: String,
+    price_place: Decimal,
+    volume_place: Decimal,
+}
+
+pub(crate) async fn standard_market(symbol: &str) -> Result<Market, Error> {
+    let symbol_fmt = format_symbol(symbol, "");
+    let res_data = get_market(&symbol_fmt).await;
+    if res_data.code == "200" {
+        let res_data_data: serde_json::Value = serde_json::from_str(&res_data.data).unwrap();
+        let market_list: Vec<SwapMarket> = serde_json::from_str(&res_data_data["data"].to_string()).unwrap();
+        let market = market_list.iter().find(|item| item.symbol == symbol_fmt).unwrap();
+
+        let result = Market {
+            symbol: market.symbol.clone(),
+            base_asset: market.base_coin.clone(),
+            quote_asset: market.quote_coin.clone(),
+            tick_size: market.price_place,
+            amount_size: market.volume_place,
+            price_precision: Decimal::from_u32(market.price_place.scale()).unwrap(),
+            amount_precision: Decimal::from_u32(market.volume_place.scale()).unwrap(),
+            min_qty: Decimal::NEGATIVE_ONE,
+            max_qty: Decimal::NEGATIVE_ONE,
+            min_notional: Decimal::NEGATIVE_ONE,
+            max_notional: Decimal::NEGATIVE_ONE,
+            ct_val: Decimal::ONE,
+        };
+        Ok(result)
+    } else {
+        Err(Error::new(ErrorKind::Other, res_data.to_string()))
+    }
+}

+ 2 - 0
src/swap_bitget/mod.rs

@@ -0,0 +1,2 @@
+pub mod bitget_swap_rest;
+pub mod bitget_swap_standard;