zfin/examples/pre-retirement-spending-target/projections.srf

73 lines
3.5 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!srfv1
# Pre-retirement projection: target spending with explicit
# retirement_target override anchored on an INFEASIBLE cell.
#
# Same household and balance sheet as `pre-retirement-spending/`, but
# with a much higher `target_spending` ($2.4M/yr) AND a horizon
# annotation that pins the headline to a (horizon × confidence) pair
# that turns out to be infeasible within the 50-year accumulation
# search cap.
#
# This example exists to demonstrate two things:
#
# 1. The explicit `retirement_target` override on a horizon record.
# Without it, the default rule would walk horizons longest →
# shortest at 99% confidence; with it, the user picks exactly
# which (horizon × confidence) cell drives the Accumulation
# phase block headline.
#
# 2. The "not feasible" rendering path. When the annotated cell
# returns no value of `accumulation_years` ≤ 50 that sustains
# the target spending, the headline retirement line renders
# "Years until possible retirement: not feasible" instead of a
# date. The full Earliest retirement grid still renders below
# so the user can see which cells DO work and pick a different
# anchor if they want.
#
# Validation rules (enforced at parse time):
# - At most ONE horizon may carry a `retirement_target` annotation.
# Two or more drops them all (warning logged) and the default
# rule applies.
# - Allowed `retirement_target` values: 90, 95, 99. Anything else
# drops the annotation on that record (warning logged).
# - The annotation rides on `horizon:num:N` or `horizon_age:num:N`
# records identically. When on a `horizon_age` record, the
# annotation survives age-resolution into the resolved horizon.
# Asset allocation target (80% stocks / 20% bonds — typical pre-retirement)
type::config,target_stock_pct:num:80
# Distribution-phase horizons. The 50-year horizon (resolved from
# `horizon_age:num:95`) is the user's preferred planning anchor —
# they want to see whether retirement is achievable at maximum
# conservatism (99% confidence) over the longest distribution
# phase. With the high target_spending below, this cell turns out
# to be INFEASIBLE within the 50-year search cap. The headline
# retirement line reflects that honestly: "not feasible". The
# Earliest grid below still renders the full matrix so the user can
# see which horizon × confidence pairs DO work.
type::config,horizon:num:25
type::config,horizon:num:35
type::config,horizon_age:num:95,retirement_target:num:99
# Annual household contribution to retirement accounts
type::config,annual_contribution:num:80000
type::config,contribution_inflation_adjusted:bool:true
# Target retirement spending — set deliberately high so the
# longest-horizon × highest-confidence cell falls outside the 50-year
# search cap. This is what produces the "not feasible" headline AND
# the mixed feasible/infeasible cells visible in the grid.
type::config,target_spending:num:2400000
type::config,target_spending_inflation_adjusted:bool:true
# Birthdates (drives life-event ages even without retirement_age)
type::birthdate,date::1981-04-12
type::birthdate,date::1983-09-08,person:num:2
# Social Security at age 70 (more conservative claim age)
type::event,name::Social Security (Pat),start_age:num:70,person:num:1,amount:num:38400
type::event,name::Social Security (Sam),start_age:num:70,person:num:2,amount:num:36000
# College tuition for the kids — 4-year overlap when Pat is age 50-53
type::event,name::College Tuition,start_age:num:50,person:num:1,duration:num:4,amount:num:-55000