Pārlūkot izejas kodu

添加主动性判断

gepangpang 1 gadu atpakaļ
vecāks
revīzija
f455e96a17
1 mainītis faili ar 83 papildinājumiem un 57 dzēšanām
  1. 83 57
      src/export/html.rs

+ 83 - 57
src/export/html.rs

@@ -34,73 +34,99 @@ pub fn export_html(export_info: Vec<ExportExchangeTickerInfo>, start_at: &str, e
     // 创建 Handlebars 实例
     let mut handlebars = Handlebars::new();
 
-    let mut name_list: Vec<String> = vec![];
-    let series_info: Vec<SeriesInfo> = export_info.iter().map(|export_exchange_ticker_info| {
-        name_list.push(format!("'{}'", export_exchange_ticker_info.name));
-        let mut ticker_info = vec![];
-        for trades in export_exchange_ticker_info.ticker_info.clone() {
-            // 赋值原ticker数据
-            ticker_info.push(trades.clone());
 
-            // 计算交易量差
-            let mut volume = Decimal::ONE;
-            let mut short_volume = Decimal::ONE;
-            let mut long_volume = Decimal::ONE;
-            let mut sum_volume = Decimal::ONE;
-            let recall_ticker_info: Vec<Trades> = export_exchange_ticker_info.recall_ticker_info.iter().filter(|recall_trades| {
-                let recall_create_time = Decimal::from_str(&recall_trades.create_time).unwrap();
-                let create_time = Decimal::from_str(&trades.create_time).unwrap();
-                let recall_time = Decimal::from_i64(config.recall_time).unwrap();
-                recall_create_time <= create_time && create_time - recall_create_time <= recall_time
-            }).cloned().collect();
-            for recall_trades in recall_ticker_info.clone() {
-                let size = Decimal::from_str(&recall_trades.size).unwrap();
-                volume += size;
-                sum_volume += size.abs();
-                if size > dec!(0) { long_volume += size } else { short_volume += size.abs() }
-            };
-            if long_volume / sum_volume >= config.long_volume_rate || short_volume / sum_volume >= config.short_volume_rate {
-                // 新增订单流主动性数据
-                let max_price = Decimal::from_str(&export_exchange_ticker_info.max_price.clone()).unwrap() * dec!(1.005);
-                ticker_info.push(Trades {
-                    id: Uuid::new_v4().to_string()[0..8].to_string(),
-                    data_type: "recall".to_string(),
-                    symbol: trades.symbol,
-                    create_time: trades.create_time,
-                    size: volume.to_string(),
-                    price: max_price.to_string(),
-                });
+    let mut max_price = Decimal::ONE;
+    for item in export_info.clone() {
+        let exchange_max_price = Decimal::from_str(&item.max_price).unwrap();
+        max_price = if max_price < exchange_max_price { exchange_max_price } else { max_price };
+    }
+
+    let mut initiative_info: Vec<Trades> = export_info.iter().flat_map(|exchange| exchange.ticker_info.clone()).collect();
+    initiative_info.sort_by(|a, b| a.create_time.cmp(&b.create_time));
+
+    let mut recall_initiative_info: Vec<Trades> = export_info.iter().flat_map(|exchange| exchange.recall_ticker_info.clone()).collect();
+    recall_initiative_info.sort_by(|a, b| a.create_time.cmp(&b.create_time));
+
+    let mut ticker_info = vec![];
+    let mut last_bool = "";
+    for trades in initiative_info {
+        // 计算交易量差
+        let mut volume = Decimal::ONE;
+        let mut short_volume = Decimal::ONE;
+        let mut long_volume = Decimal::ONE;
+        let mut sum_volume = Decimal::ONE;
+        let recall_ticker_info: Vec<Trades> = recall_initiative_info.iter().filter(|recall_trades| {
+            let recall_create_time = Decimal::from_str(&recall_trades.create_time).unwrap();
+            let create_time = Decimal::from_str(&trades.create_time).unwrap();
+            let recall_time = Decimal::from_i64(config.recall_time).unwrap();
+            recall_create_time <= create_time && create_time - recall_create_time <= recall_time
+        }).cloned().collect();
+        for recall_trades in recall_ticker_info.clone() {
+            let size = Decimal::from_str(&recall_trades.size).unwrap();
+            volume += size;
+            sum_volume += size.abs();
+            if size > dec!(0) { long_volume += size } else { short_volume += size.abs() }
+        };
+        let long_volume_bool = long_volume / sum_volume >= config.long_volume_rate;
+        let short_volume_bool = short_volume / sum_volume >= config.short_volume_rate;
+
+        if (long_volume_bool && last_bool != "long") || (short_volume_bool && last_bool != "short") || (!long_volume_bool && !short_volume_bool && last_bool != "none") {
+            // 新增订单流主动性数据
+            let max_price = max_price * dec!(1.005);
+            if long_volume_bool {
+                last_bool = "long";
             }
-        }
-        // 对订单流主动性数据(recall)去重
-        let mut ticker_set = std::collections::HashSet::new();
-        let mut end_ticker_info = vec![];
-        for trades in ticker_info {
-            if ticker_set.insert((trades.data_type.clone(), trades.create_time.clone())) {
-                end_ticker_info.push(trades.clone());
+            if short_volume_bool {
+                last_bool = "short";
+            }
+            if !long_volume_bool && !short_volume_bool {
+                last_bool = "none";
             }
+            ticker_info.push(Trades {
+                id: Uuid::new_v4().to_string()[0..8].to_string(),
+                data_type: last_bool.to_string(),
+                symbol: trades.symbol,
+                create_time: trades.create_time,
+                size: volume.to_string(),
+                price: max_price.to_string(),
+            });
         }
-        SeriesInfo {
-            name: export_exchange_ticker_info.name.clone(),
-            data: end_ticker_info.clone(),
+    }
+    // 对订单流主动性数据(recall)去重
+    let mut ticker_set = std::collections::HashSet::new();
+    let mut end_ticker_info = vec![];
+    for trades in ticker_info {
+        if ticker_set.insert((trades.data_type.clone(), trades.create_time.clone())) {
+            end_ticker_info.push(trades.clone());
         }
-    }).collect();
+    }
+    let initiative_info = SeriesInfo {
+        name: "主动性".to_string(),
+        data: end_ticker_info.clone(),
+    };
 
     let start_time_d = Decimal::from_str(start_at).unwrap() * dec!(1000) + dec!(8) * dec!(3600000);
     let end_time_d = Decimal::from_str(end_at).unwrap() * dec!(1000) + dec!(8) * dec!(3600000);
     let start_time = NaiveDateTime::from_timestamp_millis(start_time_d.to_i64().unwrap()).unwrap().format("%Y-%m-%d %H:%M:%S%.3f").to_string();
     let end_time = NaiveDateTime::from_timestamp_millis(end_time_d.to_i64().unwrap()).unwrap().format("%Y-%m-%d %H:%M:%S%.3f").to_string();
 
-    // let series_info: Vec<_> = export_info.iter().map(|item| {
-    //     SeriesInfo {
-    //         name: item.name.clone(),
-    //         data: item.ticker_info.clone(),
-    //     }
-    // }).collect();
-
+    let mut name_list: Vec<String> = vec![];
+    let mut legend_list: Vec<String> = vec![];
+    let mut series_info: Vec<SeriesInfo> = vec![];
+    for item in export_info.clone() {
+        name_list.push(format!("'{}'", item.name));
+        series_info.push(SeriesInfo {
+            name: item.name.clone(),
+            data: item.ticker_info.clone(),
+        })
+    }
+    series_info.push(initiative_info);
+    for item in series_info.clone() {
+        legend_list.push(format!("'{}'", item.name));
+    }
     let data = serde_json::json!({
         "chart_title": format!("{} Ticker数据", name_list.join("、").replace("'","")),
-        "legend_data": format!("[{}]", name_list.join(", ")),
+        "legend_data": format!("[{}]", legend_list.join(", ")),
         "series_info": series_info.clone(),
         "symbol": config.symbol.to_uppercase(),
         "start_at": start_time,
@@ -234,10 +260,10 @@ pub fn export_html(export_info: Vec<ExportExchangeTickerInfo>, start_at: &str, e
                       {
                         value: [{{create_time}},{{price}},{{size}},'{{data_type}}'],
                         symbolRotate: '{{size}}' > 0 ? '0' : '180',
-                        symbol: '{{data_type}}' == 'recall' ? 'circle' : 'triangle',
+                        symbol: '{{data_type}}' == 'ticker' ? 'triangle' : 'circle',
                         itemStyle: {
-                          color: '{{data_type}}' == 'recall' ? 'white' : exchangeColor['{{name}}'.toLocaleLowerCase()],
-                          borderColor: {{size}} > 0 ? 'green' : 'red',
+                          color: '{{data_type}}' == 'ticker' ? exchangeColor['{{name}}'.toLocaleLowerCase()] : 'white',
+                          borderColor: '{{data_type}}' == 'long' ? 'green' : '{{data_type}}' == 'short' ? 'red' : '{{data_type}}' == 'none' ? 'black' : {{size}} > 0 ? 'green' : 'red',
                           borderWidth: 1,
                         }
                       },