Derive live bond burden from owned slots
This commit is contained in:
parent
3d31b0b65e
commit
ec734c5d92
5 changed files with 49 additions and 1 deletions
|
|
@ -136,6 +136,8 @@ pub struct RuntimeCompanyAnnualFinanceState {
|
|||
pub largest_live_bond_principal: Option<u32>,
|
||||
#[serde(default)]
|
||||
pub highest_coupon_live_bond_principal: Option<u32>,
|
||||
#[serde(default)]
|
||||
pub live_bond_coupon_burden_total: Option<i64>,
|
||||
pub assigned_share_pool: u32,
|
||||
pub unassigned_share_pool: u32,
|
||||
#[serde(default)]
|
||||
|
|
@ -331,6 +333,8 @@ pub struct RuntimeCompanyAnnualBondPolicyState {
|
|||
#[serde(default)]
|
||||
pub next_live_bond_maturity_year: Option<u32>,
|
||||
#[serde(default)]
|
||||
pub live_bond_coupon_burden_total: Option<i64>,
|
||||
#[serde(default)]
|
||||
pub current_cash: Option<i64>,
|
||||
#[serde(default)]
|
||||
pub cash_after_full_repayment: Option<i64>,
|
||||
|
|
@ -3104,6 +3108,24 @@ pub fn runtime_company_average_live_bond_coupon(
|
|||
Some(weighted_coupon_sum / total_principal as f64)
|
||||
}
|
||||
|
||||
pub fn runtime_company_live_bond_coupon_burden_total(
|
||||
state: &RuntimeState,
|
||||
company_id: u32,
|
||||
) -> Option<i64> {
|
||||
let market_state = state.service_state.company_market_state.get(&company_id)?;
|
||||
let mut total = 0i64;
|
||||
for slot in &market_state.live_bond_slots {
|
||||
let coupon_rate = f32::from_bits(slot.coupon_rate_raw_u32) as f64;
|
||||
if !coupon_rate.is_finite() {
|
||||
continue;
|
||||
}
|
||||
let coupon_burden =
|
||||
runtime_round_f64_to_i64((slot.principal as f64) * coupon_rate).unwrap_or(0);
|
||||
total = total.checked_add(coupon_burden)?;
|
||||
}
|
||||
Some(total)
|
||||
}
|
||||
|
||||
pub fn runtime_company_bond_interest_rate_quote_f64(
|
||||
state: &RuntimeState,
|
||||
company_id: u32,
|
||||
|
|
@ -3287,6 +3309,7 @@ pub fn runtime_company_annual_bond_policy_state(
|
|||
matured_live_bond_count,
|
||||
matured_live_bond_principal_total,
|
||||
next_live_bond_maturity_year,
|
||||
live_bond_coupon_burden_total: annual_finance_state.live_bond_coupon_burden_total,
|
||||
current_cash,
|
||||
cash_after_full_repayment,
|
||||
issue_cash_floor,
|
||||
|
|
@ -4037,6 +4060,9 @@ pub fn runtime_company_annual_finance_state(
|
|||
bond_count: market_state.bond_count,
|
||||
largest_live_bond_principal: market_state.largest_live_bond_principal,
|
||||
highest_coupon_live_bond_principal: market_state.highest_coupon_live_bond_principal,
|
||||
live_bond_coupon_burden_total: runtime_company_live_bond_coupon_burden_total(
|
||||
state, company_id,
|
||||
),
|
||||
assigned_share_pool,
|
||||
unassigned_share_pool,
|
||||
cached_share_price: rounded_cached_share_price_i64(market_state.cached_share_price_raw_u32),
|
||||
|
|
@ -7421,6 +7447,10 @@ mod tests {
|
|||
let average_live_bond_coupon =
|
||||
runtime_company_average_live_bond_coupon(&state, 7).expect("average coupon");
|
||||
assert!((average_live_bond_coupon - 0.05).abs() < 1e-6);
|
||||
assert_eq!(
|
||||
annual_finance_state.live_bond_coupon_burden_total,
|
||||
Some(5_000)
|
||||
);
|
||||
assert_eq!(runtime_world_prime_rate_baseline(&state), Some(5.0));
|
||||
assert_eq!(
|
||||
runtime_world_issue_opinion_term_sum_raw(
|
||||
|
|
@ -7801,6 +7831,7 @@ mod tests {
|
|||
bond_count: 3,
|
||||
largest_live_bond_principal: Some(650_000),
|
||||
highest_coupon_live_bond_principal: Some(500_000),
|
||||
live_bond_coupon_burden_total: Some(0),
|
||||
assigned_share_pool: 15_500,
|
||||
unassigned_share_pool: 4_500,
|
||||
cached_share_price: Some(40),
|
||||
|
|
@ -8308,6 +8339,7 @@ mod tests {
|
|||
assert_eq!(bond_state.matured_live_bond_count, Some(0));
|
||||
assert_eq!(bond_state.matured_live_bond_principal_total, Some(0));
|
||||
assert_eq!(bond_state.next_live_bond_maturity_year, None);
|
||||
assert_eq!(bond_state.live_bond_coupon_burden_total, Some(30_000));
|
||||
assert_eq!(bond_state.current_cash, Some(-400_000));
|
||||
assert_eq!(bond_state.cash_after_full_repayment, Some(-750_000));
|
||||
assert_eq!(bond_state.issue_cash_floor, Some(-30_000));
|
||||
|
|
|
|||
|
|
@ -122,6 +122,7 @@ pub struct RuntimeSummary {
|
|||
pub selected_company_annual_bond_matured_live_bond_count: Option<u32>,
|
||||
pub selected_company_annual_bond_matured_live_bond_principal_total: Option<u32>,
|
||||
pub selected_company_annual_bond_next_live_bond_maturity_year: Option<u32>,
|
||||
pub selected_company_annual_bond_live_bond_coupon_burden_total: Option<i64>,
|
||||
pub selected_company_annual_bond_current_cash: Option<i64>,
|
||||
pub selected_company_annual_bond_cash_after_full_repayment: Option<i64>,
|
||||
pub selected_company_annual_bond_issue_cash_floor: Option<i64>,
|
||||
|
|
@ -592,6 +593,10 @@ impl RuntimeSummary {
|
|||
selected_company_annual_bond_state
|
||||
.as_ref()
|
||||
.and_then(|bond_state| bond_state.next_live_bond_maturity_year),
|
||||
selected_company_annual_bond_live_bond_coupon_burden_total:
|
||||
selected_company_annual_bond_state
|
||||
.as_ref()
|
||||
.and_then(|bond_state| bond_state.live_bond_coupon_burden_total),
|
||||
selected_company_annual_bond_current_cash: selected_company_annual_bond_state
|
||||
.as_ref()
|
||||
.and_then(|bond_state| bond_state.current_cash),
|
||||
|
|
@ -3215,6 +3220,10 @@ mod tests {
|
|||
summary.selected_company_annual_bond_next_live_bond_maturity_year,
|
||||
None
|
||||
);
|
||||
assert_eq!(
|
||||
summary.selected_company_annual_bond_live_bond_coupon_burden_total,
|
||||
Some(30_000)
|
||||
);
|
||||
assert_eq!(
|
||||
summary.selected_company_annual_bond_current_cash,
|
||||
Some(-400_000)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue