Rehost annual stock-capital issue branch
This commit is contained in:
parent
0658626a57
commit
d303ee994b
6 changed files with 789 additions and 39 deletions
|
|
@ -88,7 +88,9 @@ matches the stock-capital branch gate that requires at least two live bonds. The
|
|||
bond table now also contributes both the largest live bond principal and the chosen
|
||||
highest-coupon live bond principal into owned company market and annual-finance state, so the
|
||||
stock-capital approval ladder can extend one rehosted owner-state surface instead of hunting
|
||||
another isolated finance leaf. A checked-in
|
||||
another isolated finance leaf. The same bond-slot owner state now also exposes the highest live
|
||||
coupon rate, which is enough to run the stock-capital price-to-book approval ladder as another
|
||||
save-native runtime reader instead of a notes-only threshold table. A checked-in
|
||||
fixed-world finance-policy seam now also carries the raw stock, bond, bankruptcy, and dividend
|
||||
policy bytes from the `0x32c8` save block, and the first annual creditor-pressure branch now runs
|
||||
headlessly as a pure runtime reader over owned annual-finance state, support-adjusted share price,
|
||||
|
|
|
|||
|
|
@ -53,26 +53,27 @@ pub use runtime::{
|
|||
RuntimeCargoPriceTarget, RuntimeCargoProductionTarget, RuntimeChairmanMetric,
|
||||
RuntimeChairmanProfile, RuntimeChairmanTarget, RuntimeCompany,
|
||||
RuntimeCompanyAnnualCreditorPressureState, RuntimeCompanyAnnualDeepDistressState,
|
||||
RuntimeCompanyAnnualFinanceState, RuntimeCompanyAnnualStockRepurchaseState,
|
||||
RuntimeCompanyBondSlot, RuntimeCompanyConditionTestScope, RuntimeCompanyControllerKind,
|
||||
RuntimeCompanyMarketMetric, RuntimeCompanyMarketState, RuntimeCompanyMetric,
|
||||
RuntimeCompanyStatBandCandidate, RuntimeCompanyStatSelector, RuntimeCompanyTarget,
|
||||
RuntimeCompanyTerritoryAccess, RuntimeCompanyTerritoryTrackPieceCount, RuntimeCondition,
|
||||
RuntimeConditionComparator, RuntimeEffect, RuntimeEventRecord, RuntimeEventRecordTemplate,
|
||||
RuntimeLocomotiveCatalogEntry, RuntimePackedEventCollectionSummary,
|
||||
RuntimePackedEventCompactControlSummary, RuntimePackedEventConditionRowSummary,
|
||||
RuntimePackedEventGroupedEffectRowSummary, RuntimePackedEventNegativeSentinelScopeSummary,
|
||||
RuntimePackedEventRecordSummary, RuntimePackedEventTextBandSummary, RuntimePlayer,
|
||||
RuntimePlayerConditionTestScope, RuntimePlayerTarget, RuntimeSaveProfileState,
|
||||
RuntimeServiceState, RuntimeState, RuntimeTerritory, RuntimeTerritoryMetric,
|
||||
RuntimeTerritoryTarget, RuntimeTrackMetric, RuntimeTrackPieceCounts, RuntimeTrain,
|
||||
RuntimeWorldFinanceNeighborhoodCandidate, RuntimeWorldIssueState, RuntimeWorldRestoreState,
|
||||
RuntimeCompanyAnnualFinanceState, RuntimeCompanyAnnualStockIssueState,
|
||||
RuntimeCompanyAnnualStockRepurchaseState, RuntimeCompanyBondSlot,
|
||||
RuntimeCompanyConditionTestScope, RuntimeCompanyControllerKind, RuntimeCompanyMarketMetric,
|
||||
RuntimeCompanyMarketState, RuntimeCompanyMetric, RuntimeCompanyStatBandCandidate,
|
||||
RuntimeCompanyStatSelector, RuntimeCompanyTarget, RuntimeCompanyTerritoryAccess,
|
||||
RuntimeCompanyTerritoryTrackPieceCount, RuntimeCondition, RuntimeConditionComparator,
|
||||
RuntimeEffect, RuntimeEventRecord, RuntimeEventRecordTemplate, RuntimeLocomotiveCatalogEntry,
|
||||
RuntimePackedEventCollectionSummary, RuntimePackedEventCompactControlSummary,
|
||||
RuntimePackedEventConditionRowSummary, RuntimePackedEventGroupedEffectRowSummary,
|
||||
RuntimePackedEventNegativeSentinelScopeSummary, RuntimePackedEventRecordSummary,
|
||||
RuntimePackedEventTextBandSummary, RuntimePlayer, RuntimePlayerConditionTestScope,
|
||||
RuntimePlayerTarget, RuntimeSaveProfileState, RuntimeServiceState, RuntimeState,
|
||||
RuntimeTerritory, RuntimeTerritoryMetric, RuntimeTerritoryTarget, RuntimeTrackMetric,
|
||||
RuntimeTrackPieceCounts, RuntimeTrain, RuntimeWorldFinanceNeighborhoodCandidate,
|
||||
RuntimeWorldIssueState, RuntimeWorldRestoreState,
|
||||
runtime_company_annual_creditor_pressure_state, runtime_company_annual_deep_distress_state,
|
||||
runtime_company_annual_finance_state, runtime_company_annual_stock_repurchase_state,
|
||||
runtime_company_assigned_share_pool, runtime_company_average_live_bond_coupon,
|
||||
runtime_company_book_value_per_share, runtime_company_credit_rating,
|
||||
runtime_company_investor_confidence, runtime_company_management_attitude,
|
||||
runtime_company_market_value, runtime_company_prime_rate,
|
||||
runtime_company_annual_finance_state, runtime_company_annual_stock_issue_state,
|
||||
runtime_company_annual_stock_repurchase_state, runtime_company_assigned_share_pool,
|
||||
runtime_company_average_live_bond_coupon, runtime_company_book_value_per_share,
|
||||
runtime_company_credit_rating, runtime_company_investor_confidence,
|
||||
runtime_company_management_attitude, runtime_company_market_value, runtime_company_prime_rate,
|
||||
runtime_company_recent_per_share_subscore, runtime_company_stat_value,
|
||||
runtime_company_stat_value_f64, runtime_company_unassigned_share_pool,
|
||||
runtime_world_annual_finance_mode_active, runtime_world_bankruptcy_allowed,
|
||||
|
|
|
|||
|
|
@ -258,6 +258,58 @@ pub struct RuntimeCompanyAnnualStockRepurchaseState {
|
|||
pub eligible_for_single_batch_repurchase: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct RuntimeCompanyAnnualStockIssueState {
|
||||
pub company_id: u32,
|
||||
#[serde(default)]
|
||||
pub annual_mode_active: Option<bool>,
|
||||
#[serde(default)]
|
||||
pub stock_issue_and_buyback_allowed: Option<bool>,
|
||||
#[serde(default)]
|
||||
pub bond_issue_and_repayment_allowed: Option<bool>,
|
||||
#[serde(default)]
|
||||
pub years_since_founding: Option<u32>,
|
||||
#[serde(default)]
|
||||
pub live_bond_count: Option<u8>,
|
||||
#[serde(default)]
|
||||
pub initial_issue_batch_size: Option<u32>,
|
||||
#[serde(default)]
|
||||
pub trimmed_issue_batch_size: Option<u32>,
|
||||
#[serde(default)]
|
||||
pub share_pressure_basis_points: Option<i64>,
|
||||
#[serde(default)]
|
||||
pub pressured_support_adjusted_share_price_scalar: Option<i64>,
|
||||
#[serde(default)]
|
||||
pub pressured_proceeds: Option<i64>,
|
||||
#[serde(default)]
|
||||
pub book_value_per_share_floor_applied: Option<i64>,
|
||||
#[serde(default)]
|
||||
pub price_to_book_ratio_basis_points: Option<i64>,
|
||||
#[serde(default)]
|
||||
pub current_cash: Option<i64>,
|
||||
#[serde(default)]
|
||||
pub highest_coupon_live_bond_principal: Option<u32>,
|
||||
#[serde(default)]
|
||||
pub highest_coupon_live_bond_rate_basis_points: Option<i64>,
|
||||
#[serde(default)]
|
||||
pub current_issue_age_absolute_counter_delta: Option<i64>,
|
||||
#[serde(default)]
|
||||
pub current_issue_cooldown_floor: Option<i64>,
|
||||
#[serde(default)]
|
||||
pub minimum_price_to_book_ratio_basis_points: Option<i64>,
|
||||
#[serde(default)]
|
||||
pub passes_share_price_floor: Option<bool>,
|
||||
#[serde(default)]
|
||||
pub passes_proceeds_floor: Option<bool>,
|
||||
#[serde(default)]
|
||||
pub passes_cash_gate: Option<bool>,
|
||||
#[serde(default)]
|
||||
pub passes_issue_cooldown_gate: Option<bool>,
|
||||
#[serde(default)]
|
||||
pub passes_coupon_price_to_book_gate: Option<bool>,
|
||||
pub eligible_for_double_tranche_issue: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
|
||||
pub struct RuntimeTrackPieceCounts {
|
||||
#[serde(default)]
|
||||
|
|
@ -2168,33 +2220,34 @@ fn runtime_decode_saved_f32_value_f64(raw_u32: u32) -> Option<f64> {
|
|||
Some(value)
|
||||
}
|
||||
|
||||
pub fn runtime_company_recent_per_share_subscore(
|
||||
fn runtime_company_highest_live_bond_coupon_rate_f64(
|
||||
state: &RuntimeState,
|
||||
company_id: u32,
|
||||
) -> Option<f64> {
|
||||
let market_state = state.service_state.company_market_state.get(&company_id)?;
|
||||
if runtime_world_absolute_counter(state)
|
||||
.is_some_and(|counter| counter == market_state.recent_per_share_cache_absolute_counter)
|
||||
{
|
||||
if let Some(cached_value) =
|
||||
runtime_decode_saved_f64_bits(market_state.recent_per_share_cached_value_bits)
|
||||
{
|
||||
return Some(cached_value);
|
||||
}
|
||||
}
|
||||
runtime_decode_saved_f32_value_f64(market_state.recent_per_share_subscore_raw_u32)
|
||||
market_state
|
||||
.live_bond_slots
|
||||
.iter()
|
||||
.filter_map(|slot| {
|
||||
let value = f32::from_bits(slot.coupon_rate_raw_u32) as f64;
|
||||
value.is_finite().then_some(value)
|
||||
})
|
||||
.max_by(|left, right| left.partial_cmp(right).unwrap_or(std::cmp::Ordering::Equal))
|
||||
}
|
||||
|
||||
fn runtime_company_support_adjusted_share_price_scalar_f64(
|
||||
fn runtime_company_support_adjusted_share_price_scalar_with_pressure_f64(
|
||||
state: &RuntimeState,
|
||||
company_id: u32,
|
||||
share_pressure_shares: i64,
|
||||
) -> Option<f64> {
|
||||
let market_state = state.service_state.company_market_state.get(&company_id)?;
|
||||
if let Some(cached_value) =
|
||||
runtime_decode_saved_f32_value_f64(market_state.cached_share_price_raw_u32)
|
||||
{
|
||||
if share_pressure_shares == 0 {
|
||||
return Some(cached_value.max(0.0001));
|
||||
}
|
||||
}
|
||||
|
||||
if market_state.outstanding_shares == 0 {
|
||||
return Some(0.0010000000474974513);
|
||||
|
|
@ -2224,9 +2277,12 @@ fn runtime_company_support_adjusted_share_price_scalar_f64(
|
|||
|
||||
let mutable_support =
|
||||
runtime_decode_saved_f32_value_f64(market_state.mutable_support_scalar_raw_u32)?;
|
||||
let share_pressure =
|
||||
(share_pressure_shares as f64 / market_state.outstanding_shares as f64).clamp(-0.2, 0.2);
|
||||
let effective_mutable_support = mutable_support + share_pressure;
|
||||
let share_count_growth_ratio = ((market_state.outstanding_shares as f64
|
||||
+ 1.4
|
||||
* mutable_support
|
||||
* effective_mutable_support
|
||||
* ((market_state.outstanding_shares as f64 / 20_000.0).powf(0.33)))
|
||||
/ market_state.outstanding_shares as f64)
|
||||
.clamp(0.3, 6.0);
|
||||
|
|
@ -2242,6 +2298,30 @@ fn runtime_company_support_adjusted_share_price_scalar_f64(
|
|||
Some(((recent_per_share * share_count_growth_ratio * investor_multiplier) + 1.0).max(0.0001))
|
||||
}
|
||||
|
||||
pub fn runtime_company_recent_per_share_subscore(
|
||||
state: &RuntimeState,
|
||||
company_id: u32,
|
||||
) -> Option<f64> {
|
||||
let market_state = state.service_state.company_market_state.get(&company_id)?;
|
||||
if runtime_world_absolute_counter(state)
|
||||
.is_some_and(|counter| counter == market_state.recent_per_share_cache_absolute_counter)
|
||||
{
|
||||
if let Some(cached_value) =
|
||||
runtime_decode_saved_f64_bits(market_state.recent_per_share_cached_value_bits)
|
||||
{
|
||||
return Some(cached_value);
|
||||
}
|
||||
}
|
||||
runtime_decode_saved_f32_value_f64(market_state.recent_per_share_subscore_raw_u32)
|
||||
}
|
||||
|
||||
fn runtime_company_support_adjusted_share_price_scalar_f64(
|
||||
state: &RuntimeState,
|
||||
company_id: u32,
|
||||
) -> Option<f64> {
|
||||
runtime_company_support_adjusted_share_price_scalar_with_pressure_f64(state, company_id, 0)
|
||||
}
|
||||
|
||||
pub fn runtime_company_investor_confidence(state: &RuntimeState, company_id: u32) -> Option<i64> {
|
||||
let company = state
|
||||
.companies
|
||||
|
|
@ -2936,6 +3016,175 @@ pub fn runtime_company_annual_stock_repurchase_state(
|
|||
})
|
||||
}
|
||||
|
||||
fn runtime_company_stock_issue_price_to_book_ratio_f64(
|
||||
pressured_support_adjusted_share_price_scalar: f64,
|
||||
book_value_per_share: f64,
|
||||
) -> Option<f64> {
|
||||
let denominator = book_value_per_share.max(1.0);
|
||||
if !pressured_support_adjusted_share_price_scalar.is_finite() || !denominator.is_finite() {
|
||||
return None;
|
||||
}
|
||||
Some(pressured_support_adjusted_share_price_scalar / denominator)
|
||||
}
|
||||
|
||||
fn runtime_company_stock_issue_minimum_price_to_book_ratio_f64(
|
||||
highest_coupon_rate: f64,
|
||||
) -> Option<f64> {
|
||||
if !highest_coupon_rate.is_finite() || highest_coupon_rate <= 0.0 {
|
||||
return None;
|
||||
}
|
||||
Some(if highest_coupon_rate <= 0.07 {
|
||||
1.30
|
||||
} else if highest_coupon_rate <= 0.08 {
|
||||
1.20
|
||||
} else if highest_coupon_rate <= 0.09 {
|
||||
1.10
|
||||
} else if highest_coupon_rate <= 0.10 {
|
||||
0.95
|
||||
} else if highest_coupon_rate <= 0.11 {
|
||||
0.80
|
||||
} else if highest_coupon_rate <= 0.12 {
|
||||
0.62
|
||||
} else if highest_coupon_rate <= 0.13 {
|
||||
0.50
|
||||
} else if highest_coupon_rate <= 0.14 {
|
||||
0.35
|
||||
} else {
|
||||
return None;
|
||||
})
|
||||
}
|
||||
|
||||
pub fn runtime_company_annual_stock_issue_state(
|
||||
state: &RuntimeState,
|
||||
company_id: u32,
|
||||
) -> Option<RuntimeCompanyAnnualStockIssueState> {
|
||||
const ISSUE_PROCEEDS_CAP: i64 = 55_000;
|
||||
const SHARE_PRICE_FLOOR: i64 = 22;
|
||||
const ONE_YEAR_ABSOLUTE_COUNTER_SPAN: i64 = 12 * 28 * 24 * 60;
|
||||
|
||||
let annual_finance_state = runtime_company_annual_finance_state(state, company_id)?;
|
||||
let current_cash = runtime_company_control_transfer_stat_value_f64(
|
||||
state,
|
||||
company_id,
|
||||
RUNTIME_COMPANY_STAT_SLOT_CURRENT_CASH,
|
||||
)
|
||||
.and_then(runtime_round_f64_to_i64);
|
||||
let highest_coupon_live_bond_principal =
|
||||
annual_finance_state.highest_coupon_live_bond_principal;
|
||||
let highest_coupon_live_bond_rate =
|
||||
runtime_company_highest_live_bond_coupon_rate_f64(state, company_id);
|
||||
let highest_coupon_live_bond_rate_basis_points =
|
||||
highest_coupon_live_bond_rate.and_then(|value| runtime_round_f64_to_i64(value * 10_000.0));
|
||||
let mut initial_issue_batch_size =
|
||||
(annual_finance_state.outstanding_shares / 10 / 1_000) * 1_000;
|
||||
if initial_issue_batch_size < 2_000 {
|
||||
initial_issue_batch_size = 2_000;
|
||||
}
|
||||
let initial_issue_batch_size = Some(initial_issue_batch_size);
|
||||
let mut trimmed_issue_batch_size = initial_issue_batch_size?;
|
||||
let mut pressured_support_adjusted_share_price_scalar =
|
||||
runtime_company_support_adjusted_share_price_scalar_with_pressure_f64(
|
||||
state,
|
||||
company_id,
|
||||
-(trimmed_issue_batch_size as i64),
|
||||
);
|
||||
let mut pressured_proceeds = pressured_support_adjusted_share_price_scalar
|
||||
.and_then(|value| runtime_round_f64_to_i64(value * trimmed_issue_batch_size as f64));
|
||||
while trimmed_issue_batch_size > 2_000
|
||||
&& pressured_proceeds.is_some_and(|value| value > ISSUE_PROCEEDS_CAP)
|
||||
{
|
||||
trimmed_issue_batch_size = trimmed_issue_batch_size.saturating_sub(1_000);
|
||||
pressured_support_adjusted_share_price_scalar =
|
||||
runtime_company_support_adjusted_share_price_scalar_with_pressure_f64(
|
||||
state,
|
||||
company_id,
|
||||
-(trimmed_issue_batch_size as i64),
|
||||
);
|
||||
pressured_proceeds = pressured_support_adjusted_share_price_scalar
|
||||
.and_then(|value| runtime_round_f64_to_i64(value * trimmed_issue_batch_size as f64));
|
||||
}
|
||||
let pressured_support_adjusted_share_price_scalar_i64 =
|
||||
pressured_support_adjusted_share_price_scalar.and_then(runtime_round_f64_to_i64);
|
||||
let book_value_per_share_floor_applied =
|
||||
runtime_company_book_value_per_share(state, company_id).map(|value| value.max(1));
|
||||
let price_to_book_ratio = pressured_support_adjusted_share_price_scalar
|
||||
.zip(book_value_per_share_floor_applied)
|
||||
.and_then(|(share_price, book_value)| {
|
||||
runtime_company_stock_issue_price_to_book_ratio_f64(share_price, book_value as f64)
|
||||
});
|
||||
let price_to_book_ratio_basis_points =
|
||||
price_to_book_ratio.and_then(|value| runtime_round_f64_to_i64(value * 10_000.0));
|
||||
let minimum_price_to_book_ratio = highest_coupon_live_bond_rate
|
||||
.and_then(runtime_company_stock_issue_minimum_price_to_book_ratio_f64);
|
||||
let minimum_price_to_book_ratio_basis_points =
|
||||
minimum_price_to_book_ratio.and_then(|value| runtime_round_f64_to_i64(value * 10_000.0));
|
||||
let passes_share_price_floor =
|
||||
pressured_support_adjusted_share_price_scalar_i64.map(|value| value >= SHARE_PRICE_FLOOR);
|
||||
let passes_proceeds_floor = pressured_proceeds.map(|value| value >= ISSUE_PROCEEDS_CAP);
|
||||
let passes_cash_gate = current_cash
|
||||
.zip(highest_coupon_live_bond_principal)
|
||||
.map(|(cash, principal)| cash <= i64::from(principal) + 5_000);
|
||||
let passes_issue_cooldown_gate = Some(
|
||||
annual_finance_state
|
||||
.current_issue_age_absolute_counter_delta
|
||||
.is_none_or(|delta| delta >= ONE_YEAR_ABSOLUTE_COUNTER_SPAN),
|
||||
);
|
||||
let passes_coupon_price_to_book_gate = price_to_book_ratio_basis_points
|
||||
.zip(minimum_price_to_book_ratio_basis_points)
|
||||
.map(|(actual, minimum)| actual >= minimum);
|
||||
let eligible_for_double_tranche_issue = runtime_world_annual_finance_mode_active(state)
|
||||
== Some(true)
|
||||
&& runtime_world_stock_issue_and_buyback_allowed(state) == Some(true)
|
||||
&& runtime_world_bond_issue_and_repayment_allowed(state) == Some(true)
|
||||
&& annual_finance_state.bond_count >= 2
|
||||
&& annual_finance_state
|
||||
.years_since_founding
|
||||
.is_some_and(|years| years >= 1)
|
||||
&& !runtime_company_annual_creditor_pressure_state(state, company_id)?
|
||||
.eligible_for_bankruptcy_branch
|
||||
&& !runtime_company_annual_deep_distress_state(state, company_id)?
|
||||
.eligible_for_bankruptcy_fallback
|
||||
&& !runtime_company_annual_stock_repurchase_state(state, company_id)?
|
||||
.eligible_for_single_batch_repurchase
|
||||
&& passes_share_price_floor == Some(true)
|
||||
&& passes_proceeds_floor == Some(true)
|
||||
&& passes_cash_gate == Some(true)
|
||||
&& passes_issue_cooldown_gate == Some(true)
|
||||
&& passes_coupon_price_to_book_gate == Some(true);
|
||||
Some(RuntimeCompanyAnnualStockIssueState {
|
||||
company_id,
|
||||
annual_mode_active: runtime_world_annual_finance_mode_active(state),
|
||||
stock_issue_and_buyback_allowed: runtime_world_stock_issue_and_buyback_allowed(state),
|
||||
bond_issue_and_repayment_allowed: runtime_world_bond_issue_and_repayment_allowed(state),
|
||||
years_since_founding: annual_finance_state.years_since_founding,
|
||||
live_bond_count: Some(annual_finance_state.bond_count),
|
||||
initial_issue_batch_size,
|
||||
trimmed_issue_batch_size: Some(trimmed_issue_batch_size),
|
||||
share_pressure_basis_points: runtime_round_f64_to_i64(
|
||||
-(trimmed_issue_batch_size as f64) / annual_finance_state.outstanding_shares as f64
|
||||
* 10_000.0,
|
||||
),
|
||||
pressured_support_adjusted_share_price_scalar:
|
||||
pressured_support_adjusted_share_price_scalar_i64,
|
||||
pressured_proceeds,
|
||||
book_value_per_share_floor_applied,
|
||||
price_to_book_ratio_basis_points,
|
||||
current_cash,
|
||||
highest_coupon_live_bond_principal,
|
||||
highest_coupon_live_bond_rate_basis_points,
|
||||
current_issue_age_absolute_counter_delta: annual_finance_state
|
||||
.current_issue_age_absolute_counter_delta,
|
||||
current_issue_cooldown_floor: Some(ONE_YEAR_ABSOLUTE_COUNTER_SPAN),
|
||||
minimum_price_to_book_ratio_basis_points,
|
||||
passes_share_price_floor,
|
||||
passes_proceeds_floor,
|
||||
passes_cash_gate,
|
||||
passes_issue_cooldown_gate,
|
||||
passes_coupon_price_to_book_gate,
|
||||
eligible_for_double_tranche_issue,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn runtime_company_annual_creditor_pressure_state(
|
||||
state: &RuntimeState,
|
||||
company_id: u32,
|
||||
|
|
@ -7372,6 +7621,188 @@ mod tests {
|
|||
assert!(!repurchase_state.eligible_for_single_batch_repurchase);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn derives_annual_stock_issue_state_from_rehosted_owner_state() {
|
||||
let mut year_stat_family_qword_bits = vec![
|
||||
0u64;
|
||||
((RUNTIME_COMPANY_STAT_SLOT_COUNT + 2) * RUNTIME_COMPANY_YEAR_STAT_FAMILY_SPAN)
|
||||
as usize
|
||||
];
|
||||
let write_current_value = |bits: &mut Vec<u64>, slot_id: u32, value: f64| {
|
||||
let index = (slot_id * RUNTIME_COMPANY_YEAR_STAT_FAMILY_SPAN) as usize;
|
||||
bits[index] = value.to_bits();
|
||||
};
|
||||
write_current_value(&mut year_stat_family_qword_bits, 0x0d, 250_000.0);
|
||||
|
||||
let state = RuntimeState {
|
||||
calendar: CalendarPoint {
|
||||
year: 1845,
|
||||
month_slot: 0,
|
||||
phase_slot: 0,
|
||||
tick_slot: 0,
|
||||
},
|
||||
world_flags: BTreeMap::new(),
|
||||
save_profile: RuntimeSaveProfileState::default(),
|
||||
world_restore: RuntimeWorldRestoreState {
|
||||
partial_year_progress_raw_u8: Some(0x0c),
|
||||
stock_issue_and_buyback_policy_raw_u8: Some(0),
|
||||
stock_issue_and_buyback_allowed: Some(true),
|
||||
bond_issue_and_repayment_policy_raw_u8: Some(0),
|
||||
bond_issue_and_repayment_allowed: Some(true),
|
||||
issue_37_value: Some(2),
|
||||
issue_37_multiplier_raw_u32: Some(1.0f32.to_bits()),
|
||||
issue_37_multiplier_value_f32_text: Some("1.000000".to_string()),
|
||||
absolute_counter_raw_u32: Some(885_911_040),
|
||||
..RuntimeWorldRestoreState::default()
|
||||
},
|
||||
metadata: BTreeMap::new(),
|
||||
companies: vec![RuntimeCompany {
|
||||
company_id: 14,
|
||||
current_cash: 0,
|
||||
debt: 0,
|
||||
credit_rating_score: None,
|
||||
prime_rate: None,
|
||||
active: true,
|
||||
available_track_laying_capacity: None,
|
||||
controller_kind: RuntimeCompanyControllerKind::Unknown,
|
||||
linked_chairman_profile_id: Some(8),
|
||||
book_value_per_share: 0,
|
||||
investor_confidence: 0,
|
||||
management_attitude: 0,
|
||||
takeover_cooldown_year: None,
|
||||
merger_cooldown_year: None,
|
||||
track_piece_counts: RuntimeTrackPieceCounts::default(),
|
||||
}],
|
||||
selected_company_id: None,
|
||||
players: Vec::new(),
|
||||
selected_player_id: None,
|
||||
chairman_profiles: vec![RuntimeChairmanProfile {
|
||||
profile_id: 8,
|
||||
name: "Taylor".to_string(),
|
||||
active: true,
|
||||
current_cash: 200,
|
||||
linked_company_id: Some(14),
|
||||
company_holdings: BTreeMap::from([(14, 14_000)]),
|
||||
holdings_value_total: 0,
|
||||
net_worth_total: 0,
|
||||
purchasing_power_total: 0,
|
||||
}],
|
||||
selected_chairman_profile_id: None,
|
||||
trains: Vec::new(),
|
||||
locomotive_catalog: Vec::new(),
|
||||
cargo_catalog: Vec::new(),
|
||||
territories: Vec::new(),
|
||||
company_territory_track_piece_counts: Vec::new(),
|
||||
company_territory_access: Vec::new(),
|
||||
packed_event_collection: None,
|
||||
event_runtime_records: Vec::new(),
|
||||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
all_cargo_price_override: None,
|
||||
named_cargo_price_overrides: BTreeMap::new(),
|
||||
all_cargo_production_override: None,
|
||||
factory_cargo_production_override: None,
|
||||
farm_mine_cargo_production_override: None,
|
||||
named_cargo_production_overrides: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
world_runtime_variables: BTreeMap::new(),
|
||||
company_runtime_variables: BTreeMap::new(),
|
||||
player_runtime_variables: BTreeMap::new(),
|
||||
territory_runtime_variables: BTreeMap::new(),
|
||||
world_scalar_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
service_state: RuntimeServiceState {
|
||||
world_issue_opinion_base_terms_raw_i32: vec![0; 0x3b],
|
||||
chairman_personality_raw_u8: BTreeMap::from([(8, 20)]),
|
||||
company_market_state: BTreeMap::from([(
|
||||
14,
|
||||
RuntimeCompanyMarketState {
|
||||
outstanding_shares: 20_000,
|
||||
bond_count: 2,
|
||||
highest_coupon_live_bond_principal: Some(300_000),
|
||||
current_issue_calendar_word: 0x0101_0725,
|
||||
current_issue_calendar_word_2: 0x0001_0001,
|
||||
founding_year: 1840,
|
||||
cached_share_price_raw_u32: 35.0f32.to_bits(),
|
||||
recent_per_share_cache_absolute_counter: 885_911_040,
|
||||
recent_per_share_cached_value_bits: 34.0f64.to_bits(),
|
||||
city_connection_latch: false,
|
||||
live_bond_slots: vec![
|
||||
RuntimeCompanyBondSlot {
|
||||
slot_index: 0,
|
||||
principal: 300_000,
|
||||
coupon_rate_raw_u32: 0.11f32.to_bits(),
|
||||
},
|
||||
RuntimeCompanyBondSlot {
|
||||
slot_index: 1,
|
||||
principal: 200_000,
|
||||
coupon_rate_raw_u32: 0.07f32.to_bits(),
|
||||
},
|
||||
],
|
||||
direct_control_transfer_float_fields_raw_u32: BTreeMap::from([(
|
||||
0x32f,
|
||||
30.0f32.to_bits(),
|
||||
)]),
|
||||
year_stat_family_qword_bits,
|
||||
..RuntimeCompanyMarketState::default()
|
||||
},
|
||||
)]),
|
||||
..RuntimeServiceState::default()
|
||||
},
|
||||
};
|
||||
|
||||
let stock_issue_state =
|
||||
runtime_company_annual_stock_issue_state(&state, 14).expect("stock issue state");
|
||||
assert_eq!(stock_issue_state.live_bond_count, Some(2));
|
||||
assert_eq!(stock_issue_state.initial_issue_batch_size, Some(2_000));
|
||||
assert_eq!(stock_issue_state.trimmed_issue_batch_size, Some(2_000));
|
||||
assert_eq!(stock_issue_state.share_pressure_basis_points, Some(-1_000));
|
||||
assert_eq!(
|
||||
stock_issue_state.pressured_support_adjusted_share_price_scalar,
|
||||
Some(35)
|
||||
);
|
||||
assert_eq!(stock_issue_state.pressured_proceeds, Some(70_000));
|
||||
assert_eq!(
|
||||
stock_issue_state.book_value_per_share_floor_applied,
|
||||
Some(30)
|
||||
);
|
||||
assert_eq!(
|
||||
stock_issue_state.price_to_book_ratio_basis_points,
|
||||
Some(11_667)
|
||||
);
|
||||
assert_eq!(
|
||||
stock_issue_state.highest_coupon_live_bond_rate_basis_points,
|
||||
Some(1_100)
|
||||
);
|
||||
assert_eq!(
|
||||
stock_issue_state.minimum_price_to_book_ratio_basis_points,
|
||||
Some(8_000)
|
||||
);
|
||||
assert_eq!(stock_issue_state.current_cash, Some(250_000));
|
||||
assert_eq!(
|
||||
stock_issue_state.highest_coupon_live_bond_principal,
|
||||
Some(300_000)
|
||||
);
|
||||
assert_eq!(
|
||||
stock_issue_state.current_issue_age_absolute_counter_delta,
|
||||
Some(967_680)
|
||||
);
|
||||
assert_eq!(
|
||||
stock_issue_state.current_issue_cooldown_floor,
|
||||
Some(483_840)
|
||||
);
|
||||
assert_eq!(stock_issue_state.passes_share_price_floor, Some(true));
|
||||
assert_eq!(stock_issue_state.passes_proceeds_floor, Some(true));
|
||||
assert_eq!(stock_issue_state.passes_cash_gate, Some(true));
|
||||
assert_eq!(stock_issue_state.passes_issue_cooldown_gate, Some(true));
|
||||
assert_eq!(
|
||||
stock_issue_state.passes_coupon_price_to_book_gate,
|
||||
Some(true)
|
||||
);
|
||||
assert!(stock_issue_state.eligible_for_double_tranche_issue);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reads_company_market_metrics_from_annual_finance_reader() {
|
||||
let current_issue_calendar_word = 0x0101_0726;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,8 @@ use serde::{Deserialize, Serialize};
|
|||
use crate::{
|
||||
CalendarPoint, RuntimeState, runtime_company_annual_creditor_pressure_state,
|
||||
runtime_company_annual_deep_distress_state, runtime_company_annual_finance_state,
|
||||
runtime_company_annual_stock_repurchase_state, runtime_company_unassigned_share_pool,
|
||||
runtime_company_annual_stock_issue_state, runtime_company_annual_stock_repurchase_state,
|
||||
runtime_company_unassigned_share_pool,
|
||||
};
|
||||
|
||||
fn raw_u32_to_f32_text(raw: u32) -> String {
|
||||
|
|
@ -124,6 +125,26 @@ pub struct RuntimeSummary {
|
|||
pub selected_company_stock_repurchase_affordability_cash_floor: Option<i64>,
|
||||
pub selected_company_stock_repurchase_unassigned_share_pool: Option<u32>,
|
||||
pub selected_company_stock_repurchase_eligible_for_single_batch: Option<bool>,
|
||||
pub selected_company_stock_issue_live_bond_count: Option<u8>,
|
||||
pub selected_company_stock_issue_initial_batch_size: Option<u32>,
|
||||
pub selected_company_stock_issue_trimmed_batch_size: Option<u32>,
|
||||
pub selected_company_stock_issue_share_pressure_basis_points: Option<i64>,
|
||||
pub selected_company_stock_issue_pressured_share_price_scalar: Option<i64>,
|
||||
pub selected_company_stock_issue_pressured_proceeds: Option<i64>,
|
||||
pub selected_company_stock_issue_book_value_per_share_floor_applied: Option<i64>,
|
||||
pub selected_company_stock_issue_price_to_book_ratio_basis_points: Option<i64>,
|
||||
pub selected_company_stock_issue_current_cash: Option<i64>,
|
||||
pub selected_company_stock_issue_highest_coupon_live_bond_principal: Option<u32>,
|
||||
pub selected_company_stock_issue_highest_coupon_live_bond_rate_basis_points: Option<i64>,
|
||||
pub selected_company_stock_issue_current_issue_age_absolute_counter_delta: Option<i64>,
|
||||
pub selected_company_stock_issue_current_issue_cooldown_floor: Option<i64>,
|
||||
pub selected_company_stock_issue_minimum_price_to_book_ratio_basis_points: Option<i64>,
|
||||
pub selected_company_stock_issue_passes_share_price_floor: Option<bool>,
|
||||
pub selected_company_stock_issue_passes_proceeds_floor: Option<bool>,
|
||||
pub selected_company_stock_issue_passes_cash_gate: Option<bool>,
|
||||
pub selected_company_stock_issue_passes_issue_cooldown_gate: Option<bool>,
|
||||
pub selected_company_stock_issue_passes_coupon_price_to_book_gate: Option<bool>,
|
||||
pub selected_company_stock_issue_eligible_for_double_tranche: Option<bool>,
|
||||
pub player_count: usize,
|
||||
pub chairman_profile_count: usize,
|
||||
pub active_chairman_profile_count: usize,
|
||||
|
|
@ -224,6 +245,9 @@ impl RuntimeSummary {
|
|||
state.selected_company_id.and_then(|company_id| {
|
||||
runtime_company_annual_stock_repurchase_state(state, company_id)
|
||||
});
|
||||
let selected_company_stock_issue_state = state
|
||||
.selected_company_id
|
||||
.and_then(|company_id| runtime_company_annual_stock_issue_state(state, company_id));
|
||||
Self {
|
||||
calendar: state.calendar,
|
||||
calendar_projection_source: state.metadata.get("save_slice.calendar_source").cloned(),
|
||||
|
|
@ -550,6 +574,81 @@ impl RuntimeSummary {
|
|||
selected_company_stock_repurchase_state
|
||||
.as_ref()
|
||||
.map(|repurchase_state| repurchase_state.eligible_for_single_batch_repurchase),
|
||||
selected_company_stock_issue_live_bond_count: selected_company_stock_issue_state
|
||||
.as_ref()
|
||||
.and_then(|issue_state| issue_state.live_bond_count),
|
||||
selected_company_stock_issue_initial_batch_size: selected_company_stock_issue_state
|
||||
.as_ref()
|
||||
.and_then(|issue_state| issue_state.initial_issue_batch_size),
|
||||
selected_company_stock_issue_trimmed_batch_size: selected_company_stock_issue_state
|
||||
.as_ref()
|
||||
.and_then(|issue_state| issue_state.trimmed_issue_batch_size),
|
||||
selected_company_stock_issue_share_pressure_basis_points:
|
||||
selected_company_stock_issue_state
|
||||
.as_ref()
|
||||
.and_then(|issue_state| issue_state.share_pressure_basis_points),
|
||||
selected_company_stock_issue_pressured_share_price_scalar:
|
||||
selected_company_stock_issue_state
|
||||
.as_ref()
|
||||
.and_then(|issue_state| {
|
||||
issue_state.pressured_support_adjusted_share_price_scalar
|
||||
}),
|
||||
selected_company_stock_issue_pressured_proceeds: selected_company_stock_issue_state
|
||||
.as_ref()
|
||||
.and_then(|issue_state| issue_state.pressured_proceeds),
|
||||
selected_company_stock_issue_book_value_per_share_floor_applied:
|
||||
selected_company_stock_issue_state
|
||||
.as_ref()
|
||||
.and_then(|issue_state| issue_state.book_value_per_share_floor_applied),
|
||||
selected_company_stock_issue_price_to_book_ratio_basis_points:
|
||||
selected_company_stock_issue_state
|
||||
.as_ref()
|
||||
.and_then(|issue_state| issue_state.price_to_book_ratio_basis_points),
|
||||
selected_company_stock_issue_current_cash: selected_company_stock_issue_state
|
||||
.as_ref()
|
||||
.and_then(|issue_state| issue_state.current_cash),
|
||||
selected_company_stock_issue_highest_coupon_live_bond_principal:
|
||||
selected_company_stock_issue_state
|
||||
.as_ref()
|
||||
.and_then(|issue_state| issue_state.highest_coupon_live_bond_principal),
|
||||
selected_company_stock_issue_highest_coupon_live_bond_rate_basis_points:
|
||||
selected_company_stock_issue_state
|
||||
.as_ref()
|
||||
.and_then(|issue_state| issue_state.highest_coupon_live_bond_rate_basis_points),
|
||||
selected_company_stock_issue_current_issue_age_absolute_counter_delta:
|
||||
selected_company_stock_issue_state
|
||||
.as_ref()
|
||||
.and_then(|issue_state| issue_state.current_issue_age_absolute_counter_delta),
|
||||
selected_company_stock_issue_current_issue_cooldown_floor:
|
||||
selected_company_stock_issue_state
|
||||
.as_ref()
|
||||
.and_then(|issue_state| issue_state.current_issue_cooldown_floor),
|
||||
selected_company_stock_issue_minimum_price_to_book_ratio_basis_points:
|
||||
selected_company_stock_issue_state
|
||||
.as_ref()
|
||||
.and_then(|issue_state| issue_state.minimum_price_to_book_ratio_basis_points),
|
||||
selected_company_stock_issue_passes_share_price_floor:
|
||||
selected_company_stock_issue_state
|
||||
.as_ref()
|
||||
.and_then(|issue_state| issue_state.passes_share_price_floor),
|
||||
selected_company_stock_issue_passes_proceeds_floor: selected_company_stock_issue_state
|
||||
.as_ref()
|
||||
.and_then(|issue_state| issue_state.passes_proceeds_floor),
|
||||
selected_company_stock_issue_passes_cash_gate: selected_company_stock_issue_state
|
||||
.as_ref()
|
||||
.and_then(|issue_state| issue_state.passes_cash_gate),
|
||||
selected_company_stock_issue_passes_issue_cooldown_gate:
|
||||
selected_company_stock_issue_state
|
||||
.as_ref()
|
||||
.and_then(|issue_state| issue_state.passes_issue_cooldown_gate),
|
||||
selected_company_stock_issue_passes_coupon_price_to_book_gate:
|
||||
selected_company_stock_issue_state
|
||||
.as_ref()
|
||||
.and_then(|issue_state| issue_state.passes_coupon_price_to_book_gate),
|
||||
selected_company_stock_issue_eligible_for_double_tranche:
|
||||
selected_company_stock_issue_state
|
||||
.as_ref()
|
||||
.map(|issue_state| issue_state.eligible_for_double_tranche_issue),
|
||||
player_count: state.players.len(),
|
||||
chairman_profile_count: state.chairman_profiles.len(),
|
||||
active_chairman_profile_count: state
|
||||
|
|
@ -2811,4 +2910,216 @@ mod tests {
|
|||
Some(false)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn summarizes_selected_company_stock_issue_state() {
|
||||
let mut year_stat_family_qword_bits = vec![
|
||||
0u64;
|
||||
((crate::RUNTIME_COMPANY_STAT_SLOT_COUNT + 2)
|
||||
* crate::RUNTIME_COMPANY_YEAR_STAT_FAMILY_SPAN)
|
||||
as usize
|
||||
];
|
||||
year_stat_family_qword_bits[(crate::RUNTIME_COMPANY_STAT_SLOT_CURRENT_CASH
|
||||
* crate::RUNTIME_COMPANY_YEAR_STAT_FAMILY_SPAN)
|
||||
as usize] = 250_000.0f64.to_bits();
|
||||
|
||||
let state = RuntimeState {
|
||||
calendar: CalendarPoint {
|
||||
year: 1845,
|
||||
month_slot: 0,
|
||||
phase_slot: 0,
|
||||
tick_slot: 0,
|
||||
},
|
||||
world_flags: BTreeMap::new(),
|
||||
save_profile: RuntimeSaveProfileState::default(),
|
||||
world_restore: RuntimeWorldRestoreState {
|
||||
partial_year_progress_raw_u8: Some(0x0c),
|
||||
stock_issue_and_buyback_policy_raw_u8: Some(0),
|
||||
stock_issue_and_buyback_allowed: Some(true),
|
||||
bond_issue_and_repayment_policy_raw_u8: Some(0),
|
||||
bond_issue_and_repayment_allowed: Some(true),
|
||||
issue_37_value: Some(2),
|
||||
issue_37_multiplier_raw_u32: Some(1.0f32.to_bits()),
|
||||
issue_37_multiplier_value_f32_text: Some("1.000000".to_string()),
|
||||
absolute_counter_raw_u32: Some(885_911_040),
|
||||
..RuntimeWorldRestoreState::default()
|
||||
},
|
||||
metadata: BTreeMap::new(),
|
||||
companies: vec![RuntimeCompany {
|
||||
company_id: 14,
|
||||
current_cash: 0,
|
||||
debt: 0,
|
||||
credit_rating_score: None,
|
||||
prime_rate: None,
|
||||
active: true,
|
||||
available_track_laying_capacity: None,
|
||||
controller_kind: crate::RuntimeCompanyControllerKind::Unknown,
|
||||
linked_chairman_profile_id: Some(8),
|
||||
book_value_per_share: 0,
|
||||
investor_confidence: 0,
|
||||
management_attitude: 0,
|
||||
takeover_cooldown_year: None,
|
||||
merger_cooldown_year: None,
|
||||
track_piece_counts: RuntimeTrackPieceCounts::default(),
|
||||
}],
|
||||
selected_company_id: Some(14),
|
||||
players: Vec::new(),
|
||||
selected_player_id: None,
|
||||
chairman_profiles: vec![crate::RuntimeChairmanProfile {
|
||||
profile_id: 8,
|
||||
name: "Taylor".to_string(),
|
||||
active: true,
|
||||
current_cash: 200,
|
||||
linked_company_id: Some(14),
|
||||
company_holdings: BTreeMap::from([(14, 14_000)]),
|
||||
holdings_value_total: 0,
|
||||
net_worth_total: 0,
|
||||
purchasing_power_total: 0,
|
||||
}],
|
||||
selected_chairman_profile_id: None,
|
||||
trains: Vec::new(),
|
||||
locomotive_catalog: Vec::new(),
|
||||
cargo_catalog: Vec::new(),
|
||||
territories: Vec::new(),
|
||||
company_territory_track_piece_counts: Vec::new(),
|
||||
company_territory_access: Vec::new(),
|
||||
packed_event_collection: None,
|
||||
event_runtime_records: Vec::new(),
|
||||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: Vec::new().into_iter().collect(),
|
||||
all_cargo_price_override: None,
|
||||
named_cargo_price_overrides: BTreeMap::new(),
|
||||
all_cargo_production_override: None,
|
||||
factory_cargo_production_override: None,
|
||||
farm_mine_cargo_production_override: None,
|
||||
named_cargo_production_overrides: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
world_runtime_variables: BTreeMap::new(),
|
||||
company_runtime_variables: BTreeMap::new(),
|
||||
player_runtime_variables: BTreeMap::new(),
|
||||
territory_runtime_variables: BTreeMap::new(),
|
||||
world_scalar_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
service_state: RuntimeServiceState {
|
||||
world_issue_opinion_base_terms_raw_i32: vec![0; 0x3b],
|
||||
chairman_personality_raw_u8: BTreeMap::from([(8, 20)]),
|
||||
company_market_state: BTreeMap::from([(
|
||||
14,
|
||||
crate::RuntimeCompanyMarketState {
|
||||
outstanding_shares: 20_000,
|
||||
bond_count: 2,
|
||||
highest_coupon_live_bond_principal: Some(300_000),
|
||||
current_issue_calendar_word: 0x0101_0725,
|
||||
current_issue_calendar_word_2: 0x0001_0001,
|
||||
founding_year: 1840,
|
||||
cached_share_price_raw_u32: 35.0f32.to_bits(),
|
||||
recent_per_share_cache_absolute_counter: 885_911_040,
|
||||
recent_per_share_cached_value_bits: 34.0f64.to_bits(),
|
||||
live_bond_slots: vec![
|
||||
crate::RuntimeCompanyBondSlot {
|
||||
slot_index: 0,
|
||||
principal: 300_000,
|
||||
coupon_rate_raw_u32: 0.11f32.to_bits(),
|
||||
},
|
||||
crate::RuntimeCompanyBondSlot {
|
||||
slot_index: 1,
|
||||
principal: 200_000,
|
||||
coupon_rate_raw_u32: 0.07f32.to_bits(),
|
||||
},
|
||||
],
|
||||
direct_control_transfer_float_fields_raw_u32: BTreeMap::from([(
|
||||
0x32f,
|
||||
30.0f32.to_bits(),
|
||||
)]),
|
||||
year_stat_family_qword_bits,
|
||||
..crate::RuntimeCompanyMarketState::default()
|
||||
},
|
||||
)]),
|
||||
..RuntimeServiceState::default()
|
||||
},
|
||||
};
|
||||
|
||||
let summary = RuntimeSummary::from_state(&state);
|
||||
assert_eq!(
|
||||
summary.selected_company_stock_issue_live_bond_count,
|
||||
Some(2)
|
||||
);
|
||||
assert_eq!(
|
||||
summary.selected_company_stock_issue_initial_batch_size,
|
||||
Some(2_000)
|
||||
);
|
||||
assert_eq!(
|
||||
summary.selected_company_stock_issue_trimmed_batch_size,
|
||||
Some(2_000)
|
||||
);
|
||||
assert_eq!(
|
||||
summary.selected_company_stock_issue_share_pressure_basis_points,
|
||||
Some(-1_000)
|
||||
);
|
||||
assert_eq!(
|
||||
summary.selected_company_stock_issue_pressured_share_price_scalar,
|
||||
Some(35)
|
||||
);
|
||||
assert_eq!(
|
||||
summary.selected_company_stock_issue_pressured_proceeds,
|
||||
Some(70_000)
|
||||
);
|
||||
assert_eq!(
|
||||
summary.selected_company_stock_issue_book_value_per_share_floor_applied,
|
||||
Some(30)
|
||||
);
|
||||
assert_eq!(
|
||||
summary.selected_company_stock_issue_price_to_book_ratio_basis_points,
|
||||
Some(11_667)
|
||||
);
|
||||
assert_eq!(
|
||||
summary.selected_company_stock_issue_current_cash,
|
||||
Some(250_000)
|
||||
);
|
||||
assert_eq!(
|
||||
summary.selected_company_stock_issue_highest_coupon_live_bond_principal,
|
||||
Some(300_000)
|
||||
);
|
||||
assert_eq!(
|
||||
summary.selected_company_stock_issue_highest_coupon_live_bond_rate_basis_points,
|
||||
Some(1_100)
|
||||
);
|
||||
assert_eq!(
|
||||
summary.selected_company_stock_issue_current_issue_age_absolute_counter_delta,
|
||||
Some(967_680)
|
||||
);
|
||||
assert_eq!(
|
||||
summary.selected_company_stock_issue_current_issue_cooldown_floor,
|
||||
Some(483_840)
|
||||
);
|
||||
assert_eq!(
|
||||
summary.selected_company_stock_issue_minimum_price_to_book_ratio_basis_points,
|
||||
Some(8_000)
|
||||
);
|
||||
assert_eq!(
|
||||
summary.selected_company_stock_issue_passes_share_price_floor,
|
||||
Some(true)
|
||||
);
|
||||
assert_eq!(
|
||||
summary.selected_company_stock_issue_passes_proceeds_floor,
|
||||
Some(true)
|
||||
);
|
||||
assert_eq!(
|
||||
summary.selected_company_stock_issue_passes_cash_gate,
|
||||
Some(true)
|
||||
);
|
||||
assert_eq!(
|
||||
summary.selected_company_stock_issue_passes_issue_cooldown_gate,
|
||||
Some(true)
|
||||
);
|
||||
assert_eq!(
|
||||
summary.selected_company_stock_issue_passes_coupon_price_to_book_gate,
|
||||
Some(true)
|
||||
);
|
||||
assert_eq!(
|
||||
summary.selected_company_stock_issue_eligible_for_double_tranche,
|
||||
Some(true)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -134,10 +134,12 @@ The highest-value next passes are now:
|
|||
and last bankruptcy for later annual finance-policy rehosting; live bond-slot count now travels through that same owned annual-finance
|
||||
state for the stock-capital branch gate, and the grounded bond table now also contributes both
|
||||
the largest live bond principal and the chosen highest-coupon live bond principal into that same
|
||||
owner-state surface; the same fixed-world save block now also carries the raw stock, bond,
|
||||
owner-state surface, plus the highest live coupon rate for the stock-capital approval ladder;
|
||||
the same fixed-world save block now also carries the raw stock, bond,
|
||||
bankruptcy, and dividend finance-policy bytes, and the first annual creditor-pressure branch now
|
||||
executes as a pure runtime reader over that owner state instead of remaining atlas-only; the
|
||||
later deep-distress bankruptcy fallback now runs on that same save-native cash and trailing-
|
||||
profit seam; the annual stock-repurchase and stock-capital issue branches now do too
|
||||
net-profit surface too; the same owner 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 headlessly as another pure reader
|
||||
|
|
|
|||
|
|
@ -224,8 +224,9 @@ annual finance-policy gates in the atlas. Live bond-slot count now also flows th
|
|||
owned company market and annual-finance state, matching the stock-capital branch gate that needs
|
||||
at least two live bonds. The same grounded bond table now also contributes both the largest live
|
||||
bond principal and the chosen highest-coupon live bond principal into owned company market and
|
||||
annual-finance state, so later stock-capital gates can extend a rehosted owner-state seam instead
|
||||
of guessing another finance leaf. The same fixed-world save block now also carries the raw stock,
|
||||
annual-finance state, and now also exposes the highest live coupon rate, so the stock-capital
|
||||
price-to-book ladder can extend a rehosted owner-state seam instead of guessing another finance
|
||||
leaf. The same fixed-world save block now also carries the raw stock,
|
||||
bond, bankruptcy, and dividend finance-policy bytes, and the earliest annual creditor-pressure
|
||||
bankruptcy branch now runs as a pure runtime reader over owned annual-finance state, support-
|
||||
adjusted share price, and those policy bytes rather than staying in atlas prose only. The later
|
||||
|
|
@ -233,7 +234,9 @@ deep-distress bankruptcy fallback now rides the same owner-state seam too, using
|
|||
cash reader plus the first three trailing net-profit years instead of a parallel raw-offset guess.
|
||||
That same seam now also carries the fixed-world building-density growth setting plus the linked
|
||||
chairman personality byte, which is enough to rehost the annual stock-repurchase gate on owned
|
||||
save/runtime state instead of another threshold-only note.
|
||||
save/runtime state instead of another threshold-only note. The stock-capital issue branch now
|
||||
rides that same seam too, with share-pressure, cooldown, and price-to-book gate state exposed as
|
||||
normal runtime readers.
|
||||
|
||||
## Why This Boundary
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue