|
|
@@ -10,7 +10,7 @@ use rust_decimal_macros::dec;
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
use tracing::info;
|
|
|
use crate::struct_standard::Trades;
|
|
|
-use crate::utils::utils::ConfigInfo;
|
|
|
+use crate::utils::utils::TickerConfigInfo;
|
|
|
|
|
|
#[derive(Debug, Clone, Deserialize, Serialize)]
|
|
|
pub struct ExportExchangeTickerInfo {
|
|
|
@@ -27,91 +27,103 @@ pub struct SeriesInfo {
|
|
|
pub data: Vec<Trades>,
|
|
|
}
|
|
|
|
|
|
-pub fn export_html(export_info: Vec<ExportExchangeTickerInfo>, start_at: &str, end_at: &str, config: ConfigInfo, robot_info: Vec<Trades>) {
|
|
|
+impl SeriesInfo {
|
|
|
+ fn new() -> SeriesInfo {
|
|
|
+ SeriesInfo {
|
|
|
+ name: "".to_string(),
|
|
|
+ classify: "".to_string(),
|
|
|
+ data: vec![],
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+pub fn export_html(export_info: Vec<ExportExchangeTickerInfo>, start_at: &str, end_at: &str, config: TickerConfigInfo, robot_info: Vec<Trades>) {
|
|
|
info!("正在生成网页,请稍后!");
|
|
|
let export_path = if config.export_path == "" { "./" } else { config.export_path.as_str() };
|
|
|
- let export_name = if config.export_name == "" { "export" } else { config.export_name.as_str() };
|
|
|
+ let export_name = if config.export_name == "" { "export_ticker" } else { config.export_name.as_str() };
|
|
|
let path = format!("{}/{}.html", export_path, export_name).replace("//", "/");
|
|
|
// 创建 Handlebars 实例
|
|
|
let mut handlebars = Handlebars::new();
|
|
|
|
|
|
+ let mut initiative_info = SeriesInfo::new();
|
|
|
+ if config.recall_time != 0 {
|
|
|
+ let mut max_price = Decimal::ZERO;
|
|
|
+ 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 max_price = Decimal::ZERO;
|
|
|
- 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 old_ticker_info: Vec<Trades> = export_info.iter().flat_map(|exchange| exchange.ticker_info.clone()).collect();
|
|
|
+ old_ticker_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 old_recall_ticker_info: Vec<Trades> = export_info.iter().flat_map(|exchange| exchange.recall_ticker_info.clone()).collect();
|
|
|
+ old_recall_ticker_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::ZERO;
|
|
|
- let mut short_volume = Decimal::ZERO;
|
|
|
- let mut long_volume = Decimal::ZERO;
|
|
|
- let mut sum_volume = Decimal::ZERO;
|
|
|
- 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;
|
|
|
+ let mut ticker_info = vec![];
|
|
|
+ let mut last_bool = "";
|
|
|
+ for trades in old_ticker_info {
|
|
|
+ // 计算交易量差
|
|
|
+ let mut volume = Decimal::ZERO;
|
|
|
+ let mut short_volume = Decimal::ZERO;
|
|
|
+ let mut long_volume = Decimal::ZERO;
|
|
|
+ let mut sum_volume = Decimal::ZERO;
|
|
|
+ let recall_ticker_info: Vec<Trades> = old_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() }
|
|
|
+ };
|
|
|
+ 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 != "initiative_long") || (short_volume_bool && last_bool != "initiative_short") || (!long_volume_bool && !short_volume_bool && last_bool != "initiative_none") {
|
|
|
- // 新增订单流主动性数据
|
|
|
- let max_price = max_price * dec!(1.005);
|
|
|
- let mut side = "";
|
|
|
- if long_volume_bool {
|
|
|
- last_bool = "initiative_long";
|
|
|
- side = "LONG";
|
|
|
- }
|
|
|
- if short_volume_bool {
|
|
|
- last_bool = "initiative_short";
|
|
|
- side = "SHORT";
|
|
|
- }
|
|
|
- if !long_volume_bool && !short_volume_bool {
|
|
|
- last_bool = "initiative_none";
|
|
|
- side = "NONE";
|
|
|
+ if (long_volume_bool && last_bool != "initiative_long") || (short_volume_bool && last_bool != "initiative_short") || (!long_volume_bool && !short_volume_bool && last_bool != "initiative_none") {
|
|
|
+ // 新增订单流主动性数据
|
|
|
+ let max_price = max_price * dec!(1.005);
|
|
|
+ let mut side = "";
|
|
|
+ if long_volume_bool {
|
|
|
+ last_bool = "initiative_long";
|
|
|
+ side = "LONG";
|
|
|
+ }
|
|
|
+ if short_volume_bool {
|
|
|
+ last_bool = "initiative_short";
|
|
|
+ side = "SHORT";
|
|
|
+ }
|
|
|
+ if !long_volume_bool && !short_volume_bool {
|
|
|
+ last_bool = "initiative_none";
|
|
|
+ side = "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(),
|
|
|
+ side: side.to_string(),
|
|
|
+ is_effect: true,
|
|
|
+ });
|
|
|
}
|
|
|
- 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(),
|
|
|
- side: side.to_string(),
|
|
|
- is_effect: true,
|
|
|
- });
|
|
|
- }
|
|
|
- }
|
|
|
- // 对订单流主动性数据(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());
|
|
|
}
|
|
|
+ // 对订单流主动性数据(recall)去重
|
|
|
+ let mut ticker_set = std::collections::HashSet::new();
|
|
|
+ let mut initiative_ticker_info = vec![];
|
|
|
+ for trades in ticker_info {
|
|
|
+ if ticker_set.insert((trades.data_type.clone(), trades.create_time.clone())) {
|
|
|
+ initiative_ticker_info.push(trades.clone());
|
|
|
+ }
|
|
|
+ };
|
|
|
+ initiative_info = SeriesInfo {
|
|
|
+ name: "主动性".to_string(),
|
|
|
+ classify: "initiative".to_string(),
|
|
|
+ data: initiative_ticker_info.clone(),
|
|
|
+ };
|
|
|
}
|
|
|
- let initiative_info = SeriesInfo {
|
|
|
- name: "主动性".to_string(),
|
|
|
- classify: "initiative".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);
|
|
|
@@ -130,7 +142,9 @@ pub fn export_html(export_info: Vec<ExportExchangeTickerInfo>, start_at: &str, e
|
|
|
data: item.ticker_info.clone(),
|
|
|
})
|
|
|
}
|
|
|
- series_info.push(initiative_info);
|
|
|
+ if config.recall_time != 0 {
|
|
|
+ series_info.push(initiative_info);
|
|
|
+ }
|
|
|
|
|
|
if config.robot_name != "" {
|
|
|
let ref_robot_info: Vec<Trades> = robot_info.iter().filter(|trades| trades.data_type == "robot_ref_info").cloned().collect();
|
|
|
@@ -347,5 +361,5 @@ pub fn export_html(export_info: Vec<ExportExchangeTickerInfo>, start_at: &str, e
|
|
|
// 将 HTML 写入文件
|
|
|
let mut file = File::create(&path).expect("创建文件失败!");
|
|
|
file.write_all(output.as_bytes()).expect("写入文件到本地失败!");
|
|
|
- info!("网页生成成功!路径:{:?}", path);
|
|
|
+ info!("Ticker信息网页生成成功!路径:{:?}\n\n", path);
|
|
|
}
|