The problem
An Indian retail investor's mutual fund holdings are usually spread across several fund houses and two registrars. The one document that shows all of it in one place is the Consolidated Account Statement, and it arrives as a password-protected PDF built to be read by a person rather than parsed by a program.
So the first question any portfolio analytics tool has to answer is not analytical at all. It is whether you can reliably get the data out.
The second question is the one that actually costs investors money. A holding in a regular plan pays a trail commission to a distributor for as long as it is held. The direct plan of the same fund, same manager, same underlying portfolio, does not. Most investors do not know which one they hold, and the difference compounds quietly for years.
FinBlurock is a mutual fund portfolio analytics MVP built for a wealth management client, aimed at both of those questions.
CAS as the ingestion path
Choosing the CAS as the way in is the decision the rest of the product rests on.
The alternative was account aggregator APIs or per-registrar integrations. Those give cleaner data and take far longer to ship: commercial agreements, onboarding, and a separate set of quirks per provider. A CAS is available to every investor today, requires no integration with anyone, and the user already knows how to request one.
The cost is that you inherit a parsing problem.
Why there is only one parser
The parsing is built on casparser (v1.3.0) rather than a custom layout-aware extractor.
This is worth stating plainly because the obvious assumption is wrong. You would expect CAMS and KFintech, the two registrars, to need separate parsers producing separate shapes that then have to be reconciled. They do not. The CAS is a standardised cross-RTA format, so one library handles statements from both without branching.
That single fact removes what would otherwise have been the largest and least interesting chunk of work in the project, and it is the reason ingestion stopped being the bottleneck early enough for the analysis to get attention.
Using a maintained library here rather than writing a parser is the correct call for the same reason writing the XIRR was: parsing a standardised format is a solved problem with an actively maintained solution, and the returns calculation was not.
A dependency-free XIRR
Returns on a fund holding are irregular by nature. Money goes in on arbitrary dates in arbitrary amounts, SIPs and lump sums mixed together, sometimes partially redeemed along the way. A simple percentage return is meaningless against that cash flow. The correct measure is XIRR, the annualised internal rate of return for irregularly timed flows.
XIRR has no closed-form solution. It is found numerically, by iterating on a discount rate until the net present value of the cash flows reaches zero.
I wrote it from scratch, with no dependency.
Why not import one
The available options split into two unattractive groups. Some pull in a heavy numerical stack to provide a single function. The rest do not converge reliably on the cash flow shapes that actually show up in Indian retail portfolios: irregular intervals, partial redemptions, and mixed positive and negative flows in the same series.
That second problem is the real one. A returns figure that silently fails to converge on a subset of portfolios is worse than no figure at all, because nothing about the output tells you which portfolios were affected.
Newton-Raphson, with bisection underneath
The implementation runs Newton-Raphson with a bisection fallback.
Newton-Raphson is fast and converges quickly on well-behaved cash flows, which is most of them. It can also diverge on certain shapes, and when it diverges it does so unhelpfully rather than obviously.
Bisection is slower and cannot fail. It is guaranteed to converge on a bracketed root, so it catches every case Newton-Raphson walks away from.
Running the fast method first and falling back to the guaranteed one is the whole design. It gives Newton-Raphson's speed on the common path and bisection's guarantee on the tail, which for a financial calculation shown to an investor is the property that actually matters. A returns number that is correct 97 percent of the time is not a returns number.
What the analysis flags
Parsing and XIRR are table stakes. The output that changes behaviour is narrower, and in v1 it is deliberately narrow.
Regular versus direct plan detection, derived from the scheme name and the advisor ARN fields in the CAS itself. This turns an invisible recurring cost into a number on a screen.
AMC-level and single-fund concentration, computed directly from CAS data. Portfolios assembled one fund at a time drift into accidental concentration, and the most common form is simply too much of the portfolio sitting with one asset management company.
What v1 does not do
Category and sector-weight analysis, the look-through layer that would catch several funds holding substantially the same underlying stocks, is not in v1. It needs a holdings data source that is not the CAS, and that source is not wired in yet. It is the v2 layer.
Stating that plainly matters more than it might seem. Concentration analysis that claims to look through funds but only compares fund names would be a worse product than one that says exactly what it measures.
Decisions and trade-offs
CAS over aggregator APIs. Lower data fidelity, dramatically faster to a working product, and no dependency on anyone else's commercial timeline. Correct for an MVP whose job was to reach an investor demo.
A maintained parser, a hand-written XIRR. These look like opposite decisions and follow from the same rule: import the solved problem, own the one where correctness at the edges is the product.
The intake screen shipped before the results screen did. This is the trade-off I am least comfortable with, so it belongs in the open. The engine is real and working, CAS parsing, XIRR, plan detection, concentration flagging, and there is now a live screen to drop a CAS PDF into and run it. What is still ahead is the other half of the same problem: turning what the engine finds into something an investor looks at, rather than something an API returns. For a product whose entire value proposition is making an invisible cost visible, that reveal is still the more important surface to finish.
Outcome
Built toward an investor demo. The response was positive, and it is still early. There is meaningfully more work between this and a full product than between nothing and this.
What I would keep from it is the discipline about scope: an MVP that measures two things correctly and says so is more defensible than one that gestures at six. The v1 concentration layer is narrower than the pitch would like, and being straightforward about that boundary is what makes the numbers it does produce worth trusting.