Carry bond maturity through runtime state
This commit is contained in:
parent
b87216a556
commit
3d31b0b65e
7 changed files with 133 additions and 1 deletions
|
|
@ -109,6 +109,9 @@ the shellless creditor-pressure-bankruptcy, deep-distress-bankruptcy, dividend-a
|
||||||
stock-repurchase, stock-issue, and bond-issue branches by mutating owned company activity,
|
stock-repurchase, stock-issue, and bond-issue branches by mutating owned company activity,
|
||||||
dividend, company stat-post, outstanding-share, issue-calendar, and live bond-slot state instead
|
dividend, company stat-post, outstanding-share, issue-calendar, and live bond-slot state instead
|
||||||
of stopping at reader-only diagnostics.
|
of stopping at reader-only diagnostics.
|
||||||
|
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
|
||||||
|
shellless repayment and bond-burden simulation instead of another round of raw-slot guessing.
|
||||||
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.
|
||||||
|
|
|
||||||
|
|
@ -122,6 +122,8 @@ pub struct RuntimeCompanyMarketState {
|
||||||
pub struct RuntimeCompanyBondSlot {
|
pub struct RuntimeCompanyBondSlot {
|
||||||
pub slot_index: u32,
|
pub slot_index: u32,
|
||||||
pub principal: u32,
|
pub principal: u32,
|
||||||
|
#[serde(default)]
|
||||||
|
pub maturity_year: u32,
|
||||||
pub coupon_rate_raw_u32: u32,
|
pub coupon_rate_raw_u32: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -323,6 +325,12 @@ pub struct RuntimeCompanyAnnualBondPolicyState {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub live_bond_principal_total: Option<u32>,
|
pub live_bond_principal_total: Option<u32>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
pub matured_live_bond_count: Option<u32>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub matured_live_bond_principal_total: Option<u32>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub next_live_bond_maturity_year: Option<u32>,
|
||||||
|
#[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>,
|
||||||
|
|
@ -2353,6 +2361,49 @@ fn runtime_company_total_live_bond_principal(state: &RuntimeState, company_id: u
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn runtime_company_matured_live_bond_count(
|
||||||
|
state: &RuntimeState,
|
||||||
|
company_id: u32,
|
||||||
|
current_year_word: u32,
|
||||||
|
) -> Option<u32> {
|
||||||
|
let market_state = state.service_state.company_market_state.get(&company_id)?;
|
||||||
|
Some(
|
||||||
|
market_state
|
||||||
|
.live_bond_slots
|
||||||
|
.iter()
|
||||||
|
.filter(|slot| slot.maturity_year != 0 && slot.maturity_year <= current_year_word)
|
||||||
|
.count() as u32,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn runtime_company_matured_live_bond_principal_total(
|
||||||
|
state: &RuntimeState,
|
||||||
|
company_id: u32,
|
||||||
|
current_year_word: u32,
|
||||||
|
) -> Option<u32> {
|
||||||
|
let market_state = state.service_state.company_market_state.get(&company_id)?;
|
||||||
|
Some(
|
||||||
|
market_state
|
||||||
|
.live_bond_slots
|
||||||
|
.iter()
|
||||||
|
.filter(|slot| slot.maturity_year != 0 && slot.maturity_year <= current_year_word)
|
||||||
|
.map(|slot| slot.principal)
|
||||||
|
.sum(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn runtime_company_next_live_bond_maturity_year(
|
||||||
|
state: &RuntimeState,
|
||||||
|
company_id: u32,
|
||||||
|
) -> Option<u32> {
|
||||||
|
let market_state = state.service_state.company_market_state.get(&company_id)?;
|
||||||
|
market_state
|
||||||
|
.live_bond_slots
|
||||||
|
.iter()
|
||||||
|
.filter_map(|slot| (slot.maturity_year != 0).then_some(slot.maturity_year))
|
||||||
|
.min()
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn runtime_company_support_adjusted_share_price_scalar_with_pressure_f64(
|
pub(crate) fn runtime_company_support_adjusted_share_price_scalar_with_pressure_f64(
|
||||||
state: &RuntimeState,
|
state: &RuntimeState,
|
||||||
company_id: u32,
|
company_id: u32,
|
||||||
|
|
@ -3184,6 +3235,11 @@ pub fn runtime_company_annual_bond_policy_state(
|
||||||
const ISSUE_YEARS_TO_MATURITY: u32 = 30;
|
const ISSUE_YEARS_TO_MATURITY: u32 = 30;
|
||||||
|
|
||||||
let annual_finance_state = runtime_company_annual_finance_state(state, company_id)?;
|
let annual_finance_state = runtime_company_annual_finance_state(state, company_id)?;
|
||||||
|
let current_year_word = state
|
||||||
|
.world_restore
|
||||||
|
.packed_year_word_raw_u16
|
||||||
|
.map(u32::from)
|
||||||
|
.unwrap_or(state.calendar.year);
|
||||||
let current_cash = runtime_company_control_transfer_stat_value_f64(
|
let current_cash = runtime_company_control_transfer_stat_value_f64(
|
||||||
state,
|
state,
|
||||||
company_id,
|
company_id,
|
||||||
|
|
@ -3191,6 +3247,12 @@ pub fn runtime_company_annual_bond_policy_state(
|
||||||
)
|
)
|
||||||
.and_then(runtime_round_f64_to_i64);
|
.and_then(runtime_round_f64_to_i64);
|
||||||
let live_bond_principal_total = runtime_company_total_live_bond_principal(state, company_id);
|
let live_bond_principal_total = runtime_company_total_live_bond_principal(state, company_id);
|
||||||
|
let matured_live_bond_count =
|
||||||
|
runtime_company_matured_live_bond_count(state, company_id, current_year_word);
|
||||||
|
let matured_live_bond_principal_total =
|
||||||
|
runtime_company_matured_live_bond_principal_total(state, company_id, current_year_word);
|
||||||
|
let next_live_bond_maturity_year =
|
||||||
|
runtime_company_next_live_bond_maturity_year(state, company_id);
|
||||||
let cash_after_full_repayment = current_cash
|
let cash_after_full_repayment = current_cash
|
||||||
.zip(live_bond_principal_total)
|
.zip(live_bond_principal_total)
|
||||||
.map(|(cash, principal)| cash - i64::from(principal));
|
.map(|(cash, principal)| cash - i64::from(principal));
|
||||||
|
|
@ -3222,6 +3284,9 @@ pub fn runtime_company_annual_bond_policy_state(
|
||||||
linked_transit_latch: annual_finance_state.linked_transit_latch,
|
linked_transit_latch: annual_finance_state.linked_transit_latch,
|
||||||
live_bond_count: Some(annual_finance_state.bond_count),
|
live_bond_count: Some(annual_finance_state.bond_count),
|
||||||
live_bond_principal_total,
|
live_bond_principal_total,
|
||||||
|
matured_live_bond_count,
|
||||||
|
matured_live_bond_principal_total,
|
||||||
|
next_live_bond_maturity_year,
|
||||||
current_cash,
|
current_cash,
|
||||||
cash_after_full_repayment,
|
cash_after_full_repayment,
|
||||||
issue_cash_floor,
|
issue_cash_floor,
|
||||||
|
|
@ -7315,6 +7380,7 @@ mod tests {
|
||||||
live_bond_slots: vec![RuntimeCompanyBondSlot {
|
live_bond_slots: vec![RuntimeCompanyBondSlot {
|
||||||
slot_index: 0,
|
slot_index: 0,
|
||||||
principal: 100_000,
|
principal: 100_000,
|
||||||
|
maturity_year: 0,
|
||||||
coupon_rate_raw_u32: 0.05f32.to_bits(),
|
coupon_rate_raw_u32: 0.05f32.to_bits(),
|
||||||
}],
|
}],
|
||||||
..RuntimeCompanyMarketState::default()
|
..RuntimeCompanyMarketState::default()
|
||||||
|
|
@ -7459,11 +7525,13 @@ mod tests {
|
||||||
RuntimeCompanyBondSlot {
|
RuntimeCompanyBondSlot {
|
||||||
slot_index: 0,
|
slot_index: 0,
|
||||||
principal: 100_000,
|
principal: 100_000,
|
||||||
|
maturity_year: 0,
|
||||||
coupon_rate_raw_u32: 0.04f32.to_bits(),
|
coupon_rate_raw_u32: 0.04f32.to_bits(),
|
||||||
},
|
},
|
||||||
RuntimeCompanyBondSlot {
|
RuntimeCompanyBondSlot {
|
||||||
slot_index: 1,
|
slot_index: 1,
|
||||||
principal: 300_000,
|
principal: 300_000,
|
||||||
|
maturity_year: 0,
|
||||||
coupon_rate_raw_u32: 0.08f32.to_bits(),
|
coupon_rate_raw_u32: 0.08f32.to_bits(),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
@ -8215,11 +8283,13 @@ mod tests {
|
||||||
RuntimeCompanyBondSlot {
|
RuntimeCompanyBondSlot {
|
||||||
slot_index: 0,
|
slot_index: 0,
|
||||||
principal: 200_000,
|
principal: 200_000,
|
||||||
|
maturity_year: 0,
|
||||||
coupon_rate_raw_u32: 0.09f32.to_bits(),
|
coupon_rate_raw_u32: 0.09f32.to_bits(),
|
||||||
},
|
},
|
||||||
RuntimeCompanyBondSlot {
|
RuntimeCompanyBondSlot {
|
||||||
slot_index: 1,
|
slot_index: 1,
|
||||||
principal: 150_000,
|
principal: 150_000,
|
||||||
|
maturity_year: 0,
|
||||||
coupon_rate_raw_u32: 0.08f32.to_bits(),
|
coupon_rate_raw_u32: 0.08f32.to_bits(),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
@ -8235,6 +8305,9 @@ mod tests {
|
||||||
runtime_company_annual_bond_policy_state(&state, 11).expect("bond policy state");
|
runtime_company_annual_bond_policy_state(&state, 11).expect("bond policy state");
|
||||||
assert_eq!(bond_state.live_bond_count, Some(2));
|
assert_eq!(bond_state.live_bond_count, Some(2));
|
||||||
assert_eq!(bond_state.live_bond_principal_total, Some(350_000));
|
assert_eq!(bond_state.live_bond_principal_total, Some(350_000));
|
||||||
|
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.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));
|
||||||
|
|
@ -8356,11 +8429,13 @@ mod tests {
|
||||||
RuntimeCompanyBondSlot {
|
RuntimeCompanyBondSlot {
|
||||||
slot_index: 0,
|
slot_index: 0,
|
||||||
principal: 300_000,
|
principal: 300_000,
|
||||||
|
maturity_year: 0,
|
||||||
coupon_rate_raw_u32: 0.11f32.to_bits(),
|
coupon_rate_raw_u32: 0.11f32.to_bits(),
|
||||||
},
|
},
|
||||||
RuntimeCompanyBondSlot {
|
RuntimeCompanyBondSlot {
|
||||||
slot_index: 1,
|
slot_index: 1,
|
||||||
principal: 200_000,
|
principal: 200_000,
|
||||||
|
maturity_year: 0,
|
||||||
coupon_rate_raw_u32: 0.07f32.to_bits(),
|
coupon_rate_raw_u32: 0.07f32.to_bits(),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -4180,6 +4180,7 @@ fn parse_save_company_live_bond_slots(
|
||||||
if principal <= 0 {
|
if principal <= 0 {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
let maturity_year = read_u32_at(bytes, slot_offset + 4)?;
|
||||||
let coupon_rate_raw_u32 = read_u32_at(bytes, slot_offset + 8)?;
|
let coupon_rate_raw_u32 = read_u32_at(bytes, slot_offset + 8)?;
|
||||||
let coupon_rate = f32::from_bits(coupon_rate_raw_u32);
|
let coupon_rate = f32::from_bits(coupon_rate_raw_u32);
|
||||||
if !coupon_rate.is_finite() {
|
if !coupon_rate.is_finite() {
|
||||||
|
|
@ -4188,6 +4189,7 @@ fn parse_save_company_live_bond_slots(
|
||||||
slots.push(crate::RuntimeCompanyBondSlot {
|
slots.push(crate::RuntimeCompanyBondSlot {
|
||||||
slot_index: slot_index as u32,
|
slot_index: slot_index as u32,
|
||||||
principal: principal as u32,
|
principal: principal as u32,
|
||||||
|
maturity_year,
|
||||||
coupon_rate_raw_u32,
|
coupon_rate_raw_u32,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -16663,6 +16665,7 @@ mod tests {
|
||||||
assert_eq!(market_state.outstanding_shares, 20_000);
|
assert_eq!(market_state.outstanding_shares, 20_000);
|
||||||
assert_eq!(market_state.live_bond_slots.len(), 2);
|
assert_eq!(market_state.live_bond_slots.len(), 2);
|
||||||
assert_eq!(market_state.live_bond_slots[0].principal, 900_000);
|
assert_eq!(market_state.live_bond_slots[0].principal, 900_000);
|
||||||
|
assert_eq!(market_state.live_bond_slots[0].maturity_year, 1894);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
market_state.live_bond_slots[1].coupon_rate_raw_u32,
|
market_state.live_bond_slots[1].coupon_rate_raw_u32,
|
||||||
0.12f32.to_bits()
|
0.12f32.to_bits()
|
||||||
|
|
|
||||||
|
|
@ -499,6 +499,14 @@ fn service_company_annual_finance_policy(
|
||||||
let Some(years_to_maturity) = bond_state.proposed_issue_years_to_maturity else {
|
let Some(years_to_maturity) = bond_state.proposed_issue_years_to_maturity else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
let Some(maturity_year) = state
|
||||||
|
.world_restore
|
||||||
|
.packed_year_word_raw_u16
|
||||||
|
.map(u32::from)
|
||||||
|
.and_then(|year| year.checked_add(years_to_maturity))
|
||||||
|
else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
let Some(quote_rate) = runtime_company_bond_interest_rate_quote_f64(
|
let Some(quote_rate) = runtime_company_bond_interest_rate_quote_f64(
|
||||||
state,
|
state,
|
||||||
company_id,
|
company_id,
|
||||||
|
|
@ -544,6 +552,7 @@ fn service_company_annual_finance_policy(
|
||||||
market_state.live_bond_slots.push(crate::RuntimeCompanyBondSlot {
|
market_state.live_bond_slots.push(crate::RuntimeCompanyBondSlot {
|
||||||
slot_index,
|
slot_index,
|
||||||
principal,
|
principal,
|
||||||
|
maturity_year,
|
||||||
coupon_rate_raw_u32: (quote_rate as f32).to_bits(),
|
coupon_rate_raw_u32: (quote_rate as f32).to_bits(),
|
||||||
});
|
});
|
||||||
market_state.bond_count = market_state.bond_count.saturating_add(1);
|
market_state.bond_count = market_state.bond_count.saturating_add(1);
|
||||||
|
|
@ -2671,11 +2680,13 @@ mod tests {
|
||||||
crate::RuntimeCompanyBondSlot {
|
crate::RuntimeCompanyBondSlot {
|
||||||
slot_index: 0,
|
slot_index: 0,
|
||||||
principal: 300_000,
|
principal: 300_000,
|
||||||
|
maturity_year: 0,
|
||||||
coupon_rate_raw_u32: 0.11f32.to_bits(),
|
coupon_rate_raw_u32: 0.11f32.to_bits(),
|
||||||
},
|
},
|
||||||
crate::RuntimeCompanyBondSlot {
|
crate::RuntimeCompanyBondSlot {
|
||||||
slot_index: 1,
|
slot_index: 1,
|
||||||
principal: 200_000,
|
principal: 200_000,
|
||||||
|
maturity_year: 0,
|
||||||
coupon_rate_raw_u32: 0.07f32.to_bits(),
|
coupon_rate_raw_u32: 0.07f32.to_bits(),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
@ -2985,6 +2996,7 @@ mod tests {
|
||||||
vec![crate::RuntimeCompanyBondSlot {
|
vec![crate::RuntimeCompanyBondSlot {
|
||||||
slot_index: 0,
|
slot_index: 0,
|
||||||
principal: 500_000,
|
principal: 500_000,
|
||||||
|
maturity_year: 1875,
|
||||||
coupon_rate_raw_u32: 0.09f32.to_bits(),
|
coupon_rate_raw_u32: 0.09f32.to_bits(),
|
||||||
}]
|
}]
|
||||||
);
|
);
|
||||||
|
|
@ -3114,6 +3126,7 @@ mod tests {
|
||||||
live_bond_slots: vec![crate::RuntimeCompanyBondSlot {
|
live_bond_slots: vec![crate::RuntimeCompanyBondSlot {
|
||||||
slot_index: 0,
|
slot_index: 0,
|
||||||
principal: 500_000,
|
principal: 500_000,
|
||||||
|
maturity_year: 0,
|
||||||
coupon_rate_raw_u32: 0.08f32.to_bits(),
|
coupon_rate_raw_u32: 0.08f32.to_bits(),
|
||||||
}],
|
}],
|
||||||
..crate::RuntimeCompanyMarketState::default()
|
..crate::RuntimeCompanyMarketState::default()
|
||||||
|
|
@ -3268,6 +3281,7 @@ mod tests {
|
||||||
live_bond_slots: vec![crate::RuntimeCompanyBondSlot {
|
live_bond_slots: vec![crate::RuntimeCompanyBondSlot {
|
||||||
slot_index: 0,
|
slot_index: 0,
|
||||||
principal: 250_000,
|
principal: 250_000,
|
||||||
|
maturity_year: 0,
|
||||||
coupon_rate_raw_u32: 0.07f32.to_bits(),
|
coupon_rate_raw_u32: 0.07f32.to_bits(),
|
||||||
}],
|
}],
|
||||||
..crate::RuntimeCompanyMarketState::default()
|
..crate::RuntimeCompanyMarketState::default()
|
||||||
|
|
@ -5808,6 +5822,7 @@ mod tests {
|
||||||
live_bond_slots: vec![crate::RuntimeCompanyBondSlot {
|
live_bond_slots: vec![crate::RuntimeCompanyBondSlot {
|
||||||
slot_index: 0,
|
slot_index: 0,
|
||||||
principal: 100_000,
|
principal: 100_000,
|
||||||
|
maturity_year: 0,
|
||||||
coupon_rate_raw_u32: 0.05f32.to_bits(),
|
coupon_rate_raw_u32: 0.05f32.to_bits(),
|
||||||
}],
|
}],
|
||||||
..crate::RuntimeCompanyMarketState::default()
|
..crate::RuntimeCompanyMarketState::default()
|
||||||
|
|
|
||||||
|
|
@ -119,6 +119,9 @@ pub struct RuntimeSummary {
|
||||||
pub selected_company_annual_bond_linked_transit_latch: Option<bool>,
|
pub selected_company_annual_bond_linked_transit_latch: Option<bool>,
|
||||||
pub selected_company_annual_bond_live_bond_count: Option<u8>,
|
pub selected_company_annual_bond_live_bond_count: Option<u8>,
|
||||||
pub selected_company_annual_bond_live_bond_principal_total: Option<u32>,
|
pub selected_company_annual_bond_live_bond_principal_total: 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_next_live_bond_maturity_year: Option<u32>,
|
||||||
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>,
|
||||||
|
|
@ -577,6 +580,18 @@ impl RuntimeSummary {
|
||||||
selected_company_annual_bond_state
|
selected_company_annual_bond_state
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|bond_state| bond_state.live_bond_principal_total),
|
.and_then(|bond_state| bond_state.live_bond_principal_total),
|
||||||
|
selected_company_annual_bond_matured_live_bond_count:
|
||||||
|
selected_company_annual_bond_state
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|bond_state| bond_state.matured_live_bond_count),
|
||||||
|
selected_company_annual_bond_matured_live_bond_principal_total:
|
||||||
|
selected_company_annual_bond_state
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|bond_state| bond_state.matured_live_bond_principal_total),
|
||||||
|
selected_company_annual_bond_next_live_bond_maturity_year:
|
||||||
|
selected_company_annual_bond_state
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|bond_state| bond_state.next_live_bond_maturity_year),
|
||||||
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),
|
||||||
|
|
@ -3157,11 +3172,13 @@ mod tests {
|
||||||
crate::RuntimeCompanyBondSlot {
|
crate::RuntimeCompanyBondSlot {
|
||||||
slot_index: 0,
|
slot_index: 0,
|
||||||
principal: 200_000,
|
principal: 200_000,
|
||||||
|
maturity_year: 0,
|
||||||
coupon_rate_raw_u32: 0.09f32.to_bits(),
|
coupon_rate_raw_u32: 0.09f32.to_bits(),
|
||||||
},
|
},
|
||||||
crate::RuntimeCompanyBondSlot {
|
crate::RuntimeCompanyBondSlot {
|
||||||
slot_index: 1,
|
slot_index: 1,
|
||||||
principal: 150_000,
|
principal: 150_000,
|
||||||
|
maturity_year: 0,
|
||||||
coupon_rate_raw_u32: 0.08f32.to_bits(),
|
coupon_rate_raw_u32: 0.08f32.to_bits(),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
@ -3186,6 +3203,18 @@ mod tests {
|
||||||
summary.selected_company_annual_bond_live_bond_principal_total,
|
summary.selected_company_annual_bond_live_bond_principal_total,
|
||||||
Some(350_000)
|
Some(350_000)
|
||||||
);
|
);
|
||||||
|
assert_eq!(
|
||||||
|
summary.selected_company_annual_bond_matured_live_bond_count,
|
||||||
|
Some(0)
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
summary.selected_company_annual_bond_matured_live_bond_principal_total,
|
||||||
|
Some(0)
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
summary.selected_company_annual_bond_next_live_bond_maturity_year,
|
||||||
|
None
|
||||||
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
summary.selected_company_annual_bond_current_cash,
|
summary.selected_company_annual_bond_current_cash,
|
||||||
Some(-400_000)
|
Some(-400_000)
|
||||||
|
|
@ -3329,11 +3358,13 @@ mod tests {
|
||||||
crate::RuntimeCompanyBondSlot {
|
crate::RuntimeCompanyBondSlot {
|
||||||
slot_index: 0,
|
slot_index: 0,
|
||||||
principal: 300_000,
|
principal: 300_000,
|
||||||
|
maturity_year: 0,
|
||||||
coupon_rate_raw_u32: 0.11f32.to_bits(),
|
coupon_rate_raw_u32: 0.11f32.to_bits(),
|
||||||
},
|
},
|
||||||
crate::RuntimeCompanyBondSlot {
|
crate::RuntimeCompanyBondSlot {
|
||||||
slot_index: 1,
|
slot_index: 1,
|
||||||
principal: 200_000,
|
principal: 200_000,
|
||||||
|
maturity_year: 0,
|
||||||
coupon_rate_raw_u32: 0.07f32.to_bits(),
|
coupon_rate_raw_u32: 0.07f32.to_bits(),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -150,7 +150,9 @@ The highest-value next passes are now:
|
||||||
stock-repurchase gate headlessly as another pure reader; periodic boundary service now also
|
stock-repurchase gate headlessly as another pure reader; periodic boundary service now also
|
||||||
chooses one annual-finance action per active company and already commits the shellless
|
chooses one annual-finance action per active company and already commits the shellless
|
||||||
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
|
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
|
||||||
|
next seam for shellless repayment work
|
||||||
- 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
|
||||||
|
|
|
||||||
|
|
@ -247,6 +247,9 @@ the runtime selects one annual-finance action per active company and already com
|
||||||
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 directly into owned dividend, company stat-post,
|
stock-issue, and bond-issue branches directly into owned dividend, company stat-post,
|
||||||
outstanding-share, issue-calendar, live bond-slot, and company activity state.
|
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,
|
||||||
|
runtime state, and annual bond summaries, which is the right next base for shellless repayment and
|
||||||
|
bond-service simulation.
|
||||||
|
|
||||||
## Why This Boundary
|
## Why This Boundary
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue