Py.Cafe

Zakkenroller/

stochastic-ltc-financial-modeling

Stochastic LTC Financial Modeling

DocsPricing
  • app.py
  • requirements.txt
app.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import streamlit as st
import pandas as pd
import numpy as np
import plotly.express as px

st.set_page_config(layout="wide", page_title="LTC Financial Impact Model")

st.title("Stochastic LTC Financial Modeling Dashboard")
st.markdown("### Asset Allocation: 457(b) Conversion vs. Self-Funding")

# --- SIDEBAR: INTERACTIVE VARIABLES ---
st.sidebar.header("Demographics & Lifespan")
current_age_primary = st.sidebar.number_input("Primary Age", value=50)
current_age_spouse = st.sidebar.number_input("Spouse Age", value=50)
mortality_primary = st.sidebar.slider("Primary Mortality Age", 60, 100, 85)
mortality_spouse = st.sidebar.slider("Spouse Mortality Age", 60, 100, 88)

st.sidebar.header("LTC Actuarial Risk")
onset_age = st.sidebar.slider("Age of LTC Onset", 65, 95, 78)
duration_years = st.sidebar.slider("Duration of Memory Care (Years)", 1, 15, 6)
monthly_ltc_cost_current = st.sidebar.number_input("Current Monthly LTC Cost ($)", value=7500)
cognitive_risk_multiplier = st.sidebar.slider("Cognitive Risk Multiplier", 1.0, 3.0, 2.0)

st.sidebar.header("Financial & Asset Variables")
initial_457_asset = st.sidebar.number_input("Current 457(b) Balance ($)", value=25000)
monthly_contribution = st.sidebar.number_input("Monthly Capital Allocation ($)", value=250)
market_return = st.sidebar.slider("Est. Market Return (%)", 2.0, 12.0, 7.0) / 100
healthcare_inflation = st.sidebar.slider("Healthcare Inflation (%)", 2.0, 8.0, 3.5) / 100

st.sidebar.header("Liability: College Expenses (2030-2036)")
college_annual_cost = st.sidebar.number_input("Annual College Cost ($)", value=35000)
college_years = st.sidebar.multiselect("Active College Years", 
                                       [2030, 2031, 2032, 2033, 2034, 2035, 2036], 
                                       default=[2030, 2031, 2032, 2033, 2034, 2035])

# --- CALCULATIONS ---
current_year = 2026
years_to_model = max(mortality_primary, mortality_spouse) - current_age_primary
years_array = np.arange(0, years_to_model + 1)
actual_years = current_year + years_array
ages_array = current_age_primary + years_array

# 1. Liability: College
college_drain = np.zeros(len(years_array))
for i, yr in enumerate(actual_years):
    if yr in college_years:
        # Assuming overlapping years double the cost (Sullivan & August)
        overlap_multiplier = 2 if (yr >= 2032 and yr <= 2034) else 1
        college_drain[i] = college_annual_cost * overlap_multiplier

# 2. Liability: LTC
ltc_drain = np.zeros(len(years_array))
future_monthly_ltc = monthly_ltc_cost_current * ((1 + healthcare_inflation) ** (onset_age - current_age_primary))
for i, age in enumerate(ages_array):
    if onset_age <= age < (onset_age + duration_years):
        ltc_drain[i] = future_monthly_ltc * 12

# 3. Model: Self-Funded (457b Growth)
self_fund_value = np.zeros(len(years_array))
self_fund_value[0] = initial_457_asset
for i in range(1, len(years_array)):
    growth = self_fund_value[i-1] * (1 + market_return)
    contribution = (monthly_contribution * 12)
    # Deduct liabilities (LTC only; assuming college paid from standard cash flow, but visualized)
    net_value = growth + contribution - ltc_drain[i]
    self_fund_value[i] = max(0, net_value)

# 4. Model: Hybrid Policy (OneAmerica equivalent)
hybrid_value = np.zeros(len(years_array))
hybrid_death_benefit = 150000 # Estimated base
hybrid_ltc_pool = np.full(len(years_array), float('inf')) # Unlimited rider
hybrid_out_of_pocket = np.zeros(len(years_array))

for i, age in enumerate(ages_array):
    if onset_age <= age < (onset_age + duration_years):
        # Policy covers 100% of LTC, 0 out of pocket
        hybrid_out_of_pocket[i] = 0
    
    if age >= mortality_primary:
        hybrid_value[i] = hybrid_death_benefit if ltc_drain[i-1] == 0 else 0
    else:
        hybrid_value[i] = 0 # Illiquid during life

# --- DATA AGGREGATION ---
df = pd.DataFrame({
    "Year": actual_years,
    "Age": ages_array,
    "Self-Funded Balance ($)": self_fund_value,
    "LTC Annual Cost ($)": ltc_drain,
    "College Annual Cost ($)": college_drain
})

# --- UI RENDERING ---
col1, col2, col3 = st.columns(3)
col1.metric("Total LTC Liability", f"${np.sum(ltc_drain):,.0f}")
col2.metric("Total College Liability", f"${np.sum(college_drain):,.0f}")
col3.metric("Self-Funded Estate @ Mortality", f"${self_fund_value[-1]:,.0f}")

st.markdown("### Projected Estate Asset Valuation vs. Liabilities")
fig = px.line(df, x="Age", y=["Self-Funded Balance ($)", "LTC Annual Cost ($)"], 
              title="Self-Funded Asset Depletion vs. Uncapped Memory Care Costs")
st.plotly_chart(fig, use_container_width=True)

st.markdown("### Risk Analysis & Financial Aid Impact")
st.markdown(f"""
* **FAFSA Asset Sheltering:** Initiating the hybrid policy in {current_year} removes the `{initial_457_asset}` asset from the expected family contribution calculation for the {college_years} academic years.
* **Opportunity Cost:** At a `{market_return*100}%` return, allocating `{monthly_contribution}/mo` to the hybrid policy sacrifices `{np.sum(self_fund_value) - hybrid_death_benefit:,.0f}` in compounding capital by age {mortality_primary}.
* **Cognitive Outlier Risk:** Due to the requested Cognitive Risk Multiplier of `{cognitive_risk_multiplier}`, the projected `{duration_years}` year duration mathematically exhausts the self-funded portfolio at age `{ages_array[np.where(self_fund_value == 0)[0][0]] if 0 in self_fund_value else "N/A"}`.
""")