skyffire 1 жил өмнө
parent
commit
a47bec172d

+ 24 - 19
src/export_analyze.rs

@@ -1,4 +1,5 @@
-use std::cmp::{max};
+use crate::export_ticker::{get_binance_ticker_info, get_bitget_ticker_info, get_gate_ticker_info};
+use std::cmp::max;
 use std::collections::{BTreeMap};
 use std::str::FromStr;
 use chrono::{Utc};
@@ -6,9 +7,8 @@ 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, get_bitget_ticker_info};
 
-#[derive(Debug)]
+#[derive(Debug, Clone, Copy)]
 pub struct Ticker {
     pub create_time: Decimal,
     pub price: Decimal,
@@ -69,15 +69,12 @@ pub fn parse_range_interval(range_interval: &str) -> RangeInterval {
 }
 
 // 计算最近range毫秒的的波动
-pub fn calc_gate_ticker_amplitude(ticker_map: BTreeMap<u64, Ticker>, limit_range: Decimal) -> BTreeMap<Decimal, Decimal> {
+pub fn calc_gate_ticker_amplitude(tickers: Vec<Ticker>, limit_range: Decimal) -> BTreeMap<Decimal, Decimal> {
     let mut amplitude_map: BTreeMap<Decimal, Decimal> = BTreeMap::new();
 
     // 每一个元素都遍历一遍
     info!("精确幅度计算执行中……");
-    let keys: Vec<u64> = ticker_map.keys().cloned().collect();
-    for (index, create_time) in keys.iter().enumerate() {
-        let ticker = ticker_map.get(&create_time).unwrap();
-
+    for (index, ticker) in tickers.iter().enumerate() {
         // 该元素向前遍历range毫秒
         let mut prev_index = if index == 0 {
             0
@@ -95,7 +92,7 @@ pub fn calc_gate_ticker_amplitude(ticker_map: BTreeMap<u64, Ticker>, limit_range
                 break;
             }
 
-            let prev_ticker = ticker_map.get(&keys[prev_index]).unwrap();
+            let prev_ticker = tickers.get(prev_index).unwrap();
             let range_time = ticker.create_time - prev_ticker.create_time;
             // 判断该ticker是否是range ms以外
             if range_time > limit_range {
@@ -128,7 +125,15 @@ pub fn calc_gate_ticker_amplitude(ticker_map: BTreeMap<u64, Ticker>, limit_range
             // 去除小数位之后,可以忽略一些太小的波动,减少图表生成压力
             if up_rate > Decimal::ZERO || dn_rate > Decimal::ZERO {
                 // info!("up={}, dn={}, ra={}", up_rate, dn_rate, max(up_rate, dn_rate));
-                amplitude_map.insert(ticker.create_time, max(up_rate, dn_rate));
+                let insert_value = if amplitude_map.contains_key(&ticker.create_time) {
+                    let origin_rate = amplitude_map.get(&ticker.create_time).unwrap();
+
+                    max(*origin_rate, max(up_rate, dn_rate))
+                } else {
+                    max(up_rate, dn_rate)
+                };
+
+                amplitude_map.insert(ticker.create_time, insert_value);
             }
         }
     }
@@ -136,8 +141,7 @@ pub fn calc_gate_ticker_amplitude(ticker_map: BTreeMap<u64, Ticker>, limit_range
     return amplitude_map;
 }
 
-pub async fn get_ticker_info(exchange: &str, start_at: i64, end_at: i64, symbol: &str) -> BTreeMap<u64, Ticker> {
-    let mut ticker_map: BTreeMap<u64, Ticker> = BTreeMap::new();
+pub async fn get_ticker_info(exchange: &str, start_at: i64, end_at: i64, symbol: &str) -> Vec<Ticker> {
     let trades_list;
     match exchange {
         "BINANCE" => {
@@ -153,23 +157,24 @@ pub async fn get_ticker_info(exchange: &str, start_at: i64, end_at: i64, symbol:
             panic!("不支持该交易所");
         }
     }
+    let mut ticker_list: Vec<Ticker> = vec![];
     for trades in trades_list {
-        let key = trades.create_time.parse::<u64>().unwrap();
+        // let key = trades.create_time.parse::<u64>().unwrap();
         let ticker = Ticker {
             create_time: Decimal::from_str(&trades.create_time).unwrap(),
             price: Decimal::from_str(&trades.price).unwrap(),
             amount: Decimal::from_str(&trades.size).unwrap(),
         };
-        ticker_map.insert(key, ticker);
+        ticker_list.push(ticker.clone());
     }
-    let len = ticker_map.len();
-    info!("网络层执行完毕,总数据量条数:{}。", len);
-    return ticker_map;
+
+    info!("网络层执行完毕,数据条数: {}。", ticker_list.len());
+    return ticker_list;
 }
 
-pub fn get_amplitude(ticker_map: BTreeMap<u64, Ticker>, range_limit: Decimal) -> BTreeMap<Decimal, Decimal> {
+pub fn get_amplitude(trades: Vec<Ticker>, range_limit: Decimal) -> BTreeMap<Decimal, Decimal> {
     // 逻辑层执行
-    let amplitude_map = calc_gate_ticker_amplitude(ticker_map, range_limit);
+    let amplitude_map = calc_gate_ticker_amplitude(trades, range_limit);
     let amplitude_map_len = amplitude_map.len();
     info!("逻辑层执行完毕,剩余有效波动条数:{}。", amplitude_map_len);
 

+ 1 - 1
src/export_template/template_analyze.rs

@@ -8,7 +8,7 @@ use tracing::info;
 //生成html
 pub fn export_html(title: &str, symbol: &str, x_values: Vec<Decimal>, y_values: Vec<Decimal>, exchange: &str) {
     info!("正在生成网页,请稍候……");
-    let path = format!("./交易所{} {}.html", exchange, symbol);
+    let path = format!("./交易所{}.html", exchange);
     // 创建 Handlebars 实例
     let mut handlebars = Handlebars::new();
 

+ 19 - 18
src/export_ticker.rs

@@ -109,25 +109,26 @@ pub async fn export_ticker(config_info: TickerConfigInfo) {
 pub async fn get_gate_ticker_info(symbol: &str, start_at: &str, end_at: &str) -> Vec<Trades> {
     let market_info = gate_swap_standard::standard_market(symbol).await;
     let ct_val = market_info.unwrap().ct_val;
-    let mut end_time = end_at.to_string();
-    let mut ticker_info_list: Vec<Trades> = vec![];
+    let end_time = end_at.to_string();
     info!("正在查询 Gate {} 信息,请稍候!", symbol);
-    loop {
-        let ticker_info = gate_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() / dec!(1000)).ceil().to_string();
-                } else {
-                    break;
-                }
-            }
-            Err(err) => {
-                error!("{}", err.to_string());
-            }
-        };
-    };
+    let ticker_info = gate_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()
 }

+ 21 - 6
src/swap_gate/gate_swap_rest.rs

@@ -1,13 +1,28 @@
 use crate::http::request::{get, Response};
 
+// pub async fn get_trades(symbol: &str, start_at: &str, end_at: &str) -> Response {
+//     let url = "https://api.gateio.ws/api/v4/futures/usdt/trades";
+//     let params = serde_json::json!({
+//         "contract": symbol,
+//         "from": start_at,
+//         "to": end_at,
+//         "limit": "1000"
+//     });
+//     get(url, params.to_string(), None).await
+// }
+
 pub async fn get_trades(symbol: &str, start_at: &str, end_at: &str) -> Response {
-    let url = "https://api.gateio.ws/api/v4/futures/usdt/trades";
-    let params = serde_json::json!({
-        "contract": symbol,
-        "from": start_at,
-        "to": end_at,
-        "limit": "1000"
+    let url = "http://dc.skyfffire.com:8888/trades";
+    let mut params = serde_json::json!({
+        "exchange":"gate_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
 }
 

+ 38 - 11
src/swap_gate/gate_swap_standard.rs

@@ -1,7 +1,9 @@
 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_gate::gate_swap_rest::{get_market, get_trades};
 use crate::struct_standard::{Market, Trades};
@@ -18,23 +20,48 @@ struct SwapTrades {
     is_internal: Option<bool>,
 }
 
+// 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_str = res_data.data;
+//         let mut trades_list: Vec<SwapTrades> = serde_json::from_str(&res_data_str).unwrap();
+//         trades_list.sort_by(|a, b| (a.id).cmp(&b.id));
+//         let result = trades_list.iter().map(|item| {
+//             Trades {
+//                 id: item.id.to_string(),
+//                 data_type: "ticker_gate".to_string(),
+//                 symbol: item.contract.clone(),
+//                 create_time: (item.create_time_ms * 1000.0).to_string(),
+//                 size: (item.size * ct_val.unwrap_or(Decimal::ONE)).to_string(),
+//                 price: item.price.clone(),
+//                 side: if item.size > Decimal::ZERO { "BUY".to_string() } else { "SELL".to_string() },
+//                 is_effect: if item.is_internal.is_none() { true } else { false },
+//             }
+//         }).collect();
+//         Ok(result)
+//     } else {
+//         Err(Error::new(ErrorKind::Other, res_data.to_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_str = res_data.data;
-        let mut trades_list: Vec<SwapTrades> = serde_json::from_str(&res_data_str).unwrap();
-        trades_list.sort_by(|a, b| (a.id).cmp(&b.id));
+        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.id.to_string(),
-                data_type: "ticker_gate".to_string(),
-                symbol: item.contract.clone(),
-                create_time: (item.create_time_ms * 1000.0).to_string(),
-                size: (item.size * ct_val.unwrap_or(Decimal::ONE)).to_string(),
-                price: item.price.clone(),
-                side: if item.size > Decimal::ZERO { "BUY".to_string() } else { "SELL".to_string() },
-                is_effect: if item.is_internal.is_none() { true } else { false },
+                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)