| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175 |
- use std::collections::BTreeMap;
- use std::str::FromStr;
- use actix_web::{HttpResponse};
- use chrono::Utc;
- use rust_decimal::Decimal;
- use rust_decimal::prelude::ToPrimitive;
- use rust_decimal_macros::dec;
- use serde_json::{json, Value};
- use crate::db_connector::get_trades_json;
- use crate::params_utils::{get_str, parse_str_to_decimal};
- use crate::server::{Response, Trade};
- pub fn symbol_fix(symbol: &str) -> String {
- let mut fixed = symbol.to_uppercase();
- if !fixed.contains("_USDT") {
- fixed = format!("{}_USDT", fixed);
- }
- fixed
- }
- // 将trades_json转换为指标
- pub async fn generate_msv(query_value: Value) -> HttpResponse {
- // 参数处理
- let exchange = match get_str(query_value.clone(), "exchange") {
- Ok(str) => {
- str
- }
- Err(response) => {
- return response
- }
- };
- let symbol = match get_str(query_value.clone(), "symbol") {
- Ok(symbol) => {
- symbol_fix(symbol.as_str())
- }
- Err(response) => {
- return response
- }
- };
- let mills_back = match parse_str_to_decimal(query_value.clone(), "mills_back") {
- Ok(t) => {
- t
- }
- Err(response) => {
- return response
- }
- };
- let minute_time_range = match parse_str_to_decimal(query_value.clone(), "minute_time_range") {
- Ok(t) => {
- t.to_i64().unwrap()
- }
- Err(response) => {
- return response
- }
- };
- // 链接数据服务器查询数据
- let end_time = Utc::now().timestamp_millis();
- let start_time = end_time - minute_time_range * 60 * 1000;
- let db_response = get_trades_json(
- exchange.as_str(),
- symbol.as_str(),
- start_time,
- end_time,
- ).await;
- // 对数据库返回的数据进行容错处理
- if db_response.code == 200 {
- // 数据本地化处理
- let trades = parse_json_to_trades(db_response.data);
- // 指标生成
- let indicator = generate_msv_by_trades(trades, mills_back);
- // 返回数据
- let response = Response {
- query: query_value.clone(),
- msg: Some("指标生成完毕".to_string()),
- code: 200,
- data: indicator,
- };
- let json_string = serde_json::to_string(&response).unwrap();
- HttpResponse::Ok().content_type("application/json").body(json_string)
- } else {
- let json_string = serde_json::to_string(&db_response).unwrap();
- HttpResponse::Ok().content_type("application/json").body(json_string)
- }
- }
- // 将trades转换为具体指标
- pub fn generate_msv_by_trades(mut trades: Vec<Trade>, mills_back: Decimal) -> Value {
- let mut amplitude_map: BTreeMap<Decimal, Decimal> = BTreeMap::new();
- const GAMMA: Decimal = dec!(0.5);
- // 每一个元素都遍历一遍
- trades.sort_by(|a, b| Decimal::from_str(a.id.as_str()).unwrap().cmp(&Decimal::from_str(b.id.as_str()).unwrap()));
- for (index, trade) in trades.iter().enumerate() {
- // 该元素向前遍历range毫秒
- let mut range_index = if index == 0 {
- 0
- } else {
- index
- };
- // 计算区间的预定价格
- let mut ref_price = trade.price;
- loop {
- // 第0个就不搞
- if range_index == 0 {
- break;
- }
- let flag_trade = trades.get(range_index).unwrap();
- let range_time = trade.time - flag_trade.time;
- // 判断该ticker是否是range ms以外
- if range_time > mills_back {
- break;
- }
- ref_price = ref_price * GAMMA + flag_trade.price * (Decimal::ONE - GAMMA);
- range_index -= 1;
- }
- // 逻辑计算层
- // 取离当前点最远的点进行测量
- let last_price = trade.price;
- // 不是初始值,以及不是0波动
- if index != 0 {
- let mut rate = Decimal::ONE_HUNDRED * (last_price - ref_price) / ref_price;
- rate.rescale(2);
- // 去除小数位之后,可以忽略一些太小的波动,减少图表生成压力
- if rate.eq(&Decimal::ZERO) {
- continue
- }
- amplitude_map.insert(trade.time, rate);
- }
- }
- let x: Vec<Decimal> = amplitude_map.keys().cloned().collect();
- let y: Vec<Decimal> = amplitude_map.values().cloned().collect();
- let total_size = trades.len();
- let result_size = x.len();
- json!({
- "x": x,
- "y": y,
- "total_size": total_size,
- "result_size": result_size,
- })
- }
- // 将json转换为trades
- pub fn parse_json_to_trades(trades_json: Value) -> Vec<Trade> {
- let mut rst = vec![];
- for trade_json in trades_json.as_array().unwrap() {
- let arr = trade_json.as_array().unwrap();
- rst.push(Trade {
- id: arr[0].as_str().unwrap().to_string(),
- time: Decimal::from_str(arr[1].as_str().unwrap()).unwrap(),
- size: Decimal::from_str(arr[2].as_str().unwrap()).unwrap(),
- price: Decimal::from_str(arr[3].as_str().unwrap()).unwrap(),
- });
- }
- rst
- }
|