# mayureshw/mftools architecture

> Architecture diagram of the GitHub repository mayureshw/mftools, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-06-20). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/mayureshw/mftools
- Repository: https://github.com/mayureshw/mftools

## Overview

1. **Overall shape**
   - This repository is a **Python batch-processing tool** for mutual fund portfolio analysis.
   - It is not a web app or service; the architecture is a **file-in / file-out pipeline**: user-provided statements and fund master data are read, normalized, analyzed, and rendered into text reports.

2. **Main entry points**
   - `pfviews.py` is the primary executable for report generation. It orchestrates the full portfolio analysis workflow and writes the report files.
   - `amfi2gfg.py` is a separate utility focused on one data-preparation task: building grandfathered NAV data from AMFI.
   - The remaining modules are support libraries rather than standalone entry points.

3. **Input sources and external boundaries**
   - The tool consumes **CAMS registrar statements**: transaction history (`txns.xls`) and current valuation (`bals.xls`).
   - It also consumes **Value Research fund analysis data**, converted from spreadsheet to CSV before use.
   - Optional reference data comes from:
     - `cii.json` for Cost Inflation Index values.
     - `gfnav.json` for grandfathered NAV values.
   - These files are treated as external or semi-external inputs, usually located under `MFDOCSDIR` / `PFDATDIR`.

4. **Configuration boundary**
   - `conf.py` likely centralizes environment-driven paths and runtime settings.
   - The runtime depends on environment variables described in the README:
     - `XLS2PYSPECDIR` for spreadsheet parsing templates,
     - `MFDOCSDIR` for shared fund documents,
     - `PFDATDIR` for personal statement files,
     - `PYTHONPATH` to expose the `xls2pyobj` dependency.
   - This means the application is configured primarily by **filesystem layout plus environment**, not by a database or server config.

5. **Data ingestion and normalization**
   - `pfdata.py` is the likely ingestion/model layer.
   - Its responsibility is to parse registrar statements and fund metadata into a common internal representation: funds, holdings, buy/sell transactions, valuation snapshots, and reference attributes.
   - This is the main boundary where heterogeneous inputs are normalized into a consistent portfolio data model.

6. **Reference-data enrichment**
   - `cii.json` is used to compute indexed cost and indexed gain where applicable.
   - `gfnav.json` is used to compute grandfathered gains for equity funds with holdings or sales spanning the 31 Jan 2018 cutoff.
   - The application enriches transaction/holding data with these auxiliary datasets before report generation.

7. **Analysis and business logic**
   - `reports.py` likely contains the core computation and formatting logic for:
     - current portfolio value, cost, gain, CAGR,
     - unrealized gain per buy lot,
     - realized gain per sale transaction,
     - cashflow totals by financial year and transaction type.
   - The business rules include tax-related distinctions such as equity vs debt treatment and holding-period thresholds.
   - This layer is where portfolio math, gain classification, and grouping logic live.

8. **Report generation outputs**
   - `pfviews.py` produces plain-text report artifacts in the current working directory:
     - `pfreports.txt` for portfolio summaries and category views,
     - `pfgainreport.txt` for unrealized gains,
     - `rgainreport.txt` for realized gains,
     - `cashflowreport.txt` for year-wise cashflow totals.
   - The output format is intentionally simple and human-readable, suggesting the tool is designed for manual review and tax/portfolio reconciliation.

9. **AMFI utility flow**
   - `amfi2gfg.py` is a focused side pipeline that retrieves 31-Jan-2018 NAV data from AMFI and writes it into the `gfnav.json` format expected by the main reporting flow.
   - This utility supports one specific enrichment step in the main architecture rather than participating in daily report generation.

10. **Technology and operational profile**
   - The repo is pure **Python 3** with no server runtime, no persistent database, and no frontend.
   - It relies on local files, spreadsheet conversion tooling, and the `xls2pyobj` package for reading Excel-derived inputs.
   - The architecture is therefore best represented as:
     - **External documents and reference files** → **Python parsing/normalization layer** → **analysis/reporting layer** → **text reports**.

Main entry points: [`pfdata.py`](https://github.com/mayureshw/mftools/blob/master/pfdata.py) (Portfolio data), [`pfviews.py`](https://github.com/mayureshw/mftools/blob/master/pfviews.py) (Runner), [`reports.py`](https://github.com/mayureshw/mftools/blob/master/reports.py) (Reports), [`conf.py`](https://github.com/mayureshw/mftools/blob/master/conf.py) (Config)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_inputs["Inputs"]
  node_cams_txns["CAMS txns<br/>external xls"]
  node_cams_bals["CAMS bals<br/>external xls"]
  node_value_research["VR data<br/>external csv"]
  node_cii["CII data<br/>reference json<br/>[cii.json]"]
  node_gfnav["GF NAV<br/>reference json<br/>[gfnav.json]"]
  node_xls2pyobj(("XLS parser<br/>dependency"))
  node_amfi_nav["AMFI NAV<br/>external source"]
end

subgraph group_core["Core"]
  node_conf["Config<br/>[conf.py]"]
  node_pfdata["Portfolio data<br/>ingest/model<br/>[pfdata.py]"]
  node_reports["Reports<br/>analysis/formatting<br/>[reports.py]"]
  node_pfviews["Runner<br/>batch entrypoint<br/>[pfviews.py]"]
end

subgraph group_outputs["Outputs"]
  node_pfreports["Portfolio report<br/>text output"]
  node_pfgainreport["Unrealized gains<br/>text output"]
  node_rgainreport["Realized gains<br/>text output"]
  node_cashflowreport["Cashflows<br/>text output"]
end

subgraph group_utility["Utility"]
  node_amfi2gfg["AMFI prep<br/>data utility<br/>[amfi2gfg.py]"]
end

node_cams_txns -->|"parse"| node_pfdata
node_cams_bals -->|"parse"| node_pfdata
node_value_research -->|"enrich"| node_pfdata
node_xls2pyobj -->|"read xls"| node_pfdata
node_conf -->|"paths"| node_pfdata
node_conf -->|"settings"| node_reports
node_pfdata -->|"portfolio model"| node_reports
node_cii -->|"indexed cost"| node_reports
node_gfnav -->|"tax basis"| node_reports
node_reports -->|"render"| node_pfviews
node_pfviews -->|"write"| node_pfreports
node_pfviews -->|"write"| node_pfgainreport
node_pfviews -->|"write"| node_rgainreport
node_pfviews -->|"write"| node_cashflowreport
node_amfi_nav -->|"source"| node_amfi2gfg
node_amfi2gfg -->|"build"| node_gfnav

click node_conf "https://github.com/mayureshw/mftools/blob/master/conf.py"
click node_pfdata "https://github.com/mayureshw/mftools/blob/master/pfdata.py"
click node_reports "https://github.com/mayureshw/mftools/blob/master/reports.py"
click node_pfviews "https://github.com/mayureshw/mftools/blob/master/pfviews.py"
click node_amfi2gfg "https://github.com/mayureshw/mftools/blob/master/amfi2gfg.py"
click node_cii "https://github.com/mayureshw/mftools/blob/master/cii.json"
click node_gfnav "https://github.com/mayureshw/mftools/blob/master/gfnav.json"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_cams_txns,node_cams_bals,node_value_research,node_cii,node_gfnav,node_xls2pyobj,node_amfi_nav toneBlue
class node_conf,node_pfdata,node_reports,node_pfviews toneAmber
class node_pfreports,node_pfgainreport,node_rgainreport,node_cashflowreport toneMint
class node_amfi2gfg toneRose
```

## Components

### Inputs

External statements and reference datasets consumed by the batch pipeline.

- **CAMS txns**: external xls · Transaction history input from CAMS registrar statements.
- **CAMS bals**: external xls · Current valuation input from CAMS registrar statements.
- **VR data**: external csv · Fund analysis and master data converted from spreadsheet to CSV.
- [CII data](https://github.com/mayureshw/mftools/blob/master/cii.json): reference json · Cost Inflation Index values used for indexed cost and gain. · `cii.json`
- [GF NAV](https://github.com/mayureshw/mftools/blob/master/gfnav.json): reference json · Grandfathered NAV values for equity tax calculations. · `gfnav.json`
- **XLS parser**: dependency · Spreadsheet parsing helper exposed through PYTHONPATH.
- **AMFI NAV**: external source · AMFI 31-Jan-2018 NAV source used to populate grandfathered NAV data.

### Core

Parsing, normalization, and portfolio analysis logic.

- [Config](https://github.com/mayureshw/mftools/blob/master/conf.py): runtime config · Environment-driven paths and runtime settings. · `conf.py`
- [Portfolio data](https://github.com/mayureshw/mftools/blob/master/pfdata.py): ingest/model · Parses statements and fund metadata into the internal portfolio model. · `pfdata.py`
- [Reports](https://github.com/mayureshw/mftools/blob/master/reports.py): analysis/formatting · Computes holdings, gains, cashflows, and report sections. · `reports.py`
- [Runner](https://github.com/mayureshw/mftools/blob/master/pfviews.py): batch entrypoint · Orchestrates the full portfolio workflow and writes report files. · `pfviews.py`

### Outputs

Human-readable report artifacts written by the runner.

- **Portfolio report**: text output · Summary and category views for the portfolio.
- **Unrealized gains**: text output · Per-lot unrealized gain report.
- **Realized gains**: text output · Sale-level realized gain report.
- **Cashflows**: text output · Year-wise cashflow totals and transaction breakdowns.

### Utility

Standalone data-preparation helper for grandfathered NAVs.

- [AMFI prep](https://github.com/mayureshw/mftools/blob/master/amfi2gfg.py): data utility · Builds grandfathered NAV data from AMFI source data. · `amfi2gfg.py`

## Connections

- CAMS txns → Portfolio data: parse · Transaction history is normalized into the portfolio model.
- CAMS bals → Portfolio data: parse · Current valuation snapshots are normalized into the portfolio model.
- VR data → Portfolio data: enrich · Fund metadata and analysis data are attached during ingestion.
- XLS parser → Portfolio data: read xls · Excel parsing support for registrar statements and derived sheets.
- Config → Portfolio data: paths · Provides filesystem locations and runtime settings for ingestion.
- Config → Reports: settings · Controls report-time paths and runtime behavior.
- Portfolio data → Reports: portfolio model · Normalized holdings, transactions, and reference attributes feed analysis.
- CII data → Reports: indexed cost · Inflation index values support indexed cost and gain calculations.
- GF NAV → Reports: tax basis · Grandfathered NAV values support equity gain calculations.
- Reports → Runner: render · Computed sections are assembled into final report files.
- Runner → Portfolio report: write · Writes the main portfolio summary report.
- Runner → Unrealized gains: write · Writes unrealized gain details.
- Runner → Realized gains: write · Writes realized gain details.
- Runner → Cashflows: write · Writes cashflow summaries.
- AMFI NAV → AMFI prep: source · AMFI source data is used to derive grandfathered NAV entries.
- AMFI prep → GF NAV: build · Produces the gfnav.json reference used by the main report flow.
