@finctrl/core
v1.0.6
Published
Core financial engines for Indian taxation, mutual fund comparison, and lifestyle-driven retirement planning.
Maintainers
Readme
FinCtrl Core
Financial Engines Built for India
Lightweight JavaScript engines built to model Indian taxation, investing, and retirement planning with domain-aware assumptions.
What is this?
FinCtrl Core is the brain behind our financial applications. It's a collection of pure JavaScript calculation engines designed specifically for the unique financial landscape of India.
We built this because most financial tools are packaged as closed UI calculators rather than reusable computation engines. FinCtrl provides composable financial models designed for Indian contexts - covering taxation, mutual funds, and lifestyle-driven planning - so developers can integrate realistic financial logic directly into their applications.
This library is essentially a set of "business logic" modules. It doesn't care about React, Vue, or the DOM. It takes numbers in and returns structured results.
The Engines
1. Advance Tax Estimator
🔗 Live demo: finctrl.app/advance-tax-estimator
The Problem: Most people wait until March to think about taxes. But the government expects you to pay as you earn. Calculating advance tax installments manually (15% by June, 45% by Sept, etc.) while accounting for TDS and estimated capital gains is a headache.
Our Design Approach:
The Indian Tax Code is treated as configuration, not hardcoded logic. All year-specific constants - tax slabs, basic exemptions (by age), LTCG exemption threshold, cess rate - live in a single versioned config file (src/config/taxRules.js). The engine looks up the right rules at runtime based on taxYear and regime. When the Finance Minister announces a new budget, you add one entry to the config and the engine adapts automatically. Capital Gains (STCG/LTCG) are handled with their own flat-rate logic, separate from the slab calculation, which is a common omission in generic calculators.
Usage:
import { AdvanceTaxEngine } from '@finctrl/core'
const inputs = {
taxYear: '2024-25', // Which FY to compute for
regime: 'new', // 'new' or 'old'
fdAndOtherIncome: 12_00_000, // 12 Lakhs from FD / other sources
stcgAmount: 50_000, // Short Term Capital Gains
stcgTaxRate: 20, // 20%
ltcgAmount: 1_00_000, // Long Term Capital Gains
ltcgTaxRate: 12.5, // 12.5%
tdsDeducted: 20_000, // TDS already deducted
advanceTaxPaid: 10_000, // Advance tax already paid
ageGroup: '0-60', // '0-60', '60-80', or '80+'
exemptionMode: 'age-based', // 'age-based' (standard) or 'custom'
manualSlab: 'auto' // 'auto' = engine picks the right slab
};
const result = AdvanceTaxEngine.calculate(inputs);
console.log(result.totalTax); // Total tax liability (before TDS/payments)
console.log(result.netTaxPayable); // Tax remaining after TDS & advance paid
console.log(result.schedule); // Array of installments with due dates & amounts
console.log(result.ltcgExemption); // Exemption applied (e.g. 125000 for FY 2024-25)Tip: If
taxYearandregimeare omitted, the engine defaults to the latest year and new regime (DEFAULT_TAX_YEAR,DEFAULT_REGIME).
2. Mutual Fund Comparator (Direct vs Regular)
🔗 Live demo: finctrl.app/regular-vs-direct
The Problem: A 1% difference in expense ratio (TER) sounds trivial. Agents often say, "It's just a small fee for my advice." But over 20 years, that "small fee" can eat up 20-30% of your total corpus due to the lost compounding effect.
Our Design Approach: We wanted to make the "Cost of Ignorance" visible. The engine uses standard compound interest formulas but runs two parallel simulations: one for the Direct plan and one for the Regular plan. It then diffs the final amounts to show the raw currency value of that 1% difference. It's designed to be a "shock" engine - simple math, profound impact.
Usage:
import { MFComparatorEngine } from '@finctrl/core'
const inputs = {
currentInvestment: 5_00_000, // Initial lump sum (5 Lakhs)
investmentPeriod: 20, // Years to grow
expectedReturn: 12, // 12% annual return
terRegular: 2.0, // 2% Expense Ratio (Agent)
terDirect: 1.0 // 1% Expense Ratio (Direct)
};
const result = MFComparatorEngine.calculate(inputs);
console.log(result.difference); // Extra money made in Direct plan
console.log(result.percentageGain); // % gain over Regular plan3. Lifestyle Retirement Planner
🔗 Live demo: finctrl.app/retirement-planner
The Problem: Traditional retirement calculators ask, "What is your current income?" This is flawed. You don't replace your income in retirement; you pay for your lifestyle. A person earning ₹50L but living simply needs less corpus than a person earning ₹30L with expensive tastes.
Our Design Approach: We flipped the model. Instead of income, we ask about lifestyle markers:
- Do you send kids to international schools?
- Do you vacation in Europe or local hill stations?
- Do you drive a luxury sedan or a hatchback?
The engine assigns a "Lifestyle Index" (0-100) based on these inputs and places you in one of 5 classes:
- Lower Middle (0-25): Basic sustenance, government schools, minimal travel.
- Middle (25-45): Stability, mid-range schools, occasional domestic travel.
- Upper Middle (45-65): Comfort, good private schools, active lifestyle.
- Affluent (65-85): Luxury, international schools, frequent travel.
- High Affluence (85-100): Elite lifestyle, no compromise on quality of life.
It then calculates the retirement corpus needed to sustain that specific lifestyle, adjusting for inflation and medical buffers particular to that class. It's a behavioral model, not just a financial one.
Usage:
import { RetirementPlannerEngine } from '@finctrl/core'
const inputs = {
currentAge: 30,
yearsToRetirement: 25,
cityTier: 'Metro', // 'Metro', 'Tier-1', 'Tier-2', 'Tier-3'
housing: 'Rented', // 'Rented', 'Owned apartment', 'Gated society', ...
rentEmi: '25k–50k', // Rent/EMI bracket
schoolFees: '1.5L–3L', // Annual school fees bracket
travel: 'Twice a year', // Travel frequency
car: 'Mid Range', // Car segment
};
const result = RetirementPlannerEngine.calculate(inputs);
// Classification
console.log(result.lifestyleCategory.name); // e.g., "Upper Middle"
console.log(result.lifestyleIndex); // e.g., "54.3"
// Expenses (decimal strings, in Lakhs per year)
console.log(result.annualExpenseToday); // e.g., "9.45" (today's annual spend)
console.log(result.retirementAnnualExpenseToday); // e.g., "7.56" (retirement spend, today's ₹)
// Corpus (decimal strings, in Crores - future inflated value)
console.log(result.corpusRange.standard.corpusInCrores); // e.g., "3.82" Cr
console.log(result.corpusRange.standard.corpusInCroresPV); // e.g., "1.79" Cr (today's ₹)Tax Rules Configuration
All year- and regime-specific tax constants are stored in src/config/taxRules.js. These are fully exported so consuming applications can build dynamic UIs (e.g. year pickers, regime toggles) without hardcoding their own copies.
import {
TAX_RULES, // Full config object keyed by year → regime
getTaxRules, // (taxYear, regime) → rule set for that year/regime
getTaxYears, // () → sorted list of supported years, e.g. ['2025-26', '2024-25', ...]
DEFAULT_TAX_YEAR, // '2025-26'
DEFAULT_REGIME, // 'new'
} from '@finctrl/core';
// Look up the LTCG exemption for a specific year
const rules = getTaxRules('2024-25', 'old');
console.log(rules.ltcgExemption); // 125000
console.log(rules.basicExemption['0-60']); // 250000
console.log(rules.slabs); // [...old regime slab array]Adding a new budget year (e.g. after Budget 2026):
- Open
src/config/taxRules.js - Add a
'2026-27'key withnewandoldregime entries - No engine or UI changes needed - the new year appears automatically
Installation
Requires Node.js 18.0.0 or higher. Install via npm:
npm install @finctrl/coreAPI Reference
| Engine | Method | Key Output Fields |
|---|---|---|
| AdvanceTaxEngine | calculate(inputs) | totalTax, netTaxPayable, schedule, ltcgExemption |
| MFComparatorEngine | calculate(inputs) | difference, percentageGain |
| RetirementPlannerEngine | calculate(inputs) | lifestyleCategory, lifestyleIndex, corpusRange, annualExpenseToday |
| getTaxRules | getTaxRules(year, regime) | Full rule set: slabs, basicExemption, ltcgExemption, cess |
| getTaxYears | getTaxYears() | Sorted array of supported FY strings |
Examples
Detailed code examples for each engine are available in the examples/ directory.
# Advance Tax Calculator
node examples/advance_tax_example.js
# MF Direct vs Regular Comparator
node examples/mf_comparator_example.js
# Retirement Planner
node examples/retirement_planner_example.jsDebugging
Pass debug: true in any engine's inputs to log verbose internal calculations to the console:
AdvanceTaxEngine.calculate({ ...inputs, debug: true })Contributing
We welcome contributions! If you find a bug in a tax calculation or want to add a new engine, here's how to get started:
- Fork the repo and create your branch from
main. - Make your changes and add tests where applicable.
- Run the test suite:
npm test - Open a pull request - describe what you changed and why.
For bugs or feature ideas, open an issue on GitHub.
Ideas for future engines: Home Loan Prepayment Analyzer, NPS Corpus Estimator, HRA Exemption Calculator.
License
This project is licensed under the Apache License 2.0.
- You are free to use, modify, and distribute this software.
- You can use it in commercial applications.
- You must include a copy of the license and copyright notice with any distribution.
- This software is provided "as is" without warranty.
See the LICENSE file for the full text.
