Create a command-line financial calculator tool that computes common loan and interest calculations. Supports simple interest, mortgage payments, personal loans, car loans, and balloon payment loans. Designed as a clean, professional portfolio piece demonstrating financial domain knowledge and CLI design patterns.
- Provide 5 distinct financial calculators via command-line interface
- Accept inputs via command-line arguments (no interactive prompts)
- Return concise, accurate calculations
- Follow functional programming principles (pure calculation functions)
- Demonstrate professional code structure suitable for portfolio
Description: As a developer, I want a clean CLI foundation so I can add calculators incrementally.
Acceptance Criteria:
- Script named
finance_calc.pyin root directory - Uses argparse with subcommands for each calculator type
- Subcommands:
simple-interest,mortgage,personal-loan,car-loan,balloon - Help text shows usage for each calculator
- Running without args shows available calculators
- Typecheck passes
- Script runs:
python finance_calc.py --help
Description: Review foundation before building calculators.
Acceptance Criteria:
- CLI structure runs without errors:
python finance_calc.py --help - All 5 subcommands listed in help output
- Typecheck passes:
mypy finance_calc.py - Apply Linus criteria: Is this the simplest CLI structure possible?
- No over-engineering (no unnecessary abstractions)
Description: As a user, I want to calculate simple interest so I can evaluate non-compounding interest scenarios.
Acceptance Criteria:
- Pure function:
calculate_simple_interest(principal, rate, time) -> float - Formula: I = P × r × t
- CLI:
python finance_calc.py simple-interest --principal 1000 --rate 5 --years 3 - Output format: "Simple Interest: $150.00"
- Rate input as percentage (5 = 5%, not 0.05)
- Tests cover: basic calculation, zero values, edge cases
- Typecheck passes
Description: As a user, I want to calculate monthly mortgage payments so I can evaluate home loan affordability.
Acceptance Criteria:
- Pure function:
calculate_mortgage_payment(principal, annual_rate, years) -> float - Formula: M = P × [r(1+r)^n] / [(1+r)^n - 1] where r = monthly rate
- CLI:
python finance_calc.py mortgage --principal 200000 --rate 4.5 --years 30 - Output format: "Monthly Payment: $1,013.37"
- Tests cover: standard 30-year, 15-year, different rates
- Typecheck passes
Description: As a user, I want to calculate personal loan payments so I can evaluate unsecured loan costs.
Acceptance Criteria:
- Pure function:
calculate_personal_loan(principal, annual_rate, months) -> float - Formula: Same as mortgage but term in months (more common for personal loans)
- CLI:
python finance_calc.py personal-loan --principal 5000 --rate 12 --months 24 - Output format: "Monthly Payment: $235.37"
- Tests cover: short-term (12mo), long-term (60mo), high rates
- Typecheck passes
Description: As a user, I want to calculate car loan payments so I can evaluate auto financing options.
Acceptance Criteria:
- Pure function:
calculate_car_loan(principal, annual_rate, years, down_payment) -> dict - Returns: monthly payment and total financed amount
- CLI:
python finance_calc.py car-loan --price 25000 --down 5000 --rate 6 --years 5 - Output format: "Financed: $20,000.00\nMonthly Payment: $386.66"
- Down payment defaults to 0 if not provided
- Tests cover: with/without down payment, various terms
- Typecheck passes
Description: As a user, I want to calculate balloon payment loan costs so I can evaluate loans with large final payments.
Acceptance Criteria:
- Pure function:
calculate_balloon_payment(principal, annual_rate, years, balloon_percent) -> dict - Returns: monthly payment and final balloon amount
- Formula: Amortize partial amount, balloon pays remaining principal
- CLI:
python finance_calc.py balloon --principal 50000 --rate 7 --years 5 --balloon 30 - Output format: "Monthly Payment: $693.04\nBalloon Payment: $15,000.00"
- Balloon percent is percentage of original principal (30 = 30%)
- Tests cover: 20%, 30%, 50% balloon scenarios
- Typecheck passes
Description: Simple interest output uses :.2f while all other calculators use :,.2f (with thousands separator).
Acceptance Criteria:
- Change line 270 from
${interest:.2f}to${interest:,.2f} - Verify:
python finance_calc.py simple-interest --principal 10000 --rate 5 --years 3outputs "$1,500.00" (with comma) - All outputs consistently use
:,.2fformat
Description: The loan payment formula is duplicated 4 times (mortgage, personal-loan, car-loan, balloon). Extract to a shared helper function.
Acceptance Criteria:
- Create pure helper:
_calculate_monthly_payment(principal: float, monthly_rate: float, num_payments: int) -> float - Helper handles zero rate case (returns principal / num_payments)
- Refactor all 4 calculator functions to use the helper
- All existing tests still pass
- All CLI outputs unchanged (verify with sample inputs)
Description: Review all calculator functions before adding tests and validation.
Acceptance Criteria:
- All 5 calculators work with sample inputs from acceptance criteria
- Pure functions only (no side effects, no global state)
- Formulas match reference section exactly
- Output formatting consistent (currency with 2 decimals)
- Apply Linus criteria: Any simpler approach possible?
- No code duplication between calculators (extract shared logic)
Description: As a developer, I want automated tests for all calculators to ensure accuracy and prevent regressions.
Acceptance Criteria:
- Test file:
test/test_finance_calc.py - Tests for each calculator function (US-002 through US-006)
- Test edge cases: zero values, very large numbers, maximum terms
- Test CLI argument parsing and error handling
- Test output formatting (decimal places, currency symbols)
- All tests pass:
pytest test/test_finance_calc.py -v - Test coverage ≥ 90% for calculation functions
- Typecheck passes
Description: As a user, I want clear error messages for invalid inputs so I can correct my command quickly.
Acceptance Criteria:
- Validate: principal > 0, rate ≥ 0, term > 0
- Validate: down payment ≤ principal (car loans)
- Validate: balloon percent between 0-100 (balloon loans)
- Error messages are clear: "Error: Principal must be greater than 0"
- Exit with code 1 on validation failure
- Tests verify all validation rules
- Typecheck passes
Description: Comprehensive final review before marking project complete.
Acceptance Criteria:
- All tests pass:
pytest test/test_finance_calc.py -v - Typecheck clean:
mypy finance_calc.py - Manual test each calculator with sample inputs
- Code quality meets portfolio standards
- Apply Linus criteria to entire codebase
- No TODO comments or incomplete code
- README or docstrings explain usage
- No interactive prompts (all inputs via CLI args only)
- No GUI or web interface
- No amortization schedules (just final calculated amounts)
- No comparison mode (single calculation per run)
- No file I/O or saved scenarios
- No currency conversion or international formats
- No advanced features (extra payments, rate changes, PMI, taxes)
- No total interest calculations (just monthly payment amounts)
- Python 3.7+ (matches repo standards)
- Use argparse for CLI (stdlib, no dependencies)
- All calculation functions are pure (testable, no side effects)
- Use Decimal for currency calculations (avoid float rounding errors)
- Follow functional programming principles from CLAUDE.md
- Single responsibility: each function does one calculation
- Type hints on all functions
- Use dataclasses for complex return types if needed
Simple Interest:
I = P × r × t
where:
P = principal
r = annual rate (as decimal: 5% = 0.05)
t = time in years
Standard Loan Payment (Mortgage, Personal, Car):
M = P × [r(1+r)^n] / [(1+r)^n - 1]
where:
M = monthly payment
P = principal
r = monthly interest rate (annual_rate / 12)
n = number of payments (months)
Balloon Payment:
1. Calculate payment on reduced principal (P × (1 - balloon%))
2. Balloon amount = P × balloon%