Factor Research TerminalDeveloped by Neel Thakur

Research notes · Methods & assumptions

Methodology

Every figure on this site is produced by the same rules as the project’s Python research code, and checked against it automatically.

Data and alignment

Figures use daily Nifty Total Return Index (TRI) levels, which include reinvested dividends, from the project’s nifty_tri_master.csv. Everything is calculated when the site is built; it is a research dataset refreshed with the repository, not a live market feed.

Whenever indices are compared, calculations use one shared set of observed dates. Factor Explorer starts with all factor families selected and a 02-03-2006 baseline. It includes only indices whose stored histories cover the entire selected period, and lists exclusions with their actual available dates. A later start can include shorter-history indices if their factor and parent filters also match. Compare retains every explicitly selected index; its default date controls follow their common available history. Custom dates are preserved, with the actual observed period and any shortening explained. Missing sessions are never forward-filled or interpolated. Dates are shown as DD-MM-YYYY.

Below, V is a TRI level, r a simple daily return, n the number of daily returns and T elapsed years.

CAGR

Compound annual growth rate over the observed dates, with elapsed time measured in mean Gregorian years of 365.2425 days.

Compound annual growth rate
CAGR=(VendVstart)1/T−1,T=days(tend−tstart)365.2425\mathrm{CAGR}=\left(\frac{V_{\mathrm{end}}}{V_{\mathrm{start}}}\right)^{1/T}-1,\qquad T=\frac{\text{days}(t_{\mathrm{end}}-t_{\mathrm{start}})}{365.2425}

Volatility

Sample standard deviation (denominator n − 1) of daily simple returns, annualized with the square root of 252 trading days.

Daily return & annualized volatility
rt=VtVt−1−1,σann=252 1n−1∑t(rt−rˉ)2r_t=\frac{V_t}{V_{t-1}}-1,\qquad \sigma_{\mathrm{ann}}=\sqrt{252}\,\sqrt{\tfrac{1}{n-1}\textstyle\sum_t (r_t-\bar r)^2}

Max drawdown

Decline from the highest level observed so far within the measured period; maximum drawdown is the most negative value. A new period resets the running peak.

Peak-to-trough decline
Dt=Vtmax⁡s≤tVs−1,Dmax⁡=min⁡tDtD_t=\frac{V_t}{\max_{s\le t}V_s}-1,\qquad D_{\max}=\min_t D_t

Sharpe and Sortino

Both ratios use daily returns in excess of a daily target equivalent to a 5% effective annual risk-free rate, annualized using 252 trading days. Sortino’s denominator is the root-mean-square shortfall below the target across all days (days meeting the target count as zero). Undefined ratios are shown as —.

Daily target and excess return
τ=(1.05)1/252−1,et=rt−τ\tau=(1.05)^{1/252}-1,\qquad e_t=r_t-\tau
Sharpe and Sortino
Sharpe=eˉ 252sd(e),Sortino=eˉ 2521n∑tmin⁡(et,0)2\mathrm{Sharpe}=\frac{\bar e\,\sqrt{252}}{\mathrm{sd}(e)},\qquad \mathrm{Sortino}=\frac{\bar e\,\sqrt{252}}{\sqrt{\tfrac1n\sum_t \min(e_t,0)^2}}

Calmar

Period CAGR divided by the absolute maximum drawdown of the same period. The risk-free rate is not deducted; with no drawdown the ratio is undefined (—).

Return relative to maximum loss
Calmar=CAGR∣Dmax⁡∣\mathrm{Calmar}=\frac{\mathrm{CAGR}}{|D_{\max}|}

Rolling CAGR and win rates

Rolling k-year CAGR is calculated on every observation, using calendar anniversaries: the start is the first observation on or after the same date k years earlier (29 February becomes 28 February), and the window must span at least k − 0.01 years. Earlier observations have no value.

Rolling annualized return
Rt,k=(VtVs)1/Ts,t−1,s=first obs. ≥t−k yearsR_{t,k}=\left(\frac{V_t}{V_{s}}\right)^{1/T_{s,t}}-1,\qquad s=\text{first obs.}\ \ge t-k\ \text{years}

