1pub fn price_to_earnings(price: f64, eps: f64) -> f64 {
15 if eps <= 0.0 { f64::INFINITY } else { price / eps }
16}
17
18pub fn price_to_book(price: f64, book_value_per_share: f64) -> f64 {
20 if book_value_per_share <= 0.0 { f64::INFINITY } else { price / book_value_per_share }
21}
22
23pub fn earnings_yield(eps: f64, price: f64) -> f64 {
25 if price <= 0.0 { 0.0 } else { eps / price }
26}
27
28pub fn ev_to_ebit(enterprise_value: f64, ebit: f64) -> f64 {
30 if ebit <= 0.0 { f64::INFINITY } else { enterprise_value / ebit }
31}
32
33pub fn dividend_yield(dividend_per_share: f64, price: f64) -> f64 {
35 if price <= 0.0 { 0.0 } else { dividend_per_share / price }
36}
37
38#[cfg(test)]
39mod tests {
40 use super::*;
41 #[test]
42 fn pe_basic() { assert!((price_to_earnings(100.0, 5.0) - 20.0).abs() < 1e-9); }
43 #[test]
44 fn pe_zero_eps_is_inf() { assert!(price_to_earnings(100.0, 0.0).is_infinite()); }
45 #[test]
46 fn earnings_yield_reciprocal() {
47 let pe = price_to_earnings(100.0, 5.0);
48 let ey = earnings_yield(5.0, 100.0);
49 assert!((pe * ey - 1.0).abs() < 1e-9);
50 }
51 #[test]
52 fn pb_basic() { assert!((price_to_book(50.0, 25.0) - 2.0).abs() < 1e-9); }
53 #[test]
54 fn div_yield_pct() { assert!((dividend_yield(4.0, 100.0) - 0.04).abs() < 1e-9); }
55 #[test]
56 fn ev_ebit() { assert!((ev_to_ebit(1_000_000.0, 100_000.0) - 10.0).abs() < 1e-9); }
57}