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
|
|
@ -112,6 +112,9 @@ of stopping at reader-only diagnostics.
|
||||||
The same save-native live bond-slot surface now also carries per-slot maturity years all the way
|
The same save-native live bond-slot surface now also carries per-slot maturity years all the way
|
||||||
through runtime summaries and annual bond policy state, which is the next owner seam needed for
|
through runtime summaries and annual bond policy state, which is the next owner seam needed for
|
||||||
shellless repayment and bond-burden simulation instead of another round of raw-slot guessing.
|
shellless repayment and bond-burden simulation instead of another round of raw-slot guessing.
|
||||||
|
That same seam now also derives the current live coupon burden directly from owned bond slots, so
|
||||||
|
later finance service work can consume a runtime reader instead of recomputing from scattered raw
|
||||||
|
fields.
|
||||||
The same seam now also carries the fixed-world building-density growth setting plus the linked
|
The same seam now also carries the fixed-world building-density growth setting plus the linked
|
||||||
chairman personality byte, which is enough to run the annual stock-repurchase gate as another
|
chairman personality byte, which is enough to run the annual stock-repurchase gate as another
|
||||||
pure reader over owned save-native state instead of a guessed finance-side approximation.
|
pure reader over owned save-native state instead of a guessed finance-side approximation.
|
||||||
|
|
|
||||||
|
|
@ -136,6 +136,8 @@ pub struct RuntimeCompanyAnnualFinanceState {
|
||||||
pub largest_live_bond_principal: Option<u32>,
|
pub largest_live_bond_principal: Option<u32>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub highest_coupon_live_bond_principal: Option<u32>,
|
pub highest_coupon_live_bond_principal: Option<u32>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub live_bond_coupon_burden_total: Option<i64>,
|
||||||
pub assigned_share_pool: u32,
|
pub assigned_share_pool: u32,
|
||||||
pub unassigned_share_pool: u32,
|
pub unassigned_share_pool: u32,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
|
@ -331,6 +333,8 @@ pub struct RuntimeCompanyAnnualBondPolicyState {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub next_live_bond_maturity_year: Option<u32>,
|
pub next_live_bond_maturity_year: Option<u32>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
pub live_bond_coupon_burden_total: Option<i64>,
|
||||||
|
#[serde(default)]
|
||||||
pub current_cash: Option<i64>,
|
pub current_cash: Option<i64>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub cash_after_full_repayment: Option<i64>,
|
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)
|
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(
|
pub fn runtime_company_bond_interest_rate_quote_f64(
|
||||||
state: &RuntimeState,
|
state: &RuntimeState,
|
||||||
company_id: u32,
|
company_id: u32,
|
||||||
|
|
@ -3287,6 +3309,7 @@ pub fn runtime_company_annual_bond_policy_state(
|
||||||
matured_live_bond_count,
|
matured_live_bond_count,
|
||||||
matured_live_bond_principal_total,
|
matured_live_bond_principal_total,
|
||||||
next_live_bond_maturity_year,
|
next_live_bond_maturity_year,
|
||||||
|
live_bond_coupon_burden_total: annual_finance_state.live_bond_coupon_burden_total,
|
||||||
current_cash,
|
current_cash,
|
||||||
cash_after_full_repayment,
|
cash_after_full_repayment,
|
||||||
issue_cash_floor,
|
issue_cash_floor,
|
||||||
|
|
@ -4037,6 +4060,9 @@ pub fn runtime_company_annual_finance_state(
|
||||||
bond_count: market_state.bond_count,
|
bond_count: market_state.bond_count,
|
||||||
largest_live_bond_principal: market_state.largest_live_bond_principal,
|
largest_live_bond_principal: market_state.largest_live_bond_principal,
|
||||||
highest_coupon_live_bond_principal: market_state.highest_coupon_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,
|
assigned_share_pool,
|
||||||
unassigned_share_pool,
|
unassigned_share_pool,
|
||||||
cached_share_price: rounded_cached_share_price_i64(market_state.cached_share_price_raw_u32),
|
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 =
|
let average_live_bond_coupon =
|
||||||
runtime_company_average_live_bond_coupon(&state, 7).expect("average coupon");
|
runtime_company_average_live_bond_coupon(&state, 7).expect("average coupon");
|
||||||
assert!((average_live_bond_coupon - 0.05).abs() < 1e-6);
|
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_prime_rate_baseline(&state), Some(5.0));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
runtime_world_issue_opinion_term_sum_raw(
|
runtime_world_issue_opinion_term_sum_raw(
|
||||||
|
|
@ -7801,6 +7831,7 @@ mod tests {
|
||||||
bond_count: 3,
|
bond_count: 3,
|
||||||
largest_live_bond_principal: Some(650_000),
|
largest_live_bond_principal: Some(650_000),
|
||||||
highest_coupon_live_bond_principal: Some(500_000),
|
highest_coupon_live_bond_principal: Some(500_000),
|
||||||
|
live_bond_coupon_burden_total: Some(0),
|
||||||
assigned_share_pool: 15_500,
|
assigned_share_pool: 15_500,
|
||||||
unassigned_share_pool: 4_500,
|
unassigned_share_pool: 4_500,
|
||||||
cached_share_price: Some(40),
|
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_count, Some(0));
|
||||||
assert_eq!(bond_state.matured_live_bond_principal_total, 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.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.current_cash, Some(-400_000));
|
||||||
assert_eq!(bond_state.cash_after_full_repayment, Some(-750_000));
|
assert_eq!(bond_state.cash_after_full_repayment, Some(-750_000));
|
||||||
assert_eq!(bond_state.issue_cash_floor, Some(-30_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_count: Option<u32>,
|
||||||
pub selected_company_annual_bond_matured_live_bond_principal_total: 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_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_current_cash: Option<i64>,
|
||||||
pub selected_company_annual_bond_cash_after_full_repayment: Option<i64>,
|
pub selected_company_annual_bond_cash_after_full_repayment: Option<i64>,
|
||||||
pub selected_company_annual_bond_issue_cash_floor: Option<i64>,
|
pub selected_company_annual_bond_issue_cash_floor: Option<i64>,
|
||||||
|
|
@ -592,6 +593,10 @@ impl RuntimeSummary {
|
||||||
selected_company_annual_bond_state
|
selected_company_annual_bond_state
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|bond_state| bond_state.next_live_bond_maturity_year),
|
.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
|
selected_company_annual_bond_current_cash: selected_company_annual_bond_state
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|bond_state| bond_state.current_cash),
|
.and_then(|bond_state| bond_state.current_cash),
|
||||||
|
|
@ -3215,6 +3220,10 @@ mod tests {
|
||||||
summary.selected_company_annual_bond_next_live_bond_maturity_year,
|
summary.selected_company_annual_bond_next_live_bond_maturity_year,
|
||||||
None
|
None
|
||||||
);
|
);
|
||||||
|
assert_eq!(
|
||||||
|
summary.selected_company_annual_bond_live_bond_coupon_burden_total,
|
||||||
|
Some(30_000)
|
||||||
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
summary.selected_company_annual_bond_current_cash,
|
summary.selected_company_annual_bond_current_cash,
|
||||||
Some(-400_000)
|
Some(-400_000)
|
||||||
|
|
|
||||||
|
|
@ -152,7 +152,8 @@ The highest-value next passes are now:
|
||||||
creditor-pressure-bankruptcy, deep-distress-bankruptcy, dividend-adjustment, stock-repurchase,
|
creditor-pressure-bankruptcy, deep-distress-bankruptcy, dividend-adjustment, stock-repurchase,
|
||||||
stock-issue, and bond-issue branches against owned runtime state; the same live bond-slot owner
|
stock-issue, and bond-issue branches against owned runtime state; the same live bond-slot owner
|
||||||
surface now also carries save-native maturity years into annual bond policy summaries as the
|
surface now also carries save-native maturity years into annual bond policy summaries as the
|
||||||
next seam for shellless repayment work
|
next seam for shellless repayment work, and now also derives the current live coupon burden
|
||||||
|
directly from owned bond slots
|
||||||
- the project rule on the remaining closure work is now explicit too: when one runtime-facing field
|
- the project rule on the remaining closure work is now explicit too: when one runtime-facing field
|
||||||
is still ambiguous, prefer rehosting the owning source state or real reader/setter family first
|
is still ambiguous, prefer rehosting the owning source state or real reader/setter family first
|
||||||
instead of guessing another derived leaf field from neighboring raw offsets
|
instead of guessing another derived leaf field from neighboring raw offsets
|
||||||
|
|
|
||||||
|
|
@ -250,6 +250,9 @@ outstanding-share, issue-calendar, live bond-slot, and company activity state.
|
||||||
The same owned live bond-slot surface now also carries maturity years through save import,
|
The same owned live bond-slot surface now also carries maturity years through save import,
|
||||||
runtime state, and annual bond summaries, which is the right next base for shellless repayment and
|
runtime state, and annual bond summaries, which is the right next base for shellless repayment and
|
||||||
bond-service simulation.
|
bond-service simulation.
|
||||||
|
That same owner seam now also derives live coupon burden totals directly from saved bond slots,
|
||||||
|
which gives later finance service work a bounded runtime reader instead of another synthetic
|
||||||
|
finance leaf.
|
||||||
|
|
||||||
## Why This Boundary
|
## Why This Boundary
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue