Spaces:
Running
Running
| """ | |
| Data models for MF Portfolio Analysis Tool. | |
| """ | |
| from dataclasses import dataclass, field | |
| from typing import Optional | |
| class Fund: | |
| """Represents a single mutual fund scheme from the fund universe CSV.""" | |
| name: str | |
| category: str | |
| benchmark: str | |
| # Cost | |
| ter: Optional[float] = None # Total Expense Ratio (%) | |
| turnover: Optional[float] = None # Portfolio Turnover (%) | |
| # Returns | |
| mean: Optional[float] = None | |
| cagr_1y: Optional[float] = None | |
| cagr_1y_cat: Optional[float] = None | |
| cagr_1y_bm: Optional[float] = None | |
| cagr_3y: Optional[float] = None | |
| cagr_3y_cat: Optional[float] = None | |
| cagr_3y_bm: Optional[float] = None | |
| cagr_5y: Optional[float] = None | |
| cagr_5y_cat: Optional[float] = None | |
| cagr_5y_bm: Optional[float] = None | |
| cagr_10y: Optional[float] = None | |
| cagr_10y_cat: Optional[float] = None | |
| cagr_10y_bm: Optional[float] = None | |
| cagr_inception: Optional[float] = None | |
| nav: Optional[float] = None | |
| # Valuation | |
| pe_ratio: Optional[float] = None | |
| pb_ratio: Optional[float] = None | |
| # Risk metrics | |
| alpha: Optional[float] = None | |
| beta: Optional[float] = None | |
| std_dev: Optional[float] = None | |
| sharpe: Optional[float] = None | |
| volatility: Optional[float] = None | |
| sortino: Optional[float] = None | |
| up_capture: Optional[float] = None | |
| down_capture: Optional[float] = None | |
| max_drawdown: Optional[float] = None | |
| r_squared: Optional[float] = None | |
| info_ratio: Optional[float] = None | |
| aum: Optional[float] = None | |
| fill_status: Optional[str] = None | |
| # Scoring (computed) | |
| score: Optional[float] = None | |
| rank_in_category: Optional[int] = None | |
| is_top_quartile: bool = False | |
| weightage: Optional[int] = None # Number of periods beating benchmark | |
| order: int = 0 # Preserves original CSV insertion order for sort tiebreaker | |
| class ClientHolding: | |
| """Represents a single mutual fund holding in a client's portfolio.""" | |
| scheme_name: str | |
| current_value: float | |
| invested_amount: Optional[float] = None | |
| sip_amount: Optional[float] = None | |
| sip_frequency: Optional[str] = None # Monthly / Quarterly etc. | |
| # Matched fund data | |
| fund: Optional[Fund] = None | |
| # Computed | |
| allocation_pct: float = 0.0 | |
| xirr: Optional[float] = None | |
| is_underperforming: bool = False | |
| # Advisory | |
| suggested_fund: Optional[Fund] = None | |
| switch_reason: Optional[str] = None | |
| class Client: | |
| """Client details.""" | |
| name: str | |
| age: Optional[int] = None | |
| email: Optional[str] = None | |
| mobile: Optional[str] = None | |
| pan: Optional[str] = None | |
| class Advisor: | |
| """Financial advisor details.""" | |
| name: str = "RAVICHANDRAN" | |
| phone: str = "9281364703" | |
| email: str = "c4c.ravi@gmail.com" | |
| arn: str = "ARN-243354" | |
| location: str = "Chennai" | |
| class PortfolioReport: | |
| """The complete portfolio analysis report for a client.""" | |
| client: Client | |
| advisor: Advisor | |
| holdings: list = field(default_factory=list) | |
| # Portfolio-level metrics | |
| total_current_value: float = 0.0 | |
| total_invested: float = 0.0 | |
| unrealized_gain: float = 0.0 | |
| portfolio_xirr: Optional[float] = None | |
| sharpe: Optional[float] = None | |
| alpha: Optional[float] = None | |
| beta: Optional[float] = None | |
| std_dev: Optional[float] = None | |
| # Exposure warnings | |
| amc_exposure: dict = field(default_factory=dict) # AMC -> pct | |
| scheme_exposure: dict = field(default_factory=dict) # scheme -> pct | |
| exposure_warnings: list = field(default_factory=list) # list of warning strings | |
| # Allocation | |
| market_cap_allocation: dict = field(default_factory=dict) # Large/Mid/Small/Other -> pct | |
| sector_allocation: dict = field(default_factory=dict) # sector -> pct | |
| # Wealth projection | |
| wealth_projection: dict = field(default_factory=dict) # years -> projected value | |