Skip to content

aaronamano/MoodBank

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

38 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

How to get started

git clone this app using git clone <REPO_URL>

Frontend

  1. cd frontend
  2. pnpm install
  3. pnpm run dev

Backend

  1. cd backend
  2. python3 -m venv venv
  3. source venv/bin/activate
  4. pip install requirements.txt
  5. python3 main.py

Adding Environment Variable

  1. create a .env file under /frontend/
  2. in your .env file add NEXT_PUBLIC_GEMINI_API_KEY=""

Inspiration

Have you ever wondered why many people face debt? Part of the problem starts with us.

About 50% of consumers worldwide report negative economic attitudes, a sign of poor financial behaviors or spending driven by economic anxiety. That is about 4 Billion people around the world! Overspending and bad budgeting remain key drivers of personal debt, which lead to worst case scenarios such as gambling and depression.

What it does

MoodBank has many features to ensure to spend in the most efficient way possible:

1. Transactions

You can input transactions where they enter a price, category, description, and a sentiment rating on a scale from 1 to 10 that determines how they feel about spending x for y dollars. 1 is being the worst and 10 is being the best.

2. Insights

Your transactions are tracked, and they monitor your total spending. Two notable visuals is a pie chart, which determines how much you spend on each category by percentage and a bar chart, which shows an average ROI you expressed for each category .

3. Planning

You can determine your debt risk by calculating it based on 3 parameters (monthly income, current balance, and monthly expenses). Also, there is also a calendar feature where you can add wishlist items to anticipate future transactions on a particular date. Additionally users have an AI Agent to interact with to guide users on what wishlist items are worth spending on.

MoodBank uses a smooth heuristic model (no machine learning) to score your debt risk on a 0–1 scale and assign a risk level:

🔵 Low 🟠 Medium 🔴 High

Calculations:

  1. Cashflow projection

projected_balance = curr_balance + (income - expected_expenses)

  1. Risk components
  • Overspending penalty — if expected_expenses > income
  • Negative balance penalty — if projected_balance < 0
  • Liquidity pressure — if you’re barely breaking even (thin buffer)
  1. Emotional ROI adjustment (eROI)

Because not all spending is bad.

  • Negative emotional ROI (regretful spending) → slightly increases risk
  • Positive ROI (worthwhile experiences) → slightly reduces risk

The effect is gentle and capped — your feelings matter, but math still wins.

Risk levels are mapped from the final score:

  • Low: score < 0.34
  • Medium: 0.34 ≤ score < 0.67
  • High: score ≥ 0.67

debt_risk.py

"""Debt Risk Prediction System

A small, object-oriented module offering:
- `User` with financial attributes
- Cashflow projection
- Heuristic (non-ML) debt risk scoring on a 0–1 scale
- Optional adjustment by emotional return on investment (eROI)

Design goals:
- Keep the heuristic smooth so small overspending does not max risk
- Penalize negative projected balance
- Clean, readable code with docstrings and type hints
"""
from __future__ import annotations

from dataclasses import dataclass
from typing import Optional, Literal


RiskLevel = Literal["Low", "Medium", "High"]


@dataclass
class DebtRiskResult:
    """Immutable container for a debt risk evaluation.

    Attributes:
        risk_score: Risk on a 0–1 scale (higher is riskier).
        risk_level: Human-friendly label derived from the score.
        projected_balance: Next-period projected balance.
        confidence: Optional heuristic confidence (0–1).
    """

    risk_score: float
    risk_level: RiskLevel
    projected_balance: float
    confidence: Optional[float] = None


