Finance Forecast is a simple tool to read in a config file that outlines various financial events (i.e. anything related to income or spending, loans, etc) and associated dates and then run simulations on one or more scenarios to see how these turn out. The more specific the events are the more accurate the simulation should be. Output defaults to printing to the console in a pretty format, but CSV format for easy import to other software may also be specified.
The general goal is to help provide users with a reasonable best-guess guide for financial decisions. By expressing different choices in different scenarios and then running the simulation the user can see how things generally would out over the long-term.
finance-forecast --config=config.yaml.example --output-format=csv
Run the embedded web server to upload configurations through a browser:
finance-forecast --serve --addr :8080When running in server mode:
- Visit
http://localhost:8080(or your chosen address) to open the UI - Upload a YAML configuration to run the simulation
- Review the rendered results table and download the generated CSV without touching the CLI
- Find the build identifier in the footer of the Planning workspace for quick environment checks
- Provide
--configif you want to reuse logging settings from a file - Adjust runtime settings (address, upload limits, logging) using
server-config.yaml(copy fromserver-config.yaml.example). Upload limits accept human-friendly units like256K,10M, or1G. Configure structured logging withlogging.level,logging.format, andlogging.outputFile. CLI flags such as--addr,--max-upload, and--server-configoverride or choose the configuration file when needed, while--log-levelstill wins over file settings.
--config: Path to YAML config file (required for CLI; optional for server logging defaults)--output-format: Override output format:pretty(default) orcsv--log-level: Override logging level (takes precedence over config and server-config settings)--serve: Start the web UI server instead of running the CLI simulation--version: Print the build identifier (populated via-ldflags "-X main.version=<value>") and exit--addr: Bind address for the web UI server (overrides server config)--server-config: Path to the server configuration file (defaultserver-config.yaml)--max-upload: Maximum upload size in bytes for YAML configs (overrides server config)--emergency-months: Override the months of expenses used for emergency fund recommendations (set to0to disable)--optimize: Run the optimizer to adjust fields marked with anoptimizeblock before generating forecasts
- Processing starts from the configured
startDate(YYYY-MM format) or current month if not specified - Initial value should account for the month preceding the start date
- Compounded monthly
- Escrow handling:
- Refunded when loan is paid early (except December)
- Extrapolated to annual expense if asset not sold following maturity
- Configure
investmentswithincommonand/or each scenario to simulate long-term accounts alongside cash flow. - Each investment supports:
startingValue: balance at the beginning of the simulationannualReturnRate: expected average annual growth (percentage)taxRate: optional tax rate applied to positive monthly gainswithdrawalTaxRate: optional tax rate applied to the growth portion of withdrawalscontributionsFromCash: optional toggle (defaultfalse) that, when enabled, deducts contribution amounts from the simulated cash balance (useful for Roth IRA or brokerage contributions). Leave disabled for pre-tax payroll deductions such as traditional 401(k).contributions/withdrawals: arrays of event-style schedules (amount, frequency, start/end dates). Withdrawal events may specify a fixedamountor apercentageof the current balance; each investment must choose one style for all of its withdrawals.
- Investment balances compound monthly; contributions and withdrawals update the account before growth is calculated. Withdrawals automatically track how much came from principal versus growth and estimate taxes accordingly when
withdrawalTaxRateis set.
- Configure
recommendations.emergencyFundMonths(default6) to control the emergency fund target window. - The simulator estimates average monthly expenses across the run and highlights how many months of coverage your starting liquid balance provides.
- Set the value to
0via configuration or--emergency-months=0to disable the recommendation entirely.
Enable single-field optimization for specific events to find the smallest adjustment that keeps cash above the emergency-fund floor once it is reached. Mark events with an optimize block and run the CLI with --optimize to activate the solver.
Supported event fields:
amount: Provide numericmin/maxbounds (floating-point). Default tolerance is0.01.frequency: Provide integermin/maxbounds (in months). Bounds must be at least1. Default tolerance is1.startDate: ProvideminDate/maxDatebounds inYYYY-MM. Default tolerance is1month.endDate: ProvideminDate/maxDatebounds inYYYY-MM. Default tolerance is1month.
kind and target default to cash_floor and emergencyFund respectively and are currently the only supported values. tolerance and maxIterations are optional overrides for the solver (defaults: 0.01 for continuous fields, 1 month for discrete fields, and 50 iterations).
scenarios:
- name: Base Plan
active: true
events:
- name: Income
amount: 2000
startDate: 2025-01
endDate: 2025-12
frequency: 1
- name: New Job Amount
amount: 2000
startDate: 2026-01
frequency: 1
optimize:
field: amount
min: 0
max: 2500
tolerance: 0.5 # optional override, defaults to 0.01 for amount
- name: New Job Start Date
amount: 1800
startDate: 2026-04
frequency: 1
optimize:
field: startDate
minDate: 2025-10 # required when optimizing dates (inclusive)
maxDate: 2026-08 # required when optimizing dates (inclusive)
maxIterations: 60 # optional override, defaults to 50During optimization the emergency-fund target is snapshotted from the baseline configuration and treated as a fixed cash floor. If the cash balance starts below the floor, the constraint is enforced beginning with the first month that reaches the target. The optimizer walks toward the boundary that most reduces the adjustment while keeping the post-threshold cash balance at or above the stored floor: when only the lower bound is feasible it searches upward for the highest feasible value, and when only the upper bound is feasible it searches downward for the lowest feasible value. If neither bound produces a feasible projection, the run fails fast with a descriptive error so you can widen the search range.
Configure in YAML:
logging:
level: info # debug, info, warn, error
format: console # console or json
outputFile: path # optional log file
output:
format: pretty # pretty or csvRun with overrides:
./finance-forecast --log-level debug --output-format csv --config config.yaml