---
title: "Get Performance Analytics"
method: POST
path: "/api/portfolio/performance-analytics"
tags: ["Portfolio Analytics"]
---

# Get Performance Analytics

`POST /api/portfolio/performance-analytics`

## Request

- Base URL: `https://api.harmoney.in`
- URL: `https://api.harmoney.in/api/portfolio/performance-analytics`
- Auth: API key in header `x-api-key`

Live NAV-based performance and risk metrics for 1-20 funds, with peer enrichment.

## Request body

- PerformanceAnalyticsRequest: Request body for POST /api/portfolio/performance-analytics. Two mutually exclusive date-range modes: - **Mode A** — ``as_of`` + ``horizon``: evaluation window ends at ``as_of``, starts ``horizon`` before it. - **Mode B** — ``start_date`` + ``end_date``: explicit window. Trailing-only callers still send a full Mode A or Mode B payload; trailing ignores ``horizon`` (Mode A) or ``start_date`` (Mode B) and always emits its 9 fixed-horizon points anchored at ``as_of`` (Mode A) or ``end_date`` (Mode B). - ``rolling_window`` is required when ``rolling_return`` in metrics. - ``discrete_returns_frequency`` is required when ``discrete_return`` in metrics. ``frequency`` (the old top-level cadence field) is gone: rolling is hardcoded daily, discrete uses ``discrete_returns_frequency``, trailing has no cadence, and non-return metrics (volatility / sharpe / sortino / max_drawdown) never used it.
  - `instrument_ids` string[], required: 1–20 instrument unique_ids
  - `metrics` string[], required: One or more metric tokens
  - `benchmark_id` string: unique_id of the instrument beta / treynor / up_capture / down_capture are measured against — normally the fund the caller selected as its benchmark. There is no default: without it those four metrics are null rather than silently measured against an index the caller never chose. The response's benchmark_name name the leg actually used.
  - `rolling_window` '3M' | '6M' | '1Y': Trailing lookback for rolling_return at each daily anchor. Required when 'rolling_return' is in metrics; ignored otherwise. Options: 3M | 6M | 1Y.
  - `discrete_returns_frequency` 'monthly' | 'quarterly' | 'annual': Bucket cadence for discrete_return (calendar-aligned). Required when 'discrete_return' is in metrics; ignored otherwise. Options: monthly | quarterly | annual.
  - `risk_frequency` 'monthly' | 'daily': Return cadence for volatility / sharpe / sortino. 'monthly' (default) resamples NAV to month-end and annualises by sqrt(12), matching how AMFI factsheets publish these figures. 'daily' keeps the raw NAV series and annualises by sqrt(252). Ignored by every other metric.
  - `include_category` boolean: If true, every point in every metric series carries a 'category_avg' field with the peer average for that metric at that step.
  - `include_ranking` boolean: If true, every point in every rankable metric series carries 'rank' and 'out_of' fields with the fund's DENSE_RANK against category peers on that metric at that step.
  - `as_of` string, date: Mode A: last evaluation point / trailing anchor
  - `horizon` '1M' | '3M' | '6M' | 'YTD' | '1Y' | '3Y' | '5Y' | '10Y' | 'MAX': Mode A: outer window size — ``as_of − horizon`` becomes the evaluation window start. Ignored by trailing_return. Full ``HorizonToken`` set including ``10Y``, ``YTD``, ``MAX``.
  - `start_date` string, date: Mode B: first evaluation point
  - `end_date` string, date: Mode B: last evaluation point / trailing anchor

## Response `200`

Successful Response

- PerformanceAnalyticsResponse: Response for POST /api/portfolio/performance-analytics. ``effective_start`` / ``effective_end`` are the batch-level union (``min(effective_start)``, ``max(effective_end)``) across all funds that returned data. Per-fund ``series[].points`` are padded at serialization time to the shared date axis so every fund's metric series covers the same set of anchors; anchors outside a fund's own computed span emit ``null_reason='insufficient_data'`` points. Per- fund entries still carry their own ``effective_start`` / ``effective_end`` — the actual window each metric was computed over. ``null`` when no fund resolved.
  - `requested_start` string, date, required
  - `requested_end` string, date, required
  - `effective_start` string, date
  - `effective_end` string, date
  - `as_of` string, date
  - `horizon` '1M' | '3M' | '6M' | 'YTD' | '1Y' | '3Y' | '5Y' | '10Y' | 'MAX'
  - `start_date` string, date
  - `end_date` string, date
  - `discrete_returns_frequency` 'monthly' | 'quarterly' | 'annual'
  - `rolling_window` '3M' | '6M' | '1Y'
  - `metrics` string[], required
  - `benchmark_name` string
  - `instruments` InstrumentPerformance[], required
    - `instrument_id` string, required
    - `instrument_name` string
    - `effective_start` string, date, required
    - `effective_end` string, date, required
    - `category` string: AMFI category name. Present for MF/ETF instruments only.
    - `category_code` string: Stable AMFI category code (e.g. '44'). Present for MF/ETF only.
    - `series` object, required: Keyed by metric token. Every requested metric is always present. Each MetricPoint may carry inline category_avg / rank / out_of when the corresponding include_* flags are set on the request.

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/inferedge/apis/india-mutual-funds-data-feed.md) - [All operations](https://skmtc.dev/inferedge/apis/india-mutual-funds-data-feed/llms.txt) - [OpenAPI document](https://skmtc.dev/inferedge/apis/india-mutual-funds-data-feed/revisions/fe0d3be721c0?raw)