Overall return and risk statistics use the displayed analysis period. Rolling-return observations begin only after the first complete rolling window; their first actual endpoint is shown separately. Short periods can still have overall statistics while rolling statistics remain unavailable. Median, P10 and P90 use linear interpolation. A pairwise win counts shared rolling windows where one index’s CAGR is strictly higher; ties are not wins, and per-index win rates against several peers can add up to more than 100%. Overlapping windows are correlated and are not independent trials.

Calendar years and YTD

A full calendar-year return runs from the previous December’s last close to the reported December’s last close. Both closes must fall within seven days of 31 December, be on the same session for every compared index, and the year must contain at least 180 shared sessions. Calendar-year charts and tables also include incomplete periods: (YTD) for the ongoing year and (partial) for incomplete historical years. If the previous December close is unavailable or the selected period starts midyear, returns run from the first shared available close in the period to the last shared close in that year. Partial periods do not receive full-year ranking highlights; their actual dates appear on the year label.

Dashboard cohorts

The dashboard screens every index at one shared end date: the freshest session that still includes at least 90% of the most-populated recent cohort, so one delayed index cannot backdate the rest. Each horizon then uses one common start date for every index with a complete calendar-anniversary history; an index without enough history shows —.

Risk and consistency statistics use the cohort of the chosen horizon. “Positive 3Y windows” counts every rolling three-year return that ends inside the chosen horizon, so it uses three extra years of shared history before the horizon starts. “Fall from all-time high” compares each index’s latest close with its highest close over its full history. A value marked BT starts before that index’s launch date (backtested).

Backtest Hero?

Latest 5 years uses the latest five calendar years after launch, where available. Since launch uses the launch date through the selected end date. Newer indices default to their available since-launch period. Custom dates retain the exact selected duration in calendar months and remaining days, without rounding to whole years. The selected period is compared in two separate ways:

  • Versus its parent (factor indices only), on exactly the dates both indices observed, with beta and correlation of daily returns and Jensen’s alpha: mean(strategy excess − β × parent excess) × 252 at the 5% daily target.
  • Versus its own history: every complete equal-duration window from the pre-launch backtest, ending strictly before launch and before the selected period. Each eligible observed trading-day endpoint is used. For indices shown without a launch boundary, reference windows end before the selected period. Start dates are moved back by the same calendar months and remaining days, with month-end clipping; calculations use actual observed closes within those boundaries. A metric’s percentile is the share of eligible windows at or below its selected value; fewer than five valid windows leaves the percentile unavailable. Overlapping windows are not independent trials.

Percentiles show where a selected value falls within its reference history. A higher percentile means a larger metric value; that has different implications for returns, volatility and drawdown. Reference medians and ranges provide descriptive context rather than a prediction.

The selected performance period and the historical reference pool are separate. Published index performance can be compared with earlier backtested periods, explicitly labeled as such. Periods under one year use cumulative total returns for both strategy and parent comparisons; annualized CAGR and risk-adjusted ratios are hidden. Longer periods use CAGR. Custom selections containing pre-launch data are labeled. An optional pre-launch exploration uses the last five available years before launch.

Backtest vs post-launch

An index’s base date usually precedes its public launch; history before launch is a retrospective reconstruction that can benefit from hindsight. Charts shade that pre-launch region. Launch dates come from the project catalog (one is confirmed by an NSE press release).

Post-launch index returns are still not fund returns: costs, taxes, tracking error and liquidity separate an index from an investor’s experience.

How the numbers are verified

Core financial calculations are checked against the Python research code on the real dataset, including every index, dashboard metrics and comparisons. Backtest Hero uses those same return and risk calculations with an exact-duration, pre-launch reference rule. Dedicated tests verify its date boundaries, reference coverage, short-period total returns and consistency with the index-page snapshots.

Limitations

  • Verify values against official NSE Indices sources before relying on them.
  • Index returns omit investment costs, taxes, tracking differences and investor cash flows.
  • Factor families are descriptive labels; exposures change over time and factors can lag their parent universe for long periods.
  • Changing dates can materially change rankings. Short samples, overlapping windows and many comparisons make apparent patterns unreliable.

For educational and research purposes only. Not investment advice.