@dataclass
class User:
    """Represents a user's basic financial profile.

    Attributes:
        income: Expected income for the next period.
        curr_balance: Current available balance.
        expected_expenses: Expected expenses for the next period.
    """

    income: float
    curr_balance: float
    expected_expenses: float

    # Private field storing the multiplicative risk adjustment from eROI.
    _eroi_adjustment_factor: float = 1.0

    # --------------------------- Public API ---------------------------------
    def basic_cashflow_projection(self) -> float:
        """Compute the next projected balance: `curr_balance + (income - expected_expenses)`.

        Returns:
            The projected balance for the next period.
        """
        net_change = self.income - self.expected_expenses
        return self.curr_balance + net_change

    def adjust_for_emotional_roi(self, avg_eroi: float) -> None:
        """Adjust internal risk via average emotional ROI on a [-2, +2] scale.

        Heuristic:
        - If `avg_eroi < 0`, increase risk slightly (factor > 1).
        - If `0 <= avg_eroi <= 1`, reduce risk slightly.
        - If `avg_eroi > 1`, reduce risk a bit more, still modestly (factor < 1).

        The adjustment is multiplicative and clipped to a gentle range to avoid
        dominating the base financial signal.

        Args:
            avg_eroi: Average emotional return on investment in [-2, +2].
        """
        # Clamp input to the design range to avoid extreme adjustments.
        e = _clamp(avg_eroi, -2.0, 2.0)

        if e < 0:
            # Up to +14% risk at e = -2 (linear scale).
            factor = 1.0 + min(0.14, abs(e) * 0.07)
        elif e <= 1:
            # Up to -4% risk at e = +1 (linear scale).
            factor = 1.0 - (e * 0.04)
        else:  # 1 < e <= 2
            # From -4% to -12% risk between e=1..2.
            factor = 1.0 - (0.04 + (e - 1.0) * 0.08)

        # Keep the factor in a sane band.
        self._eroi_adjustment_factor = _clamp(factor, 0.85, 1.2)

    def debt_risk_score(self, include_confidence: bool = False) -> DebtRiskResult:
        """Compute a heuristic, smooth debt risk score.

        Scoring outline (non-ML):
        - Higher when expected_expenses > income (overspending)
        - Additional penalty if the next projected balance would be negative
        - Smooth scaling so small overspending does not saturate risk
        - Optional multiplicative adjustment from `adjust_for_emotional_roi`

        Args:
            include_confidence: When True, populate `confidence` in the result.

        Returns:
            `DebtRiskResult` containing the score, level, projected balance, and
            optional confidence.
        """
        income = float(self.income)
        expenses = float(self.expected_expenses)
        current = float(self.curr_balance)

        projected_balance = self.basic_cashflow_projection()
        net_margin = income - expenses

        # 1) Overspending component: saturates smoothly with overspend ratio.
        overspend_amount = max(0.0, expenses - income)
        income_for_ratio = income if income > 0.0 else 1.0  # avoid divide-by-zero
        overspend_ratio = overspend_amount / income_for_ratio
        overspend_component = overspend_ratio / (1.0 + overspend_ratio)  # in [0,1)

        # 2) Negative balance penalty: grows as projected shortfall grows vs resources.
        shortfall = max(0.0, -projected_balance)
        resource_scale = max(1.0, abs(current) + income + expenses)
        negative_balance_penalty = shortfall / (shortfall + resource_scale)

        # 3) Liquidity pressure: if not overspending but balance is thin.
        liquidity_risk = 0.0
        if net_margin >= 0.0 and expenses > 0.0:
            buffer_months = current / expenses
            if buffer_months < 0.5:
                liquidity_risk = _clamp((0.5 - buffer_months) / 0.5, 0.0, 1.0) * 0.15

        # Blend components with weights chosen for interpretability and smoothness.
        raw_risk = (0.65 * overspend_component) + (0.35 * negative_balance_penalty) + liquidity_risk

        # Apply eROI adjustment multiplicatively, then clamp to [0,1].
        adjusted_risk = _clamp(raw_risk * self._eroi_adjustment_factor, 0.0, 1.0)

        risk_level: RiskLevel
        if adjusted_risk < 0.34:
            risk_level = "Low"
        elif adjusted_risk < 0.67:
            risk_level = "Medium"
        else:
            risk_level = "High"

        confidence: Optional[float] = None
        if include_confidence:
            # A simple heuristic confidence: penalize questionable inputs and
            # large adjustments; cap within [0.5, 0.95].
            confidence_base = 0.8
            if income <= 0.0:
                confidence_base -= 0.25
            if expenses < 0.0:
                confidence_base -= 0.15
            # Large multiplicative adjustments slightly reduce confidence.
            confidence_base -= abs(self._eroi_adjustment_factor - 1.0) * 0.1
            confidence = _clamp(confidence_base, 0.5, 0.95)

        return DebtRiskResult(
            risk_score=adjusted_risk,
            risk_level=risk_level,
            projected_balance=projected_balance,
            confidence=confidence,
        )


