|
@@ -5,15 +5,19 @@ use chrono::NaiveDateTime;
|
|
|
use handlebars::Handlebars;
|
|
use handlebars::Handlebars;
|
|
|
use rust_decimal::Decimal;
|
|
use rust_decimal::Decimal;
|
|
|
use rust_decimal::prelude::ToPrimitive;
|
|
use rust_decimal::prelude::ToPrimitive;
|
|
|
|
|
+use uuid::Uuid;
|
|
|
use rust_decimal_macros::dec;
|
|
use rust_decimal_macros::dec;
|
|
|
use serde::{Deserialize, Serialize};
|
|
use serde::{Deserialize, Serialize};
|
|
|
use tracing::info;
|
|
use tracing::info;
|
|
|
use crate::struct_standard::Trades;
|
|
use crate::struct_standard::Trades;
|
|
|
|
|
+use crate::utils::utils::ConfigInfo;
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Deserialize, Serialize)]
|
|
#[derive(Debug, Clone, Deserialize, Serialize)]
|
|
|
pub struct ExportExchangeTickerInfo {
|
|
pub struct ExportExchangeTickerInfo {
|
|
|
pub name: String,
|
|
pub name: String,
|
|
|
pub ticker_info: Vec<Trades>,
|
|
pub ticker_info: Vec<Trades>,
|
|
|
|
|
+ pub recall_ticker_info: Vec<Trades>,
|
|
|
|
|
+ pub max_price: String,
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Deserialize, Serialize)]
|
|
#[derive(Debug, Clone, Deserialize, Serialize)]
|
|
@@ -22,34 +26,81 @@ pub struct SeriesInfo {
|
|
|
pub data: Vec<Trades>,
|
|
pub data: Vec<Trades>,
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-pub fn export_html(export_info: Vec<ExportExchangeTickerInfo>, symbol: &str, start_at: &str, end_at: &str, export_path: Option<&str>, export_name: Option<&str>) {
|
|
|
|
|
|
|
+pub fn export_html(export_info: Vec<ExportExchangeTickerInfo>, start_at: &str, end_at: &str, config: ConfigInfo) {
|
|
|
info!("正在生成网页,请稍后!");
|
|
info!("正在生成网页,请稍后!");
|
|
|
- let path = format!("{}/{}.html", export_path.unwrap_or("./"), export_name.unwrap_or("export")).replace("//", "/");
|
|
|
|
|
|
|
+ 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 path = format!("{}/{}.html", export_path, export_name).replace("//", "/");
|
|
|
// 创建 Handlebars 实例
|
|
// 创建 Handlebars 实例
|
|
|
let mut handlebars = Handlebars::new();
|
|
let mut handlebars = Handlebars::new();
|
|
|
|
|
|
|
|
let mut name_list: Vec<String> = vec![];
|
|
let mut name_list: Vec<String> = vec![];
|
|
|
- for exchange_info in export_info.clone().into_iter() {
|
|
|
|
|
- name_list.push(format!("'{}'", exchange_info.name));
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ 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;
|
|
|
|
|
+ for recall_trades in export_exchange_ticker_info.recall_ticker_info.clone() {
|
|
|
|
|
+ if recall_trades.create_time <= trades.create_time {
|
|
|
|
|
+ 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() }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ };
|
|
|
|
|
+ if long_volume / sum_volume >= dec!(0.7) || short_volume / sum_volume >= dec!(0.7) {
|
|
|
|
|
+ // 新增订单流主动性数据
|
|
|
|
|
+ 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(),
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ // 对订单流主动性数据(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());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ SeriesInfo {
|
|
|
|
|
+ name: export_exchange_ticker_info.name.clone(),
|
|
|
|
|
+ data: end_ticker_info.clone(),
|
|
|
|
|
+ }
|
|
|
|
|
+ }).collect();
|
|
|
|
|
|
|
|
let start_time_d = Decimal::from_str(start_at).unwrap() * dec!(1000) + dec!(8) * dec!(3600000);
|
|
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 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 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 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 series_info: Vec<_> = export_info.iter().map(|item| {
|
|
|
|
|
+ // SeriesInfo {
|
|
|
|
|
+ // name: item.name.clone(),
|
|
|
|
|
+ // data: item.ticker_info.clone(),
|
|
|
|
|
+ // }
|
|
|
|
|
+ // }).collect();
|
|
|
|
|
|
|
|
let data = serde_json::json!({
|
|
let data = serde_json::json!({
|
|
|
"chart_title": format!("{} Ticker数据", name_list.join("、").replace("'","")),
|
|
"chart_title": format!("{} Ticker数据", name_list.join("、").replace("'","")),
|
|
|
"legend_data": format!("[{}]", name_list.join(", ")),
|
|
"legend_data": format!("[{}]", name_list.join(", ")),
|
|
|
"series_info": series_info.clone(),
|
|
"series_info": series_info.clone(),
|
|
|
- "symbol": symbol.to_uppercase(),
|
|
|
|
|
|
|
+ "symbol": config.symbol.to_uppercase(),
|
|
|
"start_at": start_time,
|
|
"start_at": start_time,
|
|
|
"end_at": end_time,
|
|
"end_at": end_time,
|
|
|
});
|
|
});
|