use super::funejson::Value; use super::math_round_div::round_div; use super::money_amount::{assert_same_currency, money_from_value, Money}; /// Loss, expense and combined ratios against earned premium, in basis points. /// /// The combined ratio is worked from claims plus expenses, rounded once, not /// by adding the two rounded ratios, so it can differ from their sum by one /// basis point: 1.00 and 1.00 on 3.00 are 33.33% each but 66.67% together. /// /// # Panics /// Panics on mixed currencies or an earned premium that is not positive. pub fn loss_ratios(earned_premium: &Money, incurred_claims: &Money, expenses: &Money, mode: &str) -> LossRatios { assert_same_currency(earned_premium, incurred_claims); assert_same_currency(earned_premium, expenses); if earned_premium.minor <= 0 { panic!("earnedPremium must be more than zero, received {}", earned_premium.minor); } let p = earned_premium.minor; LossRatios { loss_ratio_basis_points: round_div(incurred_claims.minor * 10000, p, mode), expense_ratio_basis_points: round_div(expenses.minor * 10000, p, mode), combined_ratio_basis_points: round_div((incurred_claims.minor + expenses.minor) * 10000, p, mode), } } pub fn loss_ratios_to_value(r: &LossRatios) -> Value { Value::obj(vec![ ("lossRatioBasisPoints", Value::Int(r.loss_ratio_basis_points)), ("expenseRatioBasisPoints", Value::Int(r.expense_ratio_basis_points)), ("combinedRatioBasisPoints", Value::Int(r.combined_ratio_basis_points)), ]) } pub fn fune_vector(args: &[Value]) -> Value { loss_ratios_to_value(&loss_ratios( &money_from_value(&args[0]), &money_from_value(&args[1]), &money_from_value(&args[2]), args[3].as_str(), )) }