Mutual fund CAGR and rolling returns
The rolling-summary endpoint returns annualised returns for 1, 3, 5 and 10 years. This guide reads them, checks them against your own calculation from NAV history, and then goes further to rolling one-year returns.
You need an API key: request a free beta key. Keep it in an environment variable, never in code you publish.
Script
import os
import requests
import pandas as pd
BASE = os.environ.get("EJI_BASE", "https://fin.ejiapi.com")
HEADERS = {"x-api-key": os.environ.get("EJI_KEY", "YOUR_KEY")}
def get(path, **params):
r = requests.get(BASE + path, params=params, headers=HEADERS, timeout=60)
r.raise_for_status()
return r.json()["data"]
# Ready-made annualised returns (percent). A value is None when the scheme lacks that much history.
print(get("/api/mf/scheme-code/122639/rolling-summary"))
# Check one figure yourself from the history
nav = pd.DataFrame(get("/api/mf/nav-history/scheme-code/122639"))
nav["date"] = pd.to_datetime(nav["date"])
nav = nav.set_index("date")["nav"]
def cagr(years):
end_date = nav.index[-1]
start_date = end_date - pd.DateOffset(years=years)
start_nav = nav[:start_date].iloc[-1] # last NAV on or before the start date
return ((nav.iloc[-1] / start_nav) ** (1 / years) - 1) * 100
for y in (1, 3, 5):
print(f"{y}y CAGR computed: {cagr(y):.2f}")
# Rolling 1-year returns: for each day, the return over the previous 365 days
s = nav.resample("D").last().ffill()
roll = (s / s.shift(365) - 1) * 100
print(roll.dropna().describe().round(2))Output
{'cagr1y': 0.18, 'cagr3y': 13.48, 'cagr5y': 11.9, 'cagr10y': 17.43}
1y CAGR computed: 0.18
3y CAGR computed: 13.63
5y CAGR computed: 11.90
count 4546.00
mean 20.05
std 18.38
min -21.27
25% 5.91
50% 17.06
75% 31.56
max 100.06
Name: nav, dtype: float64Why 3 years differs slightly
The 1 and 5 year figures match exactly; the 3 year figure is 13.48 from the API and 13.63 from the script. That is a date-convention difference, not an error: the script takes the last NAV on or before the exact start date, and the stored calculation may pick a neighbouring trading day. A one or two day shift in the start NAV moves a 3-year CAGR by a few hundredths. If you need a specific convention, compute it yourself from the history as shown.
Reading the distribution
The last block is the spread of every rolling one-year return since the fund's history begins. The maximum of 100% is an early-period outlier, which is why the median (17.06) says more than the mean. Past returns do not predict future returns.
- A figure is
nullwhen the scheme has less history than that period. - Returns here are from NAV, so for IDCW plans they ignore payouts. Growth plans are not affected.
Data comes from public disclosures and is for information, not investment advice. Sample outputs were produced on 2026-11-08 and change as new data is published.