px_exchange_kalshi/
normalize.rs1pub fn normalize_kalshi_trade_price(raw: f64) -> Option<f64> {
11 if !raw.is_finite() {
12 return None;
13 }
14 let mut p = raw;
15 if p >= 1.0 {
16 p /= 100.0;
17 }
18 p = (p * 1_000_000.0).round() / 1_000_000.0;
20 if p > 0.0 && p < 1.0 {
21 Some(p)
22 } else {
23 None
24 }
25}
26
27pub fn normalize_kalshi_outcome(outcome: Option<&str>) -> Option<String> {
31 outcome.and_then(|o| match o.trim().to_ascii_lowercase().as_str() {
32 "yes" => Some("Yes".to_string()),
33 "no" => Some("No".to_string()),
34 _ => None,
35 })
36}
37
38pub trait KalshiTradeLike {
41 fn price(&self) -> f64;
42 fn set_price(&mut self, p: f64);
43 fn yes_price(&self) -> Option<f64>;
44 fn set_yes_price(&mut self, p: Option<f64>);
45 fn no_price(&self) -> Option<f64>;
46 fn set_no_price(&mut self, p: Option<f64>);
47 fn outcome(&self) -> Option<&str>;
48 fn set_outcome(&mut self, o: Option<String>);
49 fn size(&self) -> f64;
50}
51
52pub fn normalize_kalshi_trade<T: KalshiTradeLike>(mut trade: T) -> Option<T> {
55 trade.set_price(normalize_kalshi_trade_price(trade.price())?);
56 trade.set_yes_price(trade.yes_price().and_then(normalize_kalshi_trade_price));
57 trade.set_no_price(trade.no_price().and_then(normalize_kalshi_trade_price));
58 trade.set_outcome(normalize_kalshi_outcome(trade.outcome()));
59 if trade.size() <= 0.0 {
60 return None;
61 }
62 Some(trade)
63}
64
65impl KalshiTradeLike for px_core::MarketTrade {
66 fn price(&self) -> f64 {
67 self.price
68 }
69 fn set_price(&mut self, p: f64) {
70 self.price = p;
71 }
72 fn yes_price(&self) -> Option<f64> {
73 self.yes_price
74 }
75 fn set_yes_price(&mut self, p: Option<f64>) {
76 self.yes_price = p;
77 }
78 fn no_price(&self) -> Option<f64> {
79 self.no_price
80 }
81 fn set_no_price(&mut self, p: Option<f64>) {
82 self.no_price = p;
83 }
84 fn outcome(&self) -> Option<&str> {
85 self.outcome.as_deref()
86 }
87 fn set_outcome(&mut self, o: Option<String>) {
88 self.outcome = o;
89 }
90 fn size(&self) -> f64 {
91 self.size
92 }
93}