|
|
@@ -0,0 +1,143 @@
|
|
|
+use std::collections::{HashMap, HashSet};
|
|
|
+use actix_web::HttpResponse;
|
|
|
+use rust_decimal::Decimal;
|
|
|
+use serde_json::{json, Value};
|
|
|
+use tracing::info;
|
|
|
+use crate::db_connector::{get_records_json, get_symbols_json};
|
|
|
+use crate::msv::{generate_msv_by_trades, parse_json_to_trades};
|
|
|
+use crate::server::Response;
|
|
|
+
|
|
|
+fn get_public_symbols(symbols_map: &Value) -> Vec<String> {
|
|
|
+ // 解析 JSON 数据为 HashMap
|
|
|
+ let exchanges_map: HashMap<String, Vec<String>> = serde_json::from_value(symbols_map.clone()).unwrap();
|
|
|
+
|
|
|
+ // 初始化一个可选的 HashSet 用于存储交集结果
|
|
|
+ let mut common_symbols: Option<HashSet<String>> = None;
|
|
|
+
|
|
|
+ // 遍历每个交易所的 symbols
|
|
|
+ for symbols in exchanges_map.values() {
|
|
|
+ let current_set: HashSet<String> = symbols.into_iter().cloned().collect();
|
|
|
+ common_symbols = match common_symbols {
|
|
|
+ Some(set) => Some(set.intersection(¤t_set).cloned().collect()),
|
|
|
+ None => Some(current_set),
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ // 将结果从 HashSet 转换为 Vec<String>
|
|
|
+ common_symbols.unwrap_or_default().into_iter().collect::<Vec<String>>()
|
|
|
+}
|
|
|
+
|
|
|
+pub async fn get_symbols(mode: &str, exchanges: &Vec<String>, minute_time_range: &Decimal, filters: &Vec<Value>) -> HttpResponse {
|
|
|
+ // 1. 获取所选交易所的所有交易对
|
|
|
+ let mut symbols_map = json!({});
|
|
|
+ for exchange in exchanges {
|
|
|
+ let db_response = get_symbols_json(exchange.as_str()).await;
|
|
|
+
|
|
|
+ // 对数据库返回的数据进行容错处理
|
|
|
+ if db_response.code == 200 {
|
|
|
+ let symbol_array_value = db_response.data;
|
|
|
+
|
|
|
+ symbols_map[exchange] = symbol_array_value.clone();
|
|
|
+ } else {
|
|
|
+ let json_string = serde_json::to_string(&db_response).unwrap();
|
|
|
+ return HttpResponse::Ok().content_type("application/json").body(json_string);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 2. 如果是多交易所,则获取所有交易所的交集
|
|
|
+ let mut symbols: Vec<String> = get_public_symbols(&symbols_map);
|
|
|
+ // 确保有足够的元素
|
|
|
+ let n = 20;
|
|
|
+ // 获取前20个元素,如果不足20个,则获取全部
|
|
|
+ let top_symbols = if symbols.len() > n {
|
|
|
+ &symbols[0..n]
|
|
|
+ } else {
|
|
|
+ &symbols[..]
|
|
|
+ };
|
|
|
+ // 如果你需要将这些元素放在新的 Vec 中
|
|
|
+ symbols = top_symbols.to_vec();
|
|
|
+
|
|
|
+ // 3. 获取它们的k线数据,注意时间范围以及保存形式。
|
|
|
+ // {
|
|
|
+ // "symbol1": {
|
|
|
+ // "exchange1": [k1,k2,...]
|
|
|
+ // "exchange2": [k1,k2,...]
|
|
|
+ // },
|
|
|
+ // "symbol2": {
|
|
|
+ // "exchange1": [k1,k2,...]
|
|
|
+ // "exchange2": [k1,k2,...]
|
|
|
+ // },
|
|
|
+ // }
|
|
|
+ let mut records_map = json!({});
|
|
|
+ for symbol in symbols {
|
|
|
+ records_map[symbol.clone()] = json!({});
|
|
|
+ for exchange in exchanges {
|
|
|
+ let db_response = get_records_json(exchange.as_str()).await;
|
|
|
+
|
|
|
+ // 对数据库返回的数据进行容错处理
|
|
|
+ if db_response.code == 200 {
|
|
|
+ let symbol_array_value = db_response.data;
|
|
|
+
|
|
|
+ records_map[symbol.clone()][exchange] = symbol_array_value.clone();
|
|
|
+ } else {
|
|
|
+ let json_string = serde_json::to_string(&db_response).unwrap();
|
|
|
+ return HttpResponse::Ok().content_type("application/json").body(json_string);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 4. 整理完之后,获取指标数据,进行逻辑判断,注意与/或只是指过滤器,如果选择了多交易所,交易所的逻辑部分都是与
|
|
|
+ // 举例:
|
|
|
+ // 选择了gate_usdt_swap与bitget_usdt_swap两个交易所,并且对交易量进行了0.5M的过滤
|
|
|
+ // 两个交易所都有xrp,如果gate与bitget的xrp交易量都大于0.5M,则会显示在最终列表中
|
|
|
+ // 5. 最终出来的数据结构,要体现出交易所
|
|
|
+
|
|
|
+ let response_value = json!([
|
|
|
+ {
|
|
|
+ "symbol": "BTC_USDT",
|
|
|
+ "rise": {
|
|
|
+ "gate_usdt_swap": 3,
|
|
|
+ "bitget_usdt_swap": 2.9,
|
|
|
+ },
|
|
|
+ "volume": {
|
|
|
+ "gate_usdt_swap": 0.1,
|
|
|
+ "bitget_usdt_swap": 0.5,
|
|
|
+ "total": 0.6,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "symbol": "DOGE_USDT",
|
|
|
+ "rise": {
|
|
|
+ "gate_usdt_swap": -1.9,
|
|
|
+ "bitget_usdt_swap": -2,
|
|
|
+ },
|
|
|
+ "volume": {
|
|
|
+ "gate_usdt_swap": 0.2,
|
|
|
+ "bitget_usdt_swap": 0.3,
|
|
|
+ "total": 0.5,
|
|
|
+ },
|
|
|
+ }
|
|
|
+ ]);
|
|
|
+ let response = Response {
|
|
|
+ query: Value::Null,
|
|
|
+ msg: Some("指标生成完毕".to_string()),
|
|
|
+ code: 200,
|
|
|
+ data: response_value,
|
|
|
+ };
|
|
|
+
|
|
|
+ let json_string = serde_json::to_string(&response).unwrap();
|
|
|
+ HttpResponse::Ok().content_type("application/json").body(json_string)
|
|
|
+}
|
|
|
+
|
|
|
+#[tokio::test]
|
|
|
+async fn get_public_symbols_test() {
|
|
|
+ use global::log_utils::init_log_with_info;
|
|
|
+ use tracing::info;
|
|
|
+ init_log_with_info();
|
|
|
+
|
|
|
+ let exchanges = json!({
|
|
|
+ "bitget_usdt_swap": ["BTC_USDT", "ETH_USDT", "MEW_USDT"],
|
|
|
+ "gate_usdt_swap": ["BTC_USDT", "ETH_USDT", "DOGE_USDT"]
|
|
|
+ });
|
|
|
+
|
|
|
+ let rst = get_public_symbols(&exchanges);
|
|
|
+ info!(?rst)
|
|
|
+}
|