Side Project · Personal Finance · Python
Personal Budget Optimizer
Motivation
Halfway through junior year, I realized I had genuinely no idea where my money was going. I had a part-time campus job, some freelance tutoring income, and a vague sense that I was “doing fine” financially. Then my checking account hit $47 two days before rent was due.
I tried Mint and YNAB but they felt overengineered for my situation. I wanted something dead simple: import my bank CSV, categorize spending, and tell me where I’m bleeding money. So I built it myself over a weekend with Streamlit.
The core idea is the 50/30/20 rule— 50% of after-tax income to needs, 30% to wants, 20% to savings. Not revolutionary, but actually seeing your numbers mapped against that target is surprisingly motivating.
Approach
The app is intentionally minimal. You upload a CSV bank statement (Chase, BofA, and Discover formats supported), and it auto-categorizes transactions using keyword matching on merchant names. Not fancy ML — just a dictionary of patterns like “DOORDASH” → Food Delivery, “SPOTIFY” → Subscription.
From there it calculates your actual 50/30/20 split, flags the biggest deltas between target and actual, and shows month-over-month trends. The whole thing is about 400 lines of Python.
Key features:
- Auto-categorization with manual override for misclassified transactions
- Monthly spending breakdown with Plotly sunburst and bar charts
- Savings rate tracker with goal-setting (I set mine to 20%)
- Subscription detector that flags recurring charges you might have forgotten about
Key Findings
After three months of tracking, the numbers told a pretty clear story.
| Category | Before | After | Change | Note |
|---|---|---|---|---|
| Rent & Utilities | $1,080 | $1,080 | -- | Fixed cost |
| Food Delivery | $420 | $140 | -67% | Switched to meal prep |
| Subscriptions | $185 | $45 | -76% | Cancelled 9 unused services |
| Groceries | $220 | $310 | +41% | Cooking more at home |
| Transportation | $95 | $85 | -11% | More walking/biking |
| Shopping | $280 | $150 | -46% | 30-day rule for non-essentials |
| Savings | $190 | $520 | +174% | Automated transfers |
The biggest surprise was food delivery. I knew I was ordering a lot, but $420/month was genuinely shocking. That’s more than I was spending on groceries. I also found 9 subscriptions I’d completely forgotten about — including a language learning app I signed up for in freshman year and never opened again.
50/30/20 Allocation (After Optimization, $2,380/mo Income)
Limitations
Let me be upfront about what’s hacky here.
- Categorization is keyword-based, not ML. It works for chains (Uber Eats, Target) but struggles with small local businesses or vague merchant names like “SQ *JOHN’S”. About 15% of transactions need manual reclassification.
- No bank API integration. You have to manually download and upload CSV statements each month. I looked into Plaid but the cost didn’t make sense for a personal tool.
- The 50/30/20 rule is a rough heuristic. It doesn’t account for student loan payments, irregular income, or living in a high-cost area. For a student in the Bay Area, 50% on “needs” is pretty tight.
- Single-user, local only. No authentication, no cloud storage. Your data stays in a local SQLite file, which is a privacy feature but also means no access from your phone.
What I Learned
This was my first time building something purely for myself, and it taught me that the best data projects start with a real problem you actually have. I didn’t need a sophisticated model — I needed visibility.
On the technical side, Streamlit is incredible for prototyping. I went from zero to a working dashboard in about 6 hours. The tradeoff is that it’s hard to make it look polished — it always looks like a Streamlit app. But for a personal tool, that’s totally fine.
The biggest personal takeaway: tracking changes behavior. Just the act of seeing my food delivery spending in a bar chart next to my savings was enough to shift my habits. I didn’t need an algorithm to tell me to stop ordering DoorDash three times a week — I just needed to see the number.