From cbb32727d8f477d4f937e668ba44d2468e2b6de5 Mon Sep 17 00:00:00 2001 From: Emil Lerch Date: Wed, 13 May 2026 11:15:04 -0700 Subject: [PATCH] adding previously ignored example files --- .gitignore | 3 + examples/post-retirement/accounts.srf | 9 + .../history/2024-04-01-portfolio.srf | 37 ++ .../history/2024-10-01-portfolio.srf | 16 + .../history/2025-04-01-portfolio.srf | 16 + .../history/imported_values.srf | 441 ++++++++++++++++++ examples/post-retirement/portfolio.srf | 35 ++ examples/post-retirement/projections.srf | 32 ++ examples/pre-retirement-age/accounts.srf | 11 + examples/pre-retirement-age/portfolio.srf | 39 ++ examples/pre-retirement-age/projections.srf | 38 ++ examples/pre-retirement-both/accounts.srf | 11 + examples/pre-retirement-both/portfolio.srf | 39 ++ examples/pre-retirement-both/projections.srf | 50 ++ .../accounts.srf | 11 + .../portfolio.srf | 39 ++ .../projections.srf | 73 +++ examples/pre-retirement-spending/accounts.srf | 11 + .../pre-retirement-spending/portfolio.srf | 39 ++ .../pre-retirement-spending/projections.srf | 47 ++ 20 files changed, 997 insertions(+) create mode 100644 examples/post-retirement/accounts.srf create mode 100644 examples/post-retirement/history/2024-04-01-portfolio.srf create mode 100644 examples/post-retirement/history/2024-10-01-portfolio.srf create mode 100644 examples/post-retirement/history/2025-04-01-portfolio.srf create mode 100644 examples/post-retirement/history/imported_values.srf create mode 100644 examples/post-retirement/portfolio.srf create mode 100644 examples/post-retirement/projections.srf create mode 100644 examples/pre-retirement-age/accounts.srf create mode 100644 examples/pre-retirement-age/portfolio.srf create mode 100644 examples/pre-retirement-age/projections.srf create mode 100644 examples/pre-retirement-both/accounts.srf create mode 100644 examples/pre-retirement-both/portfolio.srf create mode 100644 examples/pre-retirement-both/projections.srf create mode 100644 examples/pre-retirement-spending-target/accounts.srf create mode 100644 examples/pre-retirement-spending-target/portfolio.srf create mode 100644 examples/pre-retirement-spending-target/projections.srf create mode 100644 examples/pre-retirement-spending/accounts.srf create mode 100644 examples/pre-retirement-spending/portfolio.srf create mode 100644 examples/pre-retirement-spending/projections.srf diff --git a/.gitignore b/.gitignore index 17e2993..5ce9a82 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,7 @@ coverage/ .env *.srf !metadata.srf +# Example fixtures should ship with the repo so new users can run +# `ZFIN_HOME=examples/ zfin projections` immediately. +!examples/**/*.srf scripts/ diff --git a/examples/post-retirement/accounts.srf b/examples/post-retirement/accounts.srf new file mode 100644 index 0000000..adde32d --- /dev/null +++ b/examples/post-retirement/accounts.srf @@ -0,0 +1,9 @@ +#!srfv1 +# Account tax type classification for the post-retirement example. + +account::Robin Trad IRA,tax_type::traditional,institution::fidelity,account_number::RTRA +account::Robin Roth,tax_type::roth,institution::fidelity,account_number::RROT +account::Jamie Trad IRA,tax_type::traditional,institution::vanguard,account_number::JTRA +account::Jamie Roth,tax_type::roth,institution::vanguard,account_number::JROT +account::Joint taxable,tax_type::taxable,institution::schwab,account_number::JT01 +account::Family HSA,tax_type::hsa,institution::fidelity,account_number::HSA01 diff --git a/examples/post-retirement/history/2024-04-01-portfolio.srf b/examples/post-retirement/history/2024-04-01-portfolio.srf new file mode 100644 index 0000000..dfe8837 --- /dev/null +++ b/examples/post-retirement/history/2024-04-01-portfolio.srf @@ -0,0 +1,37 @@ +#!srfv1 +# Synthetic snapshot for the projection-overlay demo. Real users land +# real snapshot files here via `zfin snapshot`; this fixture is shaped +# the same way but the totals are made up so the example renders with +# meaningful numbers. +kind::meta,snapshot_version:num:1,as_of_date::2024-04-01,captured_at:num:1711929600,zfin_version::example,stale_count:num:0 +kind::total,scope::net_worth,value:num:2350000.00 +kind::total,scope::liquid,value:num:2350000.00 +kind::total,scope::illiquid,value:num:0 +kind::tax_type,label::Traditional (Pre-Tax),value:num:1450000.00 +kind::tax_type,label::Roth (Post-Tax),value:num:480000.00 +kind::tax_type,label::Taxable,value:num:380000.00 +kind::tax_type,label::HSA (Triple Tax-Free),value:num:40000.00 +kind::account,name::Robin Trad IRA,value:num:980000.00 +kind::account,name::Jamie Trad IRA,value:num:470000.00 +kind::account,name::Robin Roth,value:num:280000.00 +kind::account,name::Jamie Roth,value:num:200000.00 +kind::account,name::Joint taxable,value:num:380000.00 +kind::account,name::Family HSA,value:num:40000.00 +kind::lot,symbol::VTI,lot_symbol::VTI,account::Robin Trad IRA,security_type::Stock,shares:num:1800,open_price:num:60.20,cost_basis:num:108360.00,value:num:455400.00,price:num:253.00,quote_date::2024-04-01 +kind::lot,symbol::AGG,lot_symbol::AGG,account::Robin Trad IRA,security_type::Stock,shares:num:1400,open_price:num:107.40,cost_basis:num:150360.00,value:num:138600.00,price:num:99.00,quote_date::2024-04-01 +kind::lot,symbol::SCHD,lot_symbol::SCHD,account::Robin Trad IRA,security_type::Stock,shares:num:600,open_price:num:53.10,cost_basis:num:31860.00,value:num:46500.00,price:num:77.50,quote_date::2024-04-01 +kind::lot,symbol::cash,lot_symbol::cash,account::Robin Trad IRA,security_type::Cash,shares:num:18500,open_price:num:1.00,cost_basis:num:18500.00,value:num:18500.00,price:num:1.00,quote_date::2024-04-01 +kind::lot,symbol::VTI,lot_symbol::VTI,account::Robin Roth,security_type::Stock,shares:num:380,open_price:num:71.50,cost_basis:num:27170.00,value:num:96140.00,price:num:253.00,quote_date::2024-04-01 +kind::lot,symbol::QQQ,lot_symbol::QQQ,account::Robin Roth,security_type::Stock,shares:num:140,open_price:num:97.30,cost_basis:num:13622.00,value:num:62300.00,price:num:445.00,quote_date::2024-04-01 +kind::lot,symbol::cash,lot_symbol::cash,account::Robin Roth,security_type::Cash,shares:num:1240,open_price:num:1.00,cost_basis:num:1240.00,value:num:1240.00,price:num:1.00,quote_date::2024-04-01 +kind::lot,symbol::VTI,lot_symbol::VTI,account::Jamie Trad IRA,security_type::Stock,shares:num:920,open_price:num:64.80,cost_basis:num:59616.00,value:num:232760.00,price:num:253.00,quote_date::2024-04-01 +kind::lot,symbol::AGG,lot_symbol::AGG,account::Jamie Trad IRA,security_type::Stock,shares:num:850,open_price:num:108.10,cost_basis:num:91885.00,value:num:84150.00,price:num:99.00,quote_date::2024-04-01 +kind::lot,symbol::cash,lot_symbol::cash,account::Jamie Trad IRA,security_type::Cash,shares:num:9800,open_price:num:1.00,cost_basis:num:9800.00,value:num:9800.00,price:num:1.00,quote_date::2024-04-01 +kind::lot,symbol::SPY,lot_symbol::SPY,account::Jamie Roth,security_type::Stock,shares:num:200,open_price:num:152.20,cost_basis:num:30440.00,value:num:104000.00,price:num:520.00,quote_date::2024-04-01 +kind::lot,symbol::SCHD,lot_symbol::SCHD,account::Jamie Roth,security_type::Stock,shares:num:280,open_price:num:55.40,cost_basis:num:15512.00,value:num:21700.00,price:num:77.50,quote_date::2024-04-01 +kind::lot,symbol::cash,lot_symbol::cash,account::Jamie Roth,security_type::Cash,shares:num:715,open_price:num:1.00,cost_basis:num:715.00,value:num:715.00,price:num:1.00,quote_date::2024-04-01 +kind::lot,symbol::SPY,lot_symbol::SPY,account::Joint taxable,security_type::Stock,shares:num:240,open_price:num:198.40,cost_basis:num:47616.00,value:num:124800.00,price:num:520.00,quote_date::2024-04-01 +kind::lot,symbol::AGG,lot_symbol::AGG,account::Joint taxable,security_type::Stock,shares:num:600,open_price:num:106.90,cost_basis:num:64140.00,value:num:59400.00,price:num:99.00,quote_date::2024-04-01 +kind::lot,symbol::cash,lot_symbol::cash,account::Joint taxable,security_type::Cash,shares:num:62000,open_price:num:1.00,cost_basis:num:62000.00,value:num:62000.00,price:num:1.00,quote_date::2024-04-01 +kind::lot,symbol::VTI,lot_symbol::VTI,account::Family HSA,security_type::Stock,shares:num:140,open_price:num:108.30,cost_basis:num:15162.00,value:num:35420.00,price:num:253.00,quote_date::2024-04-01 +kind::lot,symbol::cash,lot_symbol::cash,account::Family HSA,security_type::Cash,shares:num:4200,open_price:num:1.00,cost_basis:num:4200.00,value:num:4200.00,price:num:1.00,quote_date::2024-04-01 diff --git a/examples/post-retirement/history/2024-10-01-portfolio.srf b/examples/post-retirement/history/2024-10-01-portfolio.srf new file mode 100644 index 0000000..7f779b6 --- /dev/null +++ b/examples/post-retirement/history/2024-10-01-portfolio.srf @@ -0,0 +1,16 @@ +#!srfv1 +# Synthetic snapshot — see 2024-04-01-portfolio.srf for the framing. +kind::meta,snapshot_version:num:1,as_of_date::2024-10-01,captured_at:num:1727740800,zfin_version::example,stale_count:num:0 +kind::total,scope::net_worth,value:num:2470000.00 +kind::total,scope::liquid,value:num:2470000.00 +kind::total,scope::illiquid,value:num:0 +kind::tax_type,label::Traditional (Pre-Tax),value:num:1520000.00 +kind::tax_type,label::Roth (Post-Tax),value:num:505000.00 +kind::tax_type,label::Taxable,value:num:402000.00 +kind::tax_type,label::HSA (Triple Tax-Free),value:num:43000.00 +kind::account,name::Robin Trad IRA,value:num:1030000.00 +kind::account,name::Jamie Trad IRA,value:num:490000.00 +kind::account,name::Robin Roth,value:num:295000.00 +kind::account,name::Jamie Roth,value:num:210000.00 +kind::account,name::Joint taxable,value:num:402000.00 +kind::account,name::Family HSA,value:num:43000.00 diff --git a/examples/post-retirement/history/2025-04-01-portfolio.srf b/examples/post-retirement/history/2025-04-01-portfolio.srf new file mode 100644 index 0000000..2b3f94e --- /dev/null +++ b/examples/post-retirement/history/2025-04-01-portfolio.srf @@ -0,0 +1,16 @@ +#!srfv1 +# Synthetic snapshot — see 2024-04-01-portfolio.srf for the framing. +kind::meta,snapshot_version:num:1,as_of_date::2025-04-01,captured_at:num:1743465600,zfin_version::example,stale_count:num:0 +kind::total,scope::net_worth,value:num:2580000.00 +kind::total,scope::liquid,value:num:2580000.00 +kind::total,scope::illiquid,value:num:0 +kind::tax_type,label::Traditional (Pre-Tax),value:num:1590000.00 +kind::tax_type,label::Roth (Post-Tax),value:num:528000.00 +kind::tax_type,label::Taxable,value:num:418000.00 +kind::tax_type,label::HSA (Triple Tax-Free),value:num:44000.00 +kind::account,name::Robin Trad IRA,value:num:1075000.00 +kind::account,name::Jamie Trad IRA,value:num:515000.00 +kind::account,name::Robin Roth,value:num:308000.00 +kind::account,name::Jamie Roth,value:num:220000.00 +kind::account,name::Joint taxable,value:num:418000.00 +kind::account,name::Family HSA,value:num:44000.00 diff --git a/examples/post-retirement/history/imported_values.srf b/examples/post-retirement/history/imported_values.srf new file mode 100644 index 0000000..b543837 --- /dev/null +++ b/examples/post-retirement/history/imported_values.srf @@ -0,0 +1,441 @@ +#!srfv1 +# Synthetic imported_values for the projection-overlay demo. +# One row per week, 2016-01-03 through 2024-03-31, geometric +# growth from $1.5M to $2.35M with light noise. The post- +# retirement household had a longer accumulation history before +# the household-wide retirement on 2023-12-31; the overlay shows +# how the trajectory looked relative to projections from any +# past as-of date. +# +# All numbers fictional. +date::2016-01-03,liquid:num:1506274.21 +date::2016-01-10,liquid:num:1480170.08 +date::2016-01-17,liquid:num:1492990.64 +date::2016-01-24,liquid:num:1492211.09 +date::2016-01-31,liquid:num:1516963.26 +date::2016-02-07,liquid:num:1515844.10 +date::2016-02-14,liquid:num:1527185.11 +date::2016-02-21,liquid:num:1492278.80 +date::2016-02-28,liquid:num:1509038.33 +date::2016-03-06,liquid:num:1492802.49 +date::2016-03-13,liquid:num:1502948.92 +date::2016-03-20,liquid:num:1517570.24 +date::2016-03-27,liquid:num:1497336.99 +date::2016-04-03,liquid:num:1506760.66 +date::2016-04-10,liquid:num:1528930.61 +date::2016-04-17,liquid:num:1525730.79 +date::2016-04-24,liquid:num:1512476.06 +date::2016-05-01,liquid:num:1530950.36 +date::2016-05-08,liquid:num:1542644.98 +date::2016-05-15,liquid:num:1507400.61 +date::2016-05-22,liquid:num:1545703.68 +date::2016-05-29,liquid:num:1542365.33 +date::2016-06-05,liquid:num:1527497.31 +date::2016-06-12,liquid:num:1520576.18 +date::2016-06-19,liquid:num:1559158.06 +date::2016-06-26,liquid:num:1532120.38 +date::2016-07-03,liquid:num:1522445.71 +date::2016-07-10,liquid:num:1524219.86 +date::2016-07-17,liquid:num:1560599.35 +date::2016-07-24,liquid:num:1550922.78 +date::2016-07-31,liquid:num:1561987.23 +date::2016-08-07,liquid:num:1560021.49 +date::2016-08-14,liquid:num:1552647.61 +date::2016-08-21,liquid:num:1574618.65 +date::2016-08-28,liquid:num:1548540.50 +date::2016-09-04,liquid:num:1558256.50 +date::2016-09-11,liquid:num:1572843.72 +date::2016-09-18,liquid:num:1564623.15 +date::2016-09-25,liquid:num:1577643.90 +date::2016-10-02,liquid:num:1565964.18 +date::2016-10-09,liquid:num:1573569.05 +date::2016-10-16,liquid:num:1544272.68 +date::2016-10-23,liquid:num:1554446.46 +date::2016-10-30,liquid:num:1558964.35 +date::2016-11-06,liquid:num:1550717.65 +date::2016-11-13,liquid:num:1559553.71 +date::2016-11-20,liquid:num:1554960.54 +date::2016-11-27,liquid:num:1564949.16 +date::2016-12-04,liquid:num:1583508.18 +date::2016-12-11,liquid:num:1572334.21 +date::2016-12-18,liquid:num:1574230.29 +date::2016-12-25,liquid:num:1568249.00 +date::2017-01-01,liquid:num:1572617.69 +date::2017-01-08,liquid:num:1606110.49 +date::2017-01-15,liquid:num:1594047.11 +date::2017-01-22,liquid:num:1593858.10 +date::2017-01-29,liquid:num:1574626.68 +date::2017-02-05,liquid:num:1602920.70 +date::2017-02-12,liquid:num:1577548.29 +date::2017-02-19,liquid:num:1589536.34 +date::2017-02-26,liquid:num:1620424.63 +date::2017-03-05,liquid:num:1605354.48 +date::2017-03-12,liquid:num:1603044.29 +date::2017-03-19,liquid:num:1610854.34 +date::2017-03-26,liquid:num:1620149.82 +date::2017-04-02,liquid:num:1618622.67 +date::2017-04-09,liquid:num:1593944.83 +date::2017-04-16,liquid:num:1586105.08 +date::2017-04-23,liquid:num:1601451.00 +date::2017-04-30,liquid:num:1600816.47 +date::2017-05-07,liquid:num:1599740.94 +date::2017-05-14,liquid:num:1636883.10 +date::2017-05-21,liquid:num:1635364.85 +date::2017-05-28,liquid:num:1609795.36 +date::2017-06-04,liquid:num:1628042.92 +date::2017-06-11,liquid:num:1617100.00 +date::2017-06-18,liquid:num:1644068.86 +date::2017-06-25,liquid:num:1623563.32 +date::2017-07-02,liquid:num:1615790.00 +date::2017-07-09,liquid:num:1616585.89 +date::2017-07-16,liquid:num:1633671.74 +date::2017-07-23,liquid:num:1620754.20 +date::2017-07-30,liquid:num:1638224.83 +date::2017-08-06,liquid:num:1655307.80 +date::2017-08-13,liquid:num:1632552.05 +date::2017-08-20,liquid:num:1625401.81 +date::2017-08-27,liquid:num:1665409.40 +date::2017-09-03,liquid:num:1643100.44 +date::2017-09-10,liquid:num:1624166.31 +date::2017-09-17,liquid:num:1623700.35 +date::2017-09-24,liquid:num:1628487.71 +date::2017-10-01,liquid:num:1655812.12 +date::2017-10-08,liquid:num:1665697.22 +date::2017-10-15,liquid:num:1649093.45 +date::2017-10-22,liquid:num:1633013.47 +date::2017-10-29,liquid:num:1650526.03 +date::2017-11-05,liquid:num:1682818.09 +date::2017-11-12,liquid:num:1661320.84 +date::2017-11-19,liquid:num:1685087.37 +date::2017-11-26,liquid:num:1681343.71 +date::2017-12-03,liquid:num:1640675.61 +date::2017-12-10,liquid:num:1677854.74 +date::2017-12-17,liquid:num:1677654.66 +date::2017-12-24,liquid:num:1672154.38 +date::2017-12-31,liquid:num:1660350.28 +date::2018-01-07,liquid:num:1680871.53 +date::2018-01-14,liquid:num:1656015.95 +date::2018-01-21,liquid:num:1674009.54 +date::2018-01-28,liquid:num:1676713.19 +date::2018-02-04,liquid:num:1703681.34 +date::2018-02-11,liquid:num:1701525.72 +date::2018-02-18,liquid:num:1672355.76 +date::2018-02-25,liquid:num:1686100.66 +date::2018-03-04,liquid:num:1671560.86 +date::2018-03-11,liquid:num:1710510.67 +date::2018-03-18,liquid:num:1710160.84 +date::2018-03-25,liquid:num:1682889.49 +date::2018-04-01,liquid:num:1701961.06 +date::2018-04-08,liquid:num:1702213.01 +date::2018-04-15,liquid:num:1680749.85 +date::2018-04-22,liquid:num:1713602.74 +date::2018-04-29,liquid:num:1703999.76 +date::2018-05-06,liquid:num:1718008.44 +date::2018-05-13,liquid:num:1707099.87 +date::2018-05-20,liquid:num:1681747.79 +date::2018-05-27,liquid:num:1700095.81 +date::2018-06-03,liquid:num:1686233.51 +date::2018-06-10,liquid:num:1734731.84 +date::2018-06-17,liquid:num:1733952.88 +date::2018-06-24,liquid:num:1733341.36 +date::2018-07-01,liquid:num:1708136.36 +date::2018-07-08,liquid:num:1697043.03 +date::2018-07-15,liquid:num:1741172.70 +date::2018-07-22,liquid:num:1746555.99 +date::2018-07-29,liquid:num:1703802.00 +date::2018-08-05,liquid:num:1726323.88 +date::2018-08-12,liquid:num:1706510.78 +date::2018-08-19,liquid:num:1744190.23 +date::2018-08-26,liquid:num:1746284.18 +date::2018-09-02,liquid:num:1714943.29 +date::2018-09-09,liquid:num:1734801.75 +date::2018-09-16,liquid:num:1740499.27 +date::2018-09-23,liquid:num:1727456.04 +date::2018-09-30,liquid:num:1760993.60 +date::2018-10-07,liquid:num:1739334.74 +date::2018-10-14,liquid:num:1730086.92 +date::2018-10-21,liquid:num:1749058.35 +date::2018-10-28,liquid:num:1760887.05 +date::2018-11-04,liquid:num:1734955.23 +date::2018-11-11,liquid:num:1742580.49 +date::2018-11-18,liquid:num:1780369.42 +date::2018-11-25,liquid:num:1764038.85 +date::2018-12-02,liquid:num:1754712.57 +date::2018-12-09,liquid:num:1760741.45 +date::2018-12-16,liquid:num:1741622.11 +date::2018-12-23,liquid:num:1748927.30 +date::2018-12-30,liquid:num:1756759.30 +date::2019-01-06,liquid:num:1771860.10 +date::2019-01-13,liquid:num:1754701.40 +date::2019-01-20,liquid:num:1756008.58 +date::2019-01-27,liquid:num:1749906.94 +date::2019-02-03,liquid:num:1781553.61 +date::2019-02-10,liquid:num:1761982.34 +date::2019-02-17,liquid:num:1799912.03 +date::2019-02-24,liquid:num:1799347.16 +date::2019-03-03,liquid:num:1759058.69 +date::2019-03-10,liquid:num:1769841.27 +date::2019-03-17,liquid:num:1794778.06 +date::2019-03-24,liquid:num:1772266.19 +date::2019-03-31,liquid:num:1769719.49 +date::2019-04-07,liquid:num:1814732.12 +date::2019-04-14,liquid:num:1797020.74 +date::2019-04-21,liquid:num:1793600.39 +date::2019-04-28,liquid:num:1812290.66 +date::2019-05-05,liquid:num:1815418.39 +date::2019-05-12,liquid:num:1783979.07 +date::2019-05-19,liquid:num:1780787.53 +date::2019-05-26,liquid:num:1800735.05 +date::2019-06-02,liquid:num:1802211.18 +date::2019-06-09,liquid:num:1806450.62 +date::2019-06-16,liquid:num:1822568.06 +date::2019-06-23,liquid:num:1821443.44 +date::2019-06-30,liquid:num:1840259.10 +date::2019-07-07,liquid:num:1793931.08 +date::2019-07-14,liquid:num:1812393.60 +date::2019-07-21,liquid:num:1810830.41 +date::2019-07-28,liquid:num:1841266.99 +date::2019-08-04,liquid:num:1809657.08 +date::2019-08-11,liquid:num:1808346.93 +date::2019-08-18,liquid:num:1824400.81 +date::2019-08-25,liquid:num:1824839.72 +date::2019-09-01,liquid:num:1818872.35 +date::2019-09-08,liquid:num:1819192.07 +date::2019-09-15,liquid:num:1858163.62 +date::2019-09-22,liquid:num:1833647.60 +date::2019-09-29,liquid:num:1858632.40 +date::2019-10-06,liquid:num:1843399.65 +date::2019-10-13,liquid:num:1817701.68 +date::2019-10-20,liquid:num:1872095.57 +date::2019-10-27,liquid:num:1865008.20 +date::2019-11-03,liquid:num:1874329.49 +date::2019-11-10,liquid:num:1873921.19 +date::2019-11-17,liquid:num:1871562.87 +date::2019-11-24,liquid:num:1835561.20 +date::2019-12-01,liquid:num:1855259.51 +date::2019-12-08,liquid:num:1842042.20 +date::2019-12-15,liquid:num:1854417.03 +date::2019-12-22,liquid:num:1837228.66 +date::2019-12-29,liquid:num:1857059.48 +date::2020-01-05,liquid:num:1892937.95 +date::2020-01-12,liquid:num:1854566.61 +date::2020-01-19,liquid:num:1885607.31 +date::2020-01-26,liquid:num:1869100.59 +date::2020-02-02,liquid:num:1869254.39 +date::2020-02-09,liquid:num:1901270.63 +date::2020-02-16,liquid:num:1905402.99 +date::2020-02-23,liquid:num:1882604.03 +date::2020-03-01,liquid:num:1893750.46 +date::2020-03-08,liquid:num:1863883.73 +date::2020-03-15,liquid:num:1873857.35 +date::2020-03-22,liquid:num:1913863.37 +date::2020-03-29,liquid:num:1893784.55 +date::2020-04-05,liquid:num:1893664.36 +date::2020-04-12,liquid:num:1907330.29 +date::2020-04-19,liquid:num:1870045.52 +date::2020-04-26,liquid:num:1901994.49 +date::2020-05-03,liquid:num:1899347.68 +date::2020-05-10,liquid:num:1921286.60 +date::2020-05-17,liquid:num:1883596.42 +date::2020-05-24,liquid:num:1931478.74 +date::2020-05-31,liquid:num:1883109.89 +date::2020-06-07,liquid:num:1891131.62 +date::2020-06-14,liquid:num:1916568.62 +date::2020-06-21,liquid:num:1923172.36 +date::2020-06-28,liquid:num:1899901.32 +date::2020-07-05,liquid:num:1895253.69 +date::2020-07-12,liquid:num:1941588.20 +date::2020-07-19,liquid:num:1906496.17 +date::2020-07-26,liquid:num:1928582.73 +date::2020-08-02,liquid:num:1932033.26 +date::2020-08-09,liquid:num:1922479.54 +date::2020-08-16,liquid:num:1934005.17 +date::2020-08-23,liquid:num:1932497.80 +date::2020-08-30,liquid:num:1958406.38 +date::2020-09-06,liquid:num:1918045.00 +date::2020-09-13,liquid:num:1949800.65 +date::2020-09-20,liquid:num:1924057.21 +date::2020-09-27,liquid:num:1935216.38 +date::2020-10-04,liquid:num:1953323.00 +date::2020-10-11,liquid:num:1933671.34 +date::2020-10-18,liquid:num:1936636.55 +date::2020-10-25,liquid:num:1964139.59 +date::2020-11-01,liquid:num:1926421.58 +date::2020-11-08,liquid:num:1951040.21 +date::2020-11-15,liquid:num:1984767.72 +date::2020-11-22,liquid:num:1986702.56 +date::2020-11-29,liquid:num:1934525.87 +date::2020-12-06,liquid:num:1944779.41 +date::2020-12-13,liquid:num:1949877.06 +date::2020-12-20,liquid:num:1991311.26 +date::2020-12-27,liquid:num:1990298.29 +date::2021-01-03,liquid:num:1992283.19 +date::2021-01-10,liquid:num:1964209.07 +date::2021-01-17,liquid:num:1953719.36 +date::2021-01-24,liquid:num:1995834.42 +date::2021-01-31,liquid:num:1990192.49 +date::2021-02-07,liquid:num:1986814.37 +date::2021-02-14,liquid:num:2011223.14 +date::2021-02-21,liquid:num:1993485.46 +date::2021-02-28,liquid:num:1957062.48 +date::2021-03-07,liquid:num:2007383.72 +date::2021-03-14,liquid:num:1978564.00 +date::2021-03-21,liquid:num:2002390.89 +date::2021-03-28,liquid:num:2020971.33 +date::2021-04-04,liquid:num:1974881.64 +date::2021-04-11,liquid:num:1975813.53 +date::2021-04-18,liquid:num:1977373.69 +date::2021-04-25,liquid:num:2006251.41 +date::2021-05-02,liquid:num:1991451.29 +date::2021-05-09,liquid:num:2013552.70 +date::2021-05-16,liquid:num:2022454.62 +date::2021-05-23,liquid:num:1993550.07 +date::2021-05-30,liquid:num:2021645.89 +date::2021-06-06,liquid:num:2001368.76 +date::2021-06-13,liquid:num:2017051.85 +date::2021-06-20,liquid:num:2044415.42 +date::2021-06-27,liquid:num:2042958.06 +date::2021-07-04,liquid:num:1999319.39 +date::2021-07-11,liquid:num:2021544.84 +date::2021-07-18,liquid:num:2014718.10 +date::2021-07-25,liquid:num:2000185.32 +date::2021-08-01,liquid:num:2049078.62 +date::2021-08-08,liquid:num:2043039.39 +date::2021-08-15,liquid:num:2022249.97 +date::2021-08-22,liquid:num:2053678.63 +date::2021-08-29,liquid:num:2044217.45 +date::2021-09-05,liquid:num:2038752.62 +date::2021-09-12,liquid:num:2015232.97 +date::2021-09-19,liquid:num:2021365.92 +date::2021-09-26,liquid:num:2073151.20 +date::2021-10-03,liquid:num:2076598.49 +date::2021-10-10,liquid:num:2056688.24 +date::2021-10-17,liquid:num:2076662.71 +date::2021-10-24,liquid:num:2063266.96 +date::2021-10-31,liquid:num:2038571.19 +date::2021-11-07,liquid:num:2039423.11 +date::2021-11-14,liquid:num:2052752.87 +date::2021-11-21,liquid:num:2091524.16 +date::2021-11-28,liquid:num:2087324.69 +date::2021-12-05,liquid:num:2093517.72 +date::2021-12-12,liquid:num:2098081.98 +date::2021-12-19,liquid:num:2057383.88 +date::2021-12-26,liquid:num:2061992.10 +date::2022-01-02,liquid:num:2054990.75 +date::2022-01-09,liquid:num:2099441.91 +date::2022-01-16,liquid:num:2108138.63 +date::2022-01-23,liquid:num:2080438.49 +date::2022-01-30,liquid:num:2096037.58 +date::2022-02-06,liquid:num:2068992.93 +date::2022-02-13,liquid:num:2119833.41 +date::2022-02-20,liquid:num:2117945.21 +date::2022-02-27,liquid:num:2127179.16 +date::2022-03-06,liquid:num:2118981.81 +date::2022-03-13,liquid:num:2125649.33 +date::2022-03-20,liquid:num:2073804.56 +date::2022-03-27,liquid:num:2120940.92 +date::2022-04-03,liquid:num:2097581.19 +date::2022-04-10,liquid:num:2137672.79 +date::2022-04-17,liquid:num:2131756.64 +date::2022-04-24,liquid:num:2137906.20 +date::2022-05-01,liquid:num:2136753.44 +date::2022-05-08,liquid:num:2104403.29 +date::2022-05-15,liquid:num:2139732.30 +date::2022-05-22,liquid:num:2098690.79 +date::2022-05-29,liquid:num:2149612.76 +date::2022-06-05,liquid:num:2150991.71 +date::2022-06-12,liquid:num:2112581.95 +date::2022-06-19,liquid:num:2152800.54 +date::2022-06-26,liquid:num:2132231.85 +date::2022-07-03,liquid:num:2124514.94 +date::2022-07-10,liquid:num:2158190.94 +date::2022-07-17,liquid:num:2123970.82 +date::2022-07-24,liquid:num:2113074.49 +date::2022-07-31,liquid:num:2126191.75 +date::2022-08-07,liquid:num:2137121.49 +date::2022-08-14,liquid:num:2173938.80 +date::2022-08-21,liquid:num:2182831.55 +date::2022-08-28,liquid:num:2140649.30 +date::2022-09-04,liquid:num:2166335.51 +date::2022-09-11,liquid:num:2152933.75 +date::2022-09-18,liquid:num:2192891.54 +date::2022-09-25,liquid:num:2166297.87 +date::2022-10-02,liquid:num:2194751.65 +date::2022-10-09,liquid:num:2143446.55 +date::2022-10-16,liquid:num:2201368.82 +date::2022-10-23,liquid:num:2152048.75 +date::2022-10-30,liquid:num:2205457.05 +date::2022-11-06,liquid:num:2162223.99 +date::2022-11-13,liquid:num:2154211.56 +date::2022-11-20,liquid:num:2177813.35 +date::2022-11-27,liquid:num:2199353.30 +date::2022-12-04,liquid:num:2174435.56 +date::2022-12-11,liquid:num:2195917.05 +date::2022-12-18,liquid:num:2191980.02 +date::2022-12-25,liquid:num:2185963.32 +date::2023-01-01,liquid:num:2200854.66 +date::2023-01-08,liquid:num:2181928.89 +date::2023-01-15,liquid:num:2214181.76 +date::2023-01-22,liquid:num:2169769.29 +date::2023-01-29,liquid:num:2233150.75 +date::2023-02-05,liquid:num:2209848.60 +date::2023-02-12,liquid:num:2224153.76 +date::2023-02-19,liquid:num:2227971.52 +date::2023-02-26,liquid:num:2225561.23 +date::2023-03-05,liquid:num:2207511.18 +date::2023-03-12,liquid:num:2190230.39 +date::2023-03-19,liquid:num:2232117.23 +date::2023-03-26,liquid:num:2212167.02 +date::2023-04-02,liquid:num:2213390.50 +date::2023-04-09,liquid:num:2251404.12 +date::2023-04-16,liquid:num:2245173.51 +date::2023-04-23,liquid:num:2219423.64 +date::2023-04-30,liquid:num:2222343.04 +date::2023-05-07,liquid:num:2231317.08 +date::2023-05-14,liquid:num:2233245.28 +date::2023-05-21,liquid:num:2228398.03 +date::2023-05-28,liquid:num:2219388.90 +date::2023-06-04,liquid:num:2241467.63 +date::2023-06-11,liquid:num:2278890.69 +date::2023-06-18,liquid:num:2263503.62 +date::2023-06-25,liquid:num:2281114.76 +date::2023-07-02,liquid:num:2264051.81 +date::2023-07-09,liquid:num:2245102.67 +date::2023-07-16,liquid:num:2264200.71 +date::2023-07-23,liquid:num:2229388.93 +date::2023-07-30,liquid:num:2251191.79 +date::2023-08-06,liquid:num:2263271.58 +date::2023-08-13,liquid:num:2275859.26 +date::2023-08-20,liquid:num:2283331.39 +date::2023-08-27,liquid:num:2272767.48 +date::2023-09-03,liquid:num:2273581.88 +date::2023-09-10,liquid:num:2260330.94 +date::2023-09-17,liquid:num:2280458.73 +date::2023-09-24,liquid:num:2312175.85 +date::2023-10-01,liquid:num:2307376.22 +date::2023-10-08,liquid:num:2266767.69 +date::2023-10-15,liquid:num:2263298.54 +date::2023-10-22,liquid:num:2295303.70 +date::2023-10-29,liquid:num:2305796.28 +date::2023-11-05,liquid:num:2287668.64 +date::2023-11-12,liquid:num:2323422.44 +date::2023-11-19,liquid:num:2321199.08 +date::2023-11-26,liquid:num:2318203.53 +date::2023-12-03,liquid:num:2289586.07 +date::2023-12-10,liquid:num:2290209.09 +date::2023-12-17,liquid:num:2280476.20 +date::2023-12-24,liquid:num:2298172.34 +date::2023-12-31,liquid:num:2316589.88 +date::2024-01-07,liquid:num:2345090.41 +date::2024-01-14,liquid:num:2293393.46 +date::2024-01-21,liquid:num:2319622.73 +date::2024-01-28,liquid:num:2337084.24 +date::2024-02-04,liquid:num:2309090.09 +date::2024-02-11,liquid:num:2346629.82 +date::2024-02-18,liquid:num:2334930.69 +date::2024-02-25,liquid:num:2319809.02 +date::2024-03-03,liquid:num:2351162.44 +date::2024-03-10,liquid:num:2307900.75 +date::2024-03-17,liquid:num:2362754.08 +date::2024-03-24,liquid:num:2366566.10 +date::2024-03-31,liquid:num:2322264.40 diff --git a/examples/post-retirement/portfolio.srf b/examples/post-retirement/portfolio.srf new file mode 100644 index 0000000..b7baabd --- /dev/null +++ b/examples/post-retirement/portfolio.srf @@ -0,0 +1,35 @@ +#!srfv1 +# Example portfolio: post-retirement household, ~age 68, ~$2.5M total. +# All names, share counts, and prices are fictional. The household is +# already retired and drawing down — see projections.srf for the +# distribution-only configuration (no accumulation). + +# Robin's Traditional IRA — primary drawdown source +symbol::VTI,shares:num:1800,open_date::2010-08-15,open_price:num:60.20,account::Robin Trad IRA +symbol::AGG,shares:num:1400,open_date::2015-03-22,open_price:num:107.40,account::Robin Trad IRA +symbol::SCHD,shares:num:600,open_date::2018-04-30,open_price:num:53.10,account::Robin Trad IRA +security_type::cash,shares:num:18500.00,open_date::2026-04-30,open_price:num:1.00,account::Robin Trad IRA + +# Robin's Roth IRA — preserved for late-life / heirs +symbol::VTI,shares:num:380,open_date::2012-11-08,open_price:num:71.50,account::Robin Roth +symbol::QQQ,shares:num:140,open_date::2014-06-12,open_price:num:97.30,account::Robin Roth +security_type::cash,shares:num:1240.00,open_date::2026-04-30,open_price:num:1.00,account::Robin Roth + +# Jamie's Traditional IRA +symbol::VTI,shares:num:920,open_date::2011-05-18,open_price:num:64.80,account::Jamie Trad IRA +symbol::AGG,shares:num:850,open_date::2016-09-04,open_price:num:108.10,account::Jamie Trad IRA +security_type::cash,shares:num:9800.00,open_date::2026-04-30,open_price:num:1.00,account::Jamie Trad IRA + +# Jamie's Roth IRA +symbol::SPY,shares:num:200,open_date::2013-02-14,open_price:num:152.20,account::Jamie Roth +symbol::SCHD,shares:num:280,open_date::2020-08-25,open_price:num:55.40,account::Jamie Roth +security_type::cash,shares:num:715.00,open_date::2026-04-30,open_price:num:1.00,account::Jamie Roth + +# Joint taxable — bridge income, RMD overflow +symbol::SPY,shares:num:240,open_date::2014-09-30,open_price:num:198.40,account::Joint taxable +symbol::AGG,shares:num:600,open_date::2017-11-15,open_price:num:106.90,account::Joint taxable +security_type::cash,shares:num:62000.00,open_date::2026-04-30,open_price:num:1.00,account::Joint taxable + +# Family HSA — still tax-advantaged, used for late-life medical +symbol::VTI,shares:num:140,open_date::2016-06-22,open_price:num:108.30,account::Family HSA +security_type::cash,shares:num:4200.00,open_date::2026-04-30,open_price:num:1.00,account::Family HSA diff --git a/examples/post-retirement/projections.srf b/examples/post-retirement/projections.srf new file mode 100644 index 0000000..a63ebc2 --- /dev/null +++ b/examples/post-retirement/projections.srf @@ -0,0 +1,32 @@ +#!srfv1 +# Post-retirement projection configuration. +# +# Robin (born 1958) and Jamie (born 1961) are already retired. They +# draw down ~$120k/yr in spending, supplemented by Social Security +# already in pay status. +# +# This file demonstrates the distribution-only mode — no accumulation +# fields are set, no target_spending is set. The "Years until possible +# retirement: none" line will appear in the accumulation block to +# confirm the model isn't projecting any pre-retirement growth. + +# Allocation target shifts more conservative in retirement +type::config,target_stock_pct:num:60 + +# Distribution horizons — through age 90 (older partner first) +type::config,horizon:num:20 +type::config,horizon:num:30 +type::config,horizon_age:num:95 + +# Birthdates +type::birthdate,date::1958-02-19 +type::birthdate,date::1961-07-04,person:num:2 + +# Social Security — both already collecting +type::event,name::Social Security (Robin),start_age:num:67,person:num:1,amount:num:34800 +type::event,name::Social Security (Jamie),start_age:num:65,person:num:2,amount:num:28200 + +# Late-life healthcare bump — modeled as a recurring expense starting +# at age 80 for the older partner. Real-world planning would also +# include LTC insurance / Medicaid considerations. +type::event,name::Healthcare (late-life),start_age:num:80,person:num:1,amount:num:-25000 diff --git a/examples/pre-retirement-age/accounts.srf b/examples/pre-retirement-age/accounts.srf new file mode 100644 index 0000000..65ac972 --- /dev/null +++ b/examples/pre-retirement-age/accounts.srf @@ -0,0 +1,11 @@ +#!srfv1 +# Account tax type classification for the pre-retirement example. +# tax_type values: taxable, roth, traditional, hsa + +account::Pat 401k,tax_type::traditional,institution::fidelity,account_number::P401 +account::Pat Roth,tax_type::roth,institution::fidelity,account_number::PROTH +account::Sam 401k,tax_type::traditional,institution::vanguard,account_number::S401 +account::Sam Roth,tax_type::roth,institution::vanguard,account_number::SROTH +account::Joint taxable,tax_type::taxable,institution::schwab,account_number::JT01 +account::Family HSA,tax_type::hsa,institution::fidelity,account_number::HSA01 +account::Kids 529,tax_type::taxable,institution::vanguard,account_number::C529 diff --git a/examples/pre-retirement-age/portfolio.srf b/examples/pre-retirement-age/portfolio.srf new file mode 100644 index 0000000..4045d3a --- /dev/null +++ b/examples/pre-retirement-age/portfolio.srf @@ -0,0 +1,39 @@ +#!srfv1 +# Example portfolio: pre-retirement household, ~age 45, ~$1.3M total. +# All names, share counts, and prices are fictional. The household is +# still actively contributing to retirement accounts and plans to +# retire around age 65 — see projections.srf for the configuration. + +# Pat's 401(k) — traditional (pre-tax) +symbol::VTI,shares:num:1100,open_date::2018-06-15,open_price:num:140.00,account::Pat 401k +symbol::AGG,shares:num:600,open_date::2020-01-10,open_price:num:115.50,account::Pat 401k +symbol::SCHD,shares:num:450,open_date::2022-03-18,open_price:num:74.20,account::Pat 401k +security_type::cash,shares:num:1234.56,open_date::2026-04-30,open_price:num:1.00,account::Pat 401k + +# Pat's Roth IRA +symbol::VTI,shares:num:240,open_date::2015-01-08,open_price:num:103.40,account::Pat Roth +symbol::QQQ,shares:num:65,open_date::2019-11-22,open_price:num:200.10,account::Pat Roth +security_type::cash,shares:num:412.85,open_date::2026-04-30,open_price:num:1.00,account::Pat Roth + +# Sam's 401(k) — traditional +symbol::VTI,shares:num:780,open_date::2017-08-20,open_price:num:130.20,account::Sam 401k +symbol::AGG,shares:num:380,open_date::2021-02-15,open_price:num:114.80,account::Sam 401k +security_type::cash,shares:num:842.10,open_date::2026-04-30,open_price:num:1.00,account::Sam 401k + +# Sam's Roth IRA +symbol::SPY,shares:num:120,open_date::2016-04-12,open_price:num:200.50,account::Sam Roth +symbol::SCHD,shares:num:180,open_date::2023-05-10,open_price:num:73.80,account::Sam Roth +security_type::cash,shares:num:225.00,open_date::2026-04-30,open_price:num:1.00,account::Sam Roth + +# Joint taxable brokerage — emergency fund + bridge savings +symbol::SPY,shares:num:200,open_date::2020-09-01,open_price:num:330.00,account::Joint taxable +symbol::VTI,shares:num:150,open_date::2022-10-04,open_price:num:188.00,account::Joint taxable +security_type::cash,shares:num:48000.00,open_date::2026-04-30,open_price:num:1.00,account::Joint taxable + +# Family HSA — used as a stealth retirement account +symbol::VTI,shares:num:90,open_date::2021-07-19,open_price:num:212.40,account::Family HSA +security_type::cash,shares:num:1500.00,open_date::2026-04-30,open_price:num:1.00,account::Family HSA + +# 529 for the kids — earmarked, but counted in the household balance sheet +symbol::VTI,shares:num:120,open_date::2017-09-05,open_price:num:128.50,account::Kids 529 +security_type::cash,shares:num:850.00,open_date::2026-04-30,open_price:num:1.00,account::Kids 529 diff --git a/examples/pre-retirement-age/projections.srf b/examples/pre-retirement-age/projections.srf new file mode 100644 index 0000000..b951af5 --- /dev/null +++ b/examples/pre-retirement-age/projections.srf @@ -0,0 +1,38 @@ +#!srfv1 +# Pre-retirement projection: target retirement date only. +# +# Pat (born 1981) and Sam (born 1983) plan to retire at age 65. +# Combined annual contribution: $80k/yr (CPI-adjusted). +# +# This file exercises the target-retirement-date input — the user +# has anchored a date (`retirement_age:num:65`) but no target +# spending. The projections command renders the Accumulation phase +# block (median portfolio at retirement, p10-p90 range) and the +# standard Safe Withdrawal table, but no Earliest retirement grid. + +# Asset allocation target (80% stocks / 20% bonds — typical pre-retirement) +type::config,target_stock_pct:num:80 + +# Distribution-phase horizons to simulate +type::config,horizon:num:25 +type::config,horizon:num:35 +# Plan through age 95 — the older partner's first-to-hit-95 sets the floor +type::config,horizon_age:num:95 + +# Target retirement date: oldest partner (Pat) reaches 65 in 2046 +type::config,retirement_age:num:65 + +# Annual household contribution to retirement accounts +type::config,annual_contribution:num:80000 +type::config,contribution_inflation_adjusted:bool:true + +# Birthdates (drives both retirement_age resolution and life-event ages) +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 diff --git a/examples/pre-retirement-both/accounts.srf b/examples/pre-retirement-both/accounts.srf new file mode 100644 index 0000000..65ac972 --- /dev/null +++ b/examples/pre-retirement-both/accounts.srf @@ -0,0 +1,11 @@ +#!srfv1 +# Account tax type classification for the pre-retirement example. +# tax_type values: taxable, roth, traditional, hsa + +account::Pat 401k,tax_type::traditional,institution::fidelity,account_number::P401 +account::Pat Roth,tax_type::roth,institution::fidelity,account_number::PROTH +account::Sam 401k,tax_type::traditional,institution::vanguard,account_number::S401 +account::Sam Roth,tax_type::roth,institution::vanguard,account_number::SROTH +account::Joint taxable,tax_type::taxable,institution::schwab,account_number::JT01 +account::Family HSA,tax_type::hsa,institution::fidelity,account_number::HSA01 +account::Kids 529,tax_type::taxable,institution::vanguard,account_number::C529 diff --git a/examples/pre-retirement-both/portfolio.srf b/examples/pre-retirement-both/portfolio.srf new file mode 100644 index 0000000..4045d3a --- /dev/null +++ b/examples/pre-retirement-both/portfolio.srf @@ -0,0 +1,39 @@ +#!srfv1 +# Example portfolio: pre-retirement household, ~age 45, ~$1.3M total. +# All names, share counts, and prices are fictional. The household is +# still actively contributing to retirement accounts and plans to +# retire around age 65 — see projections.srf for the configuration. + +# Pat's 401(k) — traditional (pre-tax) +symbol::VTI,shares:num:1100,open_date::2018-06-15,open_price:num:140.00,account::Pat 401k +symbol::AGG,shares:num:600,open_date::2020-01-10,open_price:num:115.50,account::Pat 401k +symbol::SCHD,shares:num:450,open_date::2022-03-18,open_price:num:74.20,account::Pat 401k +security_type::cash,shares:num:1234.56,open_date::2026-04-30,open_price:num:1.00,account::Pat 401k + +# Pat's Roth IRA +symbol::VTI,shares:num:240,open_date::2015-01-08,open_price:num:103.40,account::Pat Roth +symbol::QQQ,shares:num:65,open_date::2019-11-22,open_price:num:200.10,account::Pat Roth +security_type::cash,shares:num:412.85,open_date::2026-04-30,open_price:num:1.00,account::Pat Roth + +# Sam's 401(k) — traditional +symbol::VTI,shares:num:780,open_date::2017-08-20,open_price:num:130.20,account::Sam 401k +symbol::AGG,shares:num:380,open_date::2021-02-15,open_price:num:114.80,account::Sam 401k +security_type::cash,shares:num:842.10,open_date::2026-04-30,open_price:num:1.00,account::Sam 401k + +# Sam's Roth IRA +symbol::SPY,shares:num:120,open_date::2016-04-12,open_price:num:200.50,account::Sam Roth +symbol::SCHD,shares:num:180,open_date::2023-05-10,open_price:num:73.80,account::Sam Roth +security_type::cash,shares:num:225.00,open_date::2026-04-30,open_price:num:1.00,account::Sam Roth + +# Joint taxable brokerage — emergency fund + bridge savings +symbol::SPY,shares:num:200,open_date::2020-09-01,open_price:num:330.00,account::Joint taxable +symbol::VTI,shares:num:150,open_date::2022-10-04,open_price:num:188.00,account::Joint taxable +security_type::cash,shares:num:48000.00,open_date::2026-04-30,open_price:num:1.00,account::Joint taxable + +# Family HSA — used as a stealth retirement account +symbol::VTI,shares:num:90,open_date::2021-07-19,open_price:num:212.40,account::Family HSA +security_type::cash,shares:num:1500.00,open_date::2026-04-30,open_price:num:1.00,account::Family HSA + +# 529 for the kids — earmarked, but counted in the household balance sheet +symbol::VTI,shares:num:120,open_date::2017-09-05,open_price:num:128.50,account::Kids 529 +security_type::cash,shares:num:850.00,open_date::2026-04-30,open_price:num:1.00,account::Kids 529 diff --git a/examples/pre-retirement-both/projections.srf b/examples/pre-retirement-both/projections.srf new file mode 100644 index 0000000..2ca56be --- /dev/null +++ b/examples/pre-retirement-both/projections.srf @@ -0,0 +1,50 @@ +#!srfv1 +# Pre-retirement projection: both targets configured. +# +# Pat (born 1981) and Sam (born 1983) plan to retire at age 65 AND +# want to spend $80k/yr in retirement. Combined annual contribution: +# $80k/yr (CPI-adjusted). +# +# This file exercises BOTH retirement-planning inputs simultaneously: +# - Target retirement date (`retirement_age:num:65`) drives the +# Accumulation phase block — median portfolio at retirement, +# p10-p90 range. The headline retirement line uses this +# configured date. +# - Target spending (`target_spending:num:80000`) drives the +# Earliest retirement grid — when each (horizon, confidence) +# pair becomes feasible. +# +# Both blocks render back-to-back; the comparison is the value-add +# (e.g. "you set a target retirement of 2046; at 95% confidence over +# 30 years you could retire as early as YYYY"). + +# Asset allocation target (80% stocks / 20% bonds — typical pre-retirement) +type::config,target_stock_pct:num:80 + +# Distribution-phase horizons to simulate +type::config,horizon:num:25 +type::config,horizon:num:35 +# Plan through age 95 — the older partner's first-to-hit-95 sets the floor +type::config,horizon_age:num:95 + +# Target retirement date: oldest partner (Pat) reaches 65 in 2046 +type::config,retirement_age:num:65 + +# Annual household contribution to retirement accounts +type::config,annual_contribution:num:80000 +type::config,contribution_inflation_adjusted:bool:true + +# Target retirement spending +type::config,target_spending:num:80000 +type::config,target_spending_inflation_adjusted:bool:true + +# Birthdates (drives both retirement_age resolution and life-event ages) +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 diff --git a/examples/pre-retirement-spending-target/accounts.srf b/examples/pre-retirement-spending-target/accounts.srf new file mode 100644 index 0000000..65ac972 --- /dev/null +++ b/examples/pre-retirement-spending-target/accounts.srf @@ -0,0 +1,11 @@ +#!srfv1 +# Account tax type classification for the pre-retirement example. +# tax_type values: taxable, roth, traditional, hsa + +account::Pat 401k,tax_type::traditional,institution::fidelity,account_number::P401 +account::Pat Roth,tax_type::roth,institution::fidelity,account_number::PROTH +account::Sam 401k,tax_type::traditional,institution::vanguard,account_number::S401 +account::Sam Roth,tax_type::roth,institution::vanguard,account_number::SROTH +account::Joint taxable,tax_type::taxable,institution::schwab,account_number::JT01 +account::Family HSA,tax_type::hsa,institution::fidelity,account_number::HSA01 +account::Kids 529,tax_type::taxable,institution::vanguard,account_number::C529 diff --git a/examples/pre-retirement-spending-target/portfolio.srf b/examples/pre-retirement-spending-target/portfolio.srf new file mode 100644 index 0000000..4045d3a --- /dev/null +++ b/examples/pre-retirement-spending-target/portfolio.srf @@ -0,0 +1,39 @@ +#!srfv1 +# Example portfolio: pre-retirement household, ~age 45, ~$1.3M total. +# All names, share counts, and prices are fictional. The household is +# still actively contributing to retirement accounts and plans to +# retire around age 65 — see projections.srf for the configuration. + +# Pat's 401(k) — traditional (pre-tax) +symbol::VTI,shares:num:1100,open_date::2018-06-15,open_price:num:140.00,account::Pat 401k +symbol::AGG,shares:num:600,open_date::2020-01-10,open_price:num:115.50,account::Pat 401k +symbol::SCHD,shares:num:450,open_date::2022-03-18,open_price:num:74.20,account::Pat 401k +security_type::cash,shares:num:1234.56,open_date::2026-04-30,open_price:num:1.00,account::Pat 401k + +# Pat's Roth IRA +symbol::VTI,shares:num:240,open_date::2015-01-08,open_price:num:103.40,account::Pat Roth +symbol::QQQ,shares:num:65,open_date::2019-11-22,open_price:num:200.10,account::Pat Roth +security_type::cash,shares:num:412.85,open_date::2026-04-30,open_price:num:1.00,account::Pat Roth + +# Sam's 401(k) — traditional +symbol::VTI,shares:num:780,open_date::2017-08-20,open_price:num:130.20,account::Sam 401k +symbol::AGG,shares:num:380,open_date::2021-02-15,open_price:num:114.80,account::Sam 401k +security_type::cash,shares:num:842.10,open_date::2026-04-30,open_price:num:1.00,account::Sam 401k + +# Sam's Roth IRA +symbol::SPY,shares:num:120,open_date::2016-04-12,open_price:num:200.50,account::Sam Roth +symbol::SCHD,shares:num:180,open_date::2023-05-10,open_price:num:73.80,account::Sam Roth +security_type::cash,shares:num:225.00,open_date::2026-04-30,open_price:num:1.00,account::Sam Roth + +# Joint taxable brokerage — emergency fund + bridge savings +symbol::SPY,shares:num:200,open_date::2020-09-01,open_price:num:330.00,account::Joint taxable +symbol::VTI,shares:num:150,open_date::2022-10-04,open_price:num:188.00,account::Joint taxable +security_type::cash,shares:num:48000.00,open_date::2026-04-30,open_price:num:1.00,account::Joint taxable + +# Family HSA — used as a stealth retirement account +symbol::VTI,shares:num:90,open_date::2021-07-19,open_price:num:212.40,account::Family HSA +security_type::cash,shares:num:1500.00,open_date::2026-04-30,open_price:num:1.00,account::Family HSA + +# 529 for the kids — earmarked, but counted in the household balance sheet +symbol::VTI,shares:num:120,open_date::2017-09-05,open_price:num:128.50,account::Kids 529 +security_type::cash,shares:num:850.00,open_date::2026-04-30,open_price:num:1.00,account::Kids 529 diff --git a/examples/pre-retirement-spending-target/projections.srf b/examples/pre-retirement-spending-target/projections.srf new file mode 100644 index 0000000..3149c7a --- /dev/null +++ b/examples/pre-retirement-spending-target/projections.srf @@ -0,0 +1,73 @@ +#!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 diff --git a/examples/pre-retirement-spending/accounts.srf b/examples/pre-retirement-spending/accounts.srf new file mode 100644 index 0000000..65ac972 --- /dev/null +++ b/examples/pre-retirement-spending/accounts.srf @@ -0,0 +1,11 @@ +#!srfv1 +# Account tax type classification for the pre-retirement example. +# tax_type values: taxable, roth, traditional, hsa + +account::Pat 401k,tax_type::traditional,institution::fidelity,account_number::P401 +account::Pat Roth,tax_type::roth,institution::fidelity,account_number::PROTH +account::Sam 401k,tax_type::traditional,institution::vanguard,account_number::S401 +account::Sam Roth,tax_type::roth,institution::vanguard,account_number::SROTH +account::Joint taxable,tax_type::taxable,institution::schwab,account_number::JT01 +account::Family HSA,tax_type::hsa,institution::fidelity,account_number::HSA01 +account::Kids 529,tax_type::taxable,institution::vanguard,account_number::C529 diff --git a/examples/pre-retirement-spending/portfolio.srf b/examples/pre-retirement-spending/portfolio.srf new file mode 100644 index 0000000..4045d3a --- /dev/null +++ b/examples/pre-retirement-spending/portfolio.srf @@ -0,0 +1,39 @@ +#!srfv1 +# Example portfolio: pre-retirement household, ~age 45, ~$1.3M total. +# All names, share counts, and prices are fictional. The household is +# still actively contributing to retirement accounts and plans to +# retire around age 65 — see projections.srf for the configuration. + +# Pat's 401(k) — traditional (pre-tax) +symbol::VTI,shares:num:1100,open_date::2018-06-15,open_price:num:140.00,account::Pat 401k +symbol::AGG,shares:num:600,open_date::2020-01-10,open_price:num:115.50,account::Pat 401k +symbol::SCHD,shares:num:450,open_date::2022-03-18,open_price:num:74.20,account::Pat 401k +security_type::cash,shares:num:1234.56,open_date::2026-04-30,open_price:num:1.00,account::Pat 401k + +# Pat's Roth IRA +symbol::VTI,shares:num:240,open_date::2015-01-08,open_price:num:103.40,account::Pat Roth +symbol::QQQ,shares:num:65,open_date::2019-11-22,open_price:num:200.10,account::Pat Roth +security_type::cash,shares:num:412.85,open_date::2026-04-30,open_price:num:1.00,account::Pat Roth + +# Sam's 401(k) — traditional +symbol::VTI,shares:num:780,open_date::2017-08-20,open_price:num:130.20,account::Sam 401k +symbol::AGG,shares:num:380,open_date::2021-02-15,open_price:num:114.80,account::Sam 401k +security_type::cash,shares:num:842.10,open_date::2026-04-30,open_price:num:1.00,account::Sam 401k + +# Sam's Roth IRA +symbol::SPY,shares:num:120,open_date::2016-04-12,open_price:num:200.50,account::Sam Roth +symbol::SCHD,shares:num:180,open_date::2023-05-10,open_price:num:73.80,account::Sam Roth +security_type::cash,shares:num:225.00,open_date::2026-04-30,open_price:num:1.00,account::Sam Roth + +# Joint taxable brokerage — emergency fund + bridge savings +symbol::SPY,shares:num:200,open_date::2020-09-01,open_price:num:330.00,account::Joint taxable +symbol::VTI,shares:num:150,open_date::2022-10-04,open_price:num:188.00,account::Joint taxable +security_type::cash,shares:num:48000.00,open_date::2026-04-30,open_price:num:1.00,account::Joint taxable + +# Family HSA — used as a stealth retirement account +symbol::VTI,shares:num:90,open_date::2021-07-19,open_price:num:212.40,account::Family HSA +security_type::cash,shares:num:1500.00,open_date::2026-04-30,open_price:num:1.00,account::Family HSA + +# 529 for the kids — earmarked, but counted in the household balance sheet +symbol::VTI,shares:num:120,open_date::2017-09-05,open_price:num:128.50,account::Kids 529 +security_type::cash,shares:num:850.00,open_date::2026-04-30,open_price:num:1.00,account::Kids 529 diff --git a/examples/pre-retirement-spending/projections.srf b/examples/pre-retirement-spending/projections.srf new file mode 100644 index 0000000..e79ff6e --- /dev/null +++ b/examples/pre-retirement-spending/projections.srf @@ -0,0 +1,47 @@ +#!srfv1 +# Pre-retirement projection: target spending only. +# +# Pat (born 1981) and Sam (born 1983) want to spend $80k/yr in +# retirement (today's dollars, CPI-adjusted). Combined annual +# contribution while working: $80k/yr. +# +# This file exercises the target-spending input — the user has +# anchored a spending number (`target_spending:num:80000`) but no +# retirement date. The projections command searches for the +# earliest accumulation length that sustains that spending at each +# configured (horizon × confidence) pair, renders the resulting +# grid, and promotes one cell into the Accumulation phase block as +# the headline. The default promotion rule is "longest configured +# horizon at 99% confidence, where the oldest person stays under +# age 100." See `pre-retirement-spending-target/` for the explicit- +# override variant. + +# Asset allocation target (80% stocks / 20% bonds — typical pre-retirement) +type::config,target_stock_pct:num:80 + +# Distribution-phase horizons to simulate +type::config,horizon:num:25 +type::config,horizon:num:35 +# Plan through age 95 — the older partner's first-to-hit-95 sets the floor +type::config,horizon_age:num:95 + +# Annual household contribution to retirement accounts +type::config,annual_contribution:num:80000 +type::config,contribution_inflation_adjusted:bool:true + +# Target retirement spending — the projections command searches for +# the earliest accumulation year at which this spending level is +# sustainable across each configured (horizon × confidence) pair. +type::config,target_spending:num:80000 +type::config,target_spending_inflation_adjusted:bool:true + +# Birthdates (drives life-event ages even without a configured retirement date) +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