While AMFI ( Association of Mutual Funds in India) provides the foundational NAV data, this guide focuses on the engineering required to build high-performance retrieval systems.
Each Mutual Fund scheme is identified by a unique, standardized scheme code; by programmatically targeting this identifier, we can retrieve real-time data points including the latest NAV (Net Asset Value), the most recent valuation date, and the official scheme nomenclature.import requests
def get_latest_nav(scheme_code):
url = f"https://api.mfapi.in/mf/{scheme_code}/latest"
response = requests.get(url)
data = response.json()
latest_nav = data['data'][0]['nav']
date = data['data'][0]['date']
fund_name = data['meta']['scheme_name']
return fund_name, latest_nav, date
# Example: Quant Small Cap Fund (Direct Plan)
name, nav, date = get_latest_nav("120847")
print(f"Fund: {name} | Current NAV: {nav} | Date: {date}")Fund: quant ELSS Tax Saver Fund - Growth Option - Direct Plan | Current NAV: 414.31430 | Date: 09-01-2026
/latest — Appended to the URL to fetch only the most recent data point, reducing payload size.
data['data'][0]['date'] — Specifically extracts the timestamp of the last updated NAV from the API response.
return fund_name, latest_nav, date — Returns a tuple containing all three critical data points for further processing.
print(f"... Date: {date}") — Uses Python f-strings to display the formatted output in the console.
# Input scheme list
input_schemes = [
{"schemeCode": 120251, "schemeName": "ICICI Prudential Equity & Debt Fund Direct Growth"},
{"schemeCode": 118955, "schemeName": "HDFC Flexi Cap Direct Plan Growth"},
{"schemeCode": 120334, "schemeName": "ICICI Prudential Multi Asset Fund Direct Growth"}
]
For production environments, this input list can be dynamically retrieved from databases such as SQLite or MySQL. Furthermore, the processed outputs can be archived back into storage for historical analysis and reporting.
Below is the complete, integrated implementation.
import requests
import json
from datetime import datetime
def fetch_latest_navs(scheme_list):
"""
Retrieves the most recent NAV and corresponding date for a list of funds.
"""
base_url = "https://api.mfapi.in/mf/"
final_report = []
print(f"{'SCHEME NAME':<65} | {'NAV':<10} | {'DATE':<12}")
print("=" * 92)
for scheme in scheme_list:
code = scheme['schemeCode']
name = scheme['schemeName']
try:
# Request data from MFAPI
response = requests.get(f"{base_url}{code}/latest", timeout=10)
response.raise_for_status()
data = response.json()
if "data" in data and len(data["data"]) > 0:
# API data is usually in reverse chronological order.
latest = data["data"][0]
nav = latest["nav"]
date = latest["date"]
final_report.append({
"name": name,
"code": code,
"nav": nav,
"date": date
})
# Truncated name for table alignment
short_name = (name[:62] + '..') if len(name) > 65 else name
print(f"{short_name:<65} | {nav:<10} | {date:<12}")
else:
print(f"Data missing for: {name}")
except Exception as e:
print(f"Could not retrieve {code}: {e}")
return final_report
if __name__ == "__main__":
# Input scheme list
input_schemes = [
{"schemeCode": 120251, "schemeName": "ICICI Prudential Equity & Debt Fund Direct Growth"},
{"schemeCode": 118955, "schemeName": "HDFC Flexi Cap Direct Plan Growth"},
{"schemeCode": 120334, "schemeName": "ICICI Prudential Multi Asset Fund Direct Growth"}
]
print(f"Querying MFAPI for latest records...\n")
results = fetch_latest_navs(input_schemes)
Querying MFAPI for latest records...
SCHEME NAME | NAV | DATE
=================================================================================
ICICI Prudential Equity & Debt Fund Direct Growth | 453.09000 | 09-01-2026
HDFC Flexi Cap Direct Plan Growth | 2264.30200 | 09-01-2026
ICICI Prudential Multi Asset Fund Direct Growth | 898.67790 | 09-01-2026
import requests
import matplotlib.pyplot as plt
from datetime import datetime
def fetch_and_plot_nav(scheme_code):
"""
Fetches historical NAV data for a given scheme code from mfapi.in
and plots the variation over time.
"""
api_url = f"https://api.mfapi.in/mf/{scheme_code}"
print(f"Fetching data for Scheme Code: {scheme_code}...")
try:
response = requests.get(api_url, timeout=10)
response.raise_for_status()
data = response.json()
if data.get("status") != "SUCCESS":
print("Error: Could not find data for this scheme code.")
return
scheme_name = data['meta']['scheme_name']
nav_data = data['data']
# Extract dates and NAV values
# We take the last 60 entries for a clear 2-month view
subset = nav_data[:60]
# Parse dates and convert NAVs to floats
dates = [datetime.strptime(item['date'], '%d-%m-%Y') for item in subset]
nav_values = [float(item['nav']) for item in subset]
# Sort by date
plot_data = sorted(zip(dates, nav_values))
dates, nav_values = zip(*plot_data)
# Plotting
plt.figure(figsize=(10, 6))
plt.plot(dates, nav_values, marker='o', linestyle='-',
color='b', markersize=4)
plt.title(f"NAV Variation: {scheme_name}", fontsize=12)
plt.xlabel("Date")
plt.ylabel("Net Asset Value (NAV)")
plt.grid(True, linestyle='--', alpha=0.7)
plt.xticks(rotation=45)
plt.tight_layout()
print("Displaying graph...")
plt.show()
except requests.exceptions.RequestException as e:
print(f"Network error: {e}")
except Exception as e:
print(f"An unexpected error occurred: {e}")
if __name__ == "__main__":
print("--- Mutual Fund NAV Tracker ---")
user_code = input("Enter the Mutual Fund Scheme Code: ").strip()
if user_code.isdigit():
fetch_and_plot_nav(user_code)
else:
print("Please enter a valid numeric scheme code.")
Once the current Net Asset Value (NAV) is retrieved for each scheme, you can determine your total investment value by multiplying the NAV by the number of units held. This provides a real-time snapshot of your portfolio's worth:
Integrating this logic allows for automated tracking of gains, losses, and overall asset allocation.
Keeping track of multiple Mutual Fund investments can be tedious if done manually. This Python script automates the process by connecting directly to the Open Source Mutual Fund API (mfapi.in) to fetch real-time Net Asset Values (NAV) and calculate your total portfolio valuation instantly.
The script features Exponential Backoff logic. If the API is busy, the script intelligently waits and retries (1s, 2s, 4s, etc.), ensuring your data is fetched even under unstable network conditions.
By mapping your specific schemeCodes and units, the code performs automated multiplication and aggregation to provide a "Grand Total" of your net worth across various fund houses.
requests library to pull live JSON data from the AMFI-linked API endpoints.import requests
import json
import time
from datetime import datetime
def fetch_nav_with_retry(scheme_code):
"""
Fetches the latest NAV for a given scheme code from the AMFI API.
Implements exponential backoff for reliability.
"""
api_url = f"https://api.mfapi.in/mf/{scheme_code}"
retries = 5
delay = 1
for i in range(retries):
try:
response = requests.get(api_url, timeout=10)
response.raise_for_status()
data = response.json()
# The API returns a list of NAVs, we take the most recent one (index 0)
if "data" in data and len(data["data"]) > 0:
latest_nav_data = data["data"][0]
return {
"nav": float(latest_nav_data["nav"]),
"date": latest_nav_data["date"]
}
return None
except (requests.RequestException, ValueError, KeyError):
if i < retries - 1:
time.sleep(delay)
delay *= 2 # Exponential backoff: 1s, 2s, 4s, 8s, 16s
else:
return None
def calculate_portfolio():
# User Input Data , expand this list based
input_schemes = [
{"schemeCode": 120251,
"schemeName": "ICICI Prudential Equity & Debt Fund Direct Growth",
"Units": 100.02},
{"schemeCode": 118955,
"schemeName": "HDFC Flexi Cap Direct Plan Growth",
"Units": 250.589},
{"schemeCode": 120334,
"schemeName": "ICICI Prudential Multi Asset Fund Direct Growth",
"Units": 200.567}
]
results = []
total_portfolio_value = 0.0
print("Fetching real-time data from AMFI...")
for scheme in input_schemes:
nav_info = fetch_nav_with_retry(scheme["schemeCode"])
if nav_info:
current_value = nav_info["nav"] * scheme["Units"]
total_portfolio_value += current_value
results.append({
"Date": nav_info["date"],
"Fund Name": scheme["schemeName"],
"NAV": nav_info["nav"],
"Units": scheme["Units"],
"Investment": round(current_value, 2)
})
else:
print(f"Error: Could not fetch data for {scheme['schemeName']}")
# --- OUTPUT ---
print("\n" + "="*80)
print(f" TOTAL INVESTMENT VALUE: ₹{total_portfolio_value:,.2f}")
print("="*80)
# Header
print(f"{'Date':<12} | {'Fund Name':<50} | {'NAV':<8} | {'Units':<10} | {'Investment':<12}")
print("-" * 105)
# Rows
for r in results:
print(f"{r['Date']:<12} | {r['Fund Name'][:50]:<50} | {r['NAV']:<8.2f} | {r['Units']:<10.3f} | ₹{r['Investment']:<12,.2f}")
if __name__ == "__main__":
calculate_portfolio()
import requests
import json
import time
import pandas as pd
from datetime import datetime
def fetch_nav_with_retry(scheme_code):
"""
Fetches the latest NAV for a given scheme code from the AMFI API.
Implements exponential backoff for reliability.
"""
api_url = f"https://api.mfapi.in/mf/{scheme_code}"
retries = 5
delay = 1
for i in range(retries):
try:
response = requests.get(api_url, timeout=10)
response.raise_for_status()
data = response.json()
# The API returns a list of NAVs, we take the most recent one (index 0)
if "data" in data and len(data["data"]) > 0:
latest_nav_data = data["data"][0]
return {
"nav": float(latest_nav_data["nav"]),
"date": latest_nav_data["date"]
}
return None
except (requests.RequestException, ValueError, KeyError):
if i < retries - 1:
time.sleep(delay)
delay *= 2 # Exponential backoff
else:
return None
def calculate_portfolio():
# --- LOAD DATA FROM FILE ---
try:
# Update filename here if needed. Using pd.read_csv for your uploaded file.
#df = pd.read_csv('input_schemes.xlsx - Sheet1.csv')
df = pd.read_excel('E:\\testing3\\input_schemes.xlsx', sheet_name='Sheet1')
# Convert dataframe to a list of dictionaries to maintain the loop logic
input_schemes = df.to_dict('records')
except Exception as e:
print(f"Error reading the file: {e}")
return
results = []
total_portfolio_value = 0.0
print(f"Fetching real-time data for {len(input_schemes)} funds from AMFI...")
for scheme in input_schemes:
# Note: Ensure keys match the column names in your CSV exactly
nav_info = fetch_nav_with_retry(scheme["schemeCode"])
if nav_info:
current_value = nav_info["nav"] * scheme["Units"]
total_portfolio_value += current_value
results.append({
"Date": nav_info["date"],
"Fund Name": scheme["schemeName"],
"NAV": nav_info["nav"],
"Units": scheme["Units"],
"Investment": round(current_value, 2)
})
else:
print(f"Error: Could not fetch data for {scheme['schemeName']}")
# --- OUTPUT ---
print("\n" + "="*85)
print(f" TOTAL PORTFOLIO VALUE: ₹{total_portfolio_value:,.2f}")
print("="*85)
# Header
print(f"{'Date':<12} | {'Fund Name':<40} | {'NAV':<8} | {'Units':<10} | {'Value (₹)':<12}")
print("-" * 95)
# Rows
for r in results:
print(f"{r['Date']:<12} | {r['Fund Name'][:40]:<40} | {r['NAV']:<8.2f} | {r['Units']:<10.3f} | ₹{r['Investment']:<12,.2f}")
if __name__ == "__main__":
calculate_portfolio()
Access raw master data for all mutual fund schemes including scheme codes, types, and classification categories via the official AMFI portal.
Curious how the stock prices are fetched in the background? Check out the Backend Data Logic for this monitor.
View Backend Fetching LogicReady to simplify your code? Learn how to use the mftool wrapper to fetch AMFI data even faster without manual API handling.
Author
🎥 Join me live on YouTubePassionate about coding and teaching, I publish practical tutorials on PHP, Python, JavaScript, SQL, and web development. My goal is to make learning simple, engaging, and project‑oriented with real examples and source code.