1use std::time::{SystemTime, UNIX_EPOCH};
2
3use rand::Rng;
4
5use crate::types::{OrderSide, TickSize};
6
7pub fn current_timestamp() -> u64 {
9 SystemTime::now()
10 .duration_since(UNIX_EPOCH)
11 .unwrap_or_default()
12 .as_secs()
13}
14
15pub fn calculate_order_amounts(
17 price: f64,
18 size: f64,
19 side: OrderSide,
20 tick_size: TickSize,
21) -> (String, String) {
22 const SIZE_DECIMALS: u32 = 2; let tick_decimals = tick_size.decimals();
25
26 let price_rounded = round_to_decimals(price, tick_decimals);
28
29 let size_rounded = round_to_decimals(size, SIZE_DECIMALS);
31
32 let cost = price_rounded * size_rounded;
34 let cost_rounded = round_to_decimals(cost, tick_decimals);
35
36 let share_amount = to_raw_amount(size_rounded, SIZE_DECIMALS);
38 let cost_amount = to_raw_amount(cost_rounded, SIZE_DECIMALS);
39
40 match side {
41 OrderSide::Buy => {
42 (cost_amount, share_amount)
44 }
45 OrderSide::Sell => {
46 (share_amount, cost_amount)
48 }
49 }
50}
51
52fn round_to_decimals(value: f64, decimals: u32) -> f64 {
54 let multiplier = 10_f64.powi(decimals as i32);
55 (value * multiplier).round() / multiplier
56}
57
58fn to_raw_amount(value: f64, decimals: u32) -> String {
60 let multiplier = 10_f64.powi(decimals as i32);
61 let raw = (value * multiplier).floor() as u128;
62 raw.to_string()
63}
64
65pub fn generate_salt() -> String {
67 rand::rng().random::<u128>().to_string()
68}
69
70#[cfg(test)]
71mod tests {
72 use super::*;
73
74 #[test]
75 fn test_calculate_order_amounts_buy() {
76 let (maker, taker) =
77 calculate_order_amounts(0.52, 100.0, OrderSide::Buy, TickSize::Hundredth);
78
79 assert_eq!(maker, "5200");
81 assert_eq!(taker, "10000");
82 }
83
84 #[test]
85 fn test_calculate_order_amounts_sell() {
86 let (maker, taker) =
87 calculate_order_amounts(0.52, 100.0, OrderSide::Sell, TickSize::Hundredth);
88
89 assert_eq!(maker, "10000");
91 assert_eq!(taker, "5200");
92 }
93}