use std::collections::VecDeque; use std::ops::{Div, Mul}; use std::path::Path; use chrono::Utc; use rand::Rng; use rust_decimal::Decimal; use tokio::fs; use tokio::fs::File; use tokio::io::AsyncWriteExt; use tracing::{error}; use global::public_params; // 生成订单的id,可以根据交易所名字来 pub fn generate_client_id(exchange_name_some: Option) -> String { // 交易所名字获取 let mut exchange_name = exchange_name_some.unwrap_or("".to_string()); // 0-1000的随机数 let rand_num = rand::thread_rng().gen_range(1..1000); // 随机时间戳 let in_ms = Utc::now().timestamp_micros(); let time_str = in_ms.to_string(); let time_slice = &time_str[10..]; // 火币只能纯数字 if exchange_name == "htx" { let mut rng = rand::thread_rng(); // 获取一个随机数生成器 let random_number = rng.gen_range(1000..10000); // 生成一个四位随机数 exchange_name = random_number.to_string(); } let result = format!("{}{}{}{}", "1", time_slice, rand_num, exchange_name); return result; } // 大小限定:将num限定在lower_limit和upper_limit范围内 pub fn clip(num: Decimal, lower_limit: Decimal, upper_limit: Decimal) -> Decimal { if num.ge(&upper_limit) { return upper_limit; } if num.le(&lower_limit) { return lower_limit; } num } // 步长修复数量 pub fn fix_amount(amount: Decimal, step_size: Decimal) -> Decimal { // 思路:做除法后取整,然后使用这个值乘以步长 amount.div(step_size).floor().mul(step_size) } // 根据最小下单价值获取下单数量 // pub fn get_amount_by_min_amount_value(min_amount_value: Decimal, // order_price: Decimal, // step_size: Decimal) -> Decimal { // // ceil可以向上取整 // let amount_unit = ((min_amount_value / order_price) / step_size).ceil(); // // amount_unit * step_size // } // 步长修复价格 pub fn fix_price(amount: Decimal, tick_size: Decimal) -> Decimal { // 思路:做除法后四舍五入,然后使用这个值乘以步长 amount.div(tick_size).round().mul(tick_size) } // 每秒请求频率 pub fn get_limit_requests_num_per_second(exchange: String) -> i64 { if exchange.eq("kucoin_spot") { return public_params::KUCOIN_SPOT_LIMIT * public_params::RATIO; } else if exchange.eq("kucoin_usdt_swap") { return public_params::KUCOIN_USDT_SWAP_LIMIT * public_params::RATIO; } else if exchange.eq("binance_usdt_swap") { return public_params::BINANCE_USDT_SWAP_LIMIT * public_params::RATIO; } else if exchange.eq("binance_spot") { return public_params::BINANCE_SPOT_LIMIT * public_params::RATIO; } else if exchange.eq("gate_spot") { return public_params::GATE_SPOT_LIMIT * public_params::RATIO; } else if exchange.eq("gate_usdt_swap") { return public_params::GATE_USDT_SWAP_LIMIT * public_params::RATIO; } else if exchange.eq("coinex_usdt_swap") { return public_params::COINEX_USDT_SWAP_LIMIT * public_params::RATIO; } else if exchange.eq("coinex_spot") { return public_params::COINEX_SPOT_LIMIT * public_params::RATIO; } else if exchange.eq("okex_usdt_swap") { return public_params::OKEX_USDT_SWAP_LIMIT * public_params::RATIO; } else if exchange.eq("bitget_spot") { return public_params::BITGET_USDT_SPOT_LIMIT * public_params::RATIO; } else if exchange.eq("bitget_usdt_swap") { return public_params::BITGET_USDT_SWAP_LIMIT * public_params::RATIO; } else if exchange.eq("bybit_usdt_swap"){ return public_params::BYBIT_USDT_SWAP_LIMIT * public_params::RATIO; } else if exchange.eq("htx_usdt_swap") { return public_params::HTX_USDT_SWAP_LIMIT * public_params::RATIO; } else if exchange.eq("mexc_usdt_swap") { return public_params::MEXC_USDT_SWAP_LIMIT * public_params::RATIO; } else { error!("限频规则(ratio)未找到,请检查配置!"); panic!("限频规则(ratio)未找到,请检查配置!"); } } // 每秒下单请求频率 pub fn get_limit_order_requests_num_per_second(exchange: String) -> i64 { if exchange.eq("kucoin_spot") { return public_params::KUCOIN_SPOT_LIMIT } else if exchange.eq("kucoin_usdt_swap") { return public_params::KUCOIN_USDT_SWAP_LIMIT } else if exchange.eq("binance_usdt_swap") { return public_params::BINANCE_USDT_SWAP_LIMIT } else if exchange.eq("binance_spot") { return public_params::BINANCE_SPOT_LIMIT } else if exchange.eq("gate_spot") { return public_params::GATE_SPOT_LIMIT } else if exchange.eq("gate_usdt_swap") { return public_params::GATE_USDT_SWAP_LIMIT } else if exchange.eq("coinex_usdt_swap") { return public_params::COINEX_USDT_SWAP_LIMIT } else if exchange.eq("coinex_spot") { return public_params::COINEX_SPOT_LIMIT } else if exchange.eq("okex_usdt_swap") { return public_params::OKEX_USDT_SWAP_LIMIT } else if exchange.eq("bitget_spot") { return public_params::BITGET_USDT_SPOT_LIMIT } else if exchange.eq("bitget_usdt_swap") { return public_params::BITGET_USDT_SWAP_LIMIT } else if exchange.eq("bybit_usdt_swap") { return public_params::BYBIT_USDT_SWAP_LIMIT } else if exchange.eq("htx_usdt_swap") { return public_params::HTX_USDT_SWAP_LIMIT } else if exchange.eq("mexc_usdt_swap") { return public_params::MEXC_USDT_SWAP_LIMIT } else { error!("限频规则(limit)未找到,请检查配置!"); panic!("限频规则(limit)未找到,请检查配置!"); } } pub async fn write_to_file(json_data: &String, file_path: String) { // 尝试创建文件路径 if let Err(e) = fs::create_dir_all( // 获取文件目录路径 Path::new(&file_path) .parent() // 获取父目录(即文件路径除去文件名后的部分) .unwrap_or_else(|| Path::new("")), // 如果没有父目录,使用当前目录 ) .await { // 如果创建路径失败,打印错误日志 error!("创建目录错误: {:?}", e); return; // 结束任务 } // 异步地执行文件写入操作 if let Err(e) = async { let mut file = File::create(&file_path).await?; file.write_all(json_data.as_bytes()).await?; Result::<(), std::io::Error>::Ok(()) } .await { // 如果发生错误,只打印错误日志 error!("json db写入错误: {:?}", e); } } pub fn build_html_file(data_c: &Vec>>) -> String { let temp_json_str = serde_json::to_string(&data_c).unwrap(); let str1 = r##" Document
上一页
第1/1页
下一页
"##; format!("{}{}{}", str1, temp_json_str, str2) } #[cfg(test)] mod tests { use chrono::Utc; use rust_decimal_macros::dec; use crate::utils::{clip, fix_amount, fix_price, generate_client_id}; #[test] fn clip_test() { let num = dec!(11); // let num2 = dec!(2); let lower_limit = dec!(3); let upper_limit = dec!(6); println!("mum: {}", clip(num, lower_limit, upper_limit)); println!("mum2: {}", clip(num, lower_limit, upper_limit)); } #[test] fn generate_client_id_test() { println!("{}", generate_client_id(None)); println!("{}", generate_client_id(Some("binance".to_string()))); } #[test] fn fix_amount_test() { println!("{}", fix_amount(dec!(0.9), dec!(0.04))); println!("{}", fix_amount(dec!(1.0), dec!(0.1))); println!("{}", fix_amount(dec!(0.9), dec!(0.05))); println!("{}", fix_amount(dec!(1), dec!(0.1))); println!("{}", fix_amount(dec!(0.01), dec!(0.05))); } #[test] fn fix_price_test() { println!("{}", fix_price(dec!(1), dec!(0.1))); println!("{}", fix_price(dec!(0.9), dec!(2.0))); println!("{}", fix_price(dec!(1.1), dec!(0.1))); println!("{}", fix_price(dec!(1.2), dec!(0.5))); println!("{}", fix_price(dec!(4999.99), dec!(0.5))); } #[test] fn utc_timestamp_test() { let now = Utc::now(); println!("timestamp: {}", now.timestamp()); println!("timestamp_millis: {}", now.timestamp_millis()); println!("timestamp_micros: {}", now.timestamp_micros()); println!("timestamp_nanos: {}", now.timestamp_nanos_opt().unwrap()); } }