# --------------------------- Helpers -----------------------------------------

def _clamp(value: float, low: float, high: float) -> float:
    """Clamp a numeric value to [low, high]."""
    return max(low, min(high, value))


# --------------------------- Example usage -----------------------------------
if __name__ == "__main__":
    # Example profiles
    alice = User(income=5000.0, curr_balance=2000.0, expected_expenses=4500.0)
    bob = User(income=3000.0, curr_balance=500.0, expected_expenses=3800.0)

    print("-- Without eROI adjustment --")
    alice_result = alice.debt_risk_score(include_confidence=True)
    bob_result = bob.debt_risk_score(include_confidence=True)
    print("Alice:", alice_result)
    print("Bob:", bob_result)

    print("\n-- With eROI adjustment --")
    # Suppose Bob's recent spending had negative emotional ROI on average
    bob.adjust_for_emotional_roi(avg_eroi=-1.0)
    bob_result_adjusted = bob.debt_risk_score(include_confidence=True)
    print("Bob (after eROI = -1.0):", bob_result_adjusted)

    # Suppose Alice's recent spending had strong positive emotional ROI
    alice.adjust_for_emotional_roi(avg_eroi=1.5)
    alice_result_adjusted = alice.debt_risk_score(include_confidence=True)
    print("Alice (after eROI = +1.5):", alice_result_adjusted)

4. Wellness

You can receive a wellness score to determine how you usually feel overall, and see how many good vs bad sentiment transaction ratings you have. Also, you can see a graph that shows if your sentiment rating has inclined or declined from how many transactions you spent and the average sentiment rating for each date. We also have an AI Agent that analyzes your sentiment rating graph to establish patterns and trends.

How we built it

We used Next.js and Tailwind for the frontend. As for the backend, we used Flask and SQLite. I also integrated AI Agents with the @google/generative-ai library and use a Gemini API.

Challenges we ran into

A major challenge we faced was connecting the frontend and the backend together. It was difficult rendering information from the database, which was in the backend, into the frontend. However we were able to overcome that challenge and create an MVP on time.

Accomplishments that we're proud of

We were proud of creating a MVP and having the extra time implementing miscellaneous features, thus learning how to manage our time efficiently. We are also proud of creating a workable, fullstack app that can potentially be scaled as well as implementing AI features into our app. Additionally, we are proud of creating a fullstack app in the fintech field, an industry none of us had exposure to before.

What we learned

We learned how to integrate the frontend with the backend, how to extract data and visualize it to derive impactful insights, team collaboration, and real-world problem-solving. We also learned that fintech requires a lot of mathematical calculations.

What's next for MoodBank

  • We want to integrate transactions from 3rd party apps such as Stripe, Venmo, American Express, etc. in the future
  • Also we would like to handle multiple users next time to make the application more robust and veresatile

🎯 Why It’s Cool

  • 🫀 Emotion‑aware finance — tracks not just money, but meaning
  • 🧠 Smooth & realistic — tiny overspending doesn’t max out your risk
  • 🧰 Plug‑and‑play Python module — extendable for apps or dashboards
  • 💡 Hackathon‑ready — runs instantly, no setup or data training needed

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • TypeScript 66.3%
  • Python 30.7%
  • CSS 2.7%
  • JavaScript 0.3%