---
updatedAt: 2026-08-19T10:42:55.000Z
agentTools:
  projectIndex: https://docs.inferedge.com/llms.txt
---

# Get Performance Analytics

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

# OpenAPI definition

```json
{
  "openapi": "3.1.0",
  "info": {
    "title": "India Mutual Funds Data Feed",
    "version": "1.0.0",
    "description": "Indian mutual fund data feed: share-class reference detail, daily NAV / TER /\nAUM history, fund performance and risk metrics, AMFI category cohorts, holdings\nattribution and Brinson-Fachler active-return attribution.\n\nEvery endpoint identifies funds by instrument `unique_id` (`INS-...`). Start at\n**List Funds** to turn a fund name or ISIN into the ids the other endpoints take.\n\n## Base URLs\n\nThe harmoney and inferedge hosts serve the same API — pick either.\n\n| | Production | Development |\n|---|---|---|\n| harmoney | `https://api.harmoney.in` | `https://api.harmoney.dev` |\n| inferedge | `https://api.inferedge.com` | `https://api.inferedge.tech` |",
    "contact": {
      "name": "Harmoney API Support",
      "email": "support@harmoney.in",
      "url": "https://harmoney.in"
    }
  },
  "servers": [
    {
      "url": "https://api.harmoney.in",
      "description": "Production"
    },
    {
      "url": "https://api.inferedge.com",
      "description": "Production — inferedge domain"
    },
    {
      "url": "https://api.harmoney.dev",
      "description": "Development"
    },
    {
      "url": "https://api.inferedge.tech",
      "description": "Development — inferedge domain"
    }
  ],
  "tags": [
    {
      "name": "Portfolio Analytics",
      "description": "Fund performance and risk metrics, AMFI category cohorts, holdings attribution and Brinson-Fachler active-return attribution."
    }
  ],
  "security": [
    {
      "X-API-Key": []
    }
  ],
  "paths": {
    "/api/portfolio/performance-analytics": {
      "post": {
        "tags": [
          "Portfolio Analytics"
        ],
        "summary": "Get Performance Analytics",
        "operationId": "performance_analytics",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PerformanceAnalyticsRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PerformanceAnalyticsResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "description": "Live NAV-based performance and risk metrics for 1-20 funds, with peer enrichment."
      }
    }
  },
  "components": {
    "securitySchemes": {
      "X-API-Key": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key",
        "description": "Generate from Org Settings"
      }
    },
    "schemas": {
      "HTTPValidationError": {
        "properties": {
          "detail": {
            "items": {
              "$ref": "#/components/schemas/ValidationError"
            },
            "type": "array",
            "title": "Detail"
          }
        },
        "type": "object",
        "title": "HTTPValidationError"
      },
      "InstrumentPerformance": {
        "properties": {
          "instrument_id": {
            "type": "string",
            "title": "Instrument Id"
          },
          "instrument_name": {
            "type": "string",
            "title": "Instrument Name"
          },
          "effective_start": {
            "type": "string",
            "format": "date",
            "title": "Effective Start"
          },
          "effective_end": {
            "type": "string",
            "format": "date",
            "title": "Effective End"
          },
          "category": {
            "type": "string",
            "title": "Category",
            "description": "AMFI category name. Present for MF/ETF instruments only."
          },
          "category_code": {
            "type": "string",
            "title": "Category Code",
            "description": "Stable AMFI category code (e.g. '44'). Present for MF/ETF only."
          },
          "series": {
            "additionalProperties": {
              "$ref": "#/components/schemas/MetricSeries"
            },
            "type": "object",
            "title": "Series",
            "description": "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."
          }
        },
        "type": "object",
        "required": [
          "instrument_id",
          "effective_start",
          "effective_end",
          "series"
        ],
        "title": "InstrumentPerformance",
        "description": "Performance result for a single instrument."
      },
      "MetricSeries": {
        "description": "One metric's full series of evaluation points.\n\n``null_reason`` at the series level is populated when the metric cannot\nbe computed for the entire series (e.g. CAGR over a sub-1Y frequency\nstep). In that case ``points`` is empty. Per-point ``null_reason`` is\nused only for step-specific null reasons.",
        "properties": {
          "unit": {
            "title": "Unit",
            "type": "string"
          },
          "label": {
            "title": "Label",
            "type": "string"
          },
          "points": {
            "items": {
              "$ref": "#/components/schemas/MetricPoint"
            },
            "title": "Points",
            "type": "array"
          },
          "null_reason": {
            "type": "string",
            "default": null,
            "title": "Null Reason"
          }
        },
        "required": [
          "unit",
          "label",
          "points"
        ],
        "title": "MetricSeries",
        "type": "object"
      },
      "PerformanceAnalyticsRequest": {
        "properties": {
          "instrument_ids": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "maxItems": 20,
            "minItems": 1,
            "title": "Instrument Ids",
            "description": "1–20 instrument unique_ids",
            "example": [
              "INS-HAQO5J6GGY"
            ]
          },
          "metrics": {
            "items": {
              "type": "string",
              "enum": [
                "cumulative_return",
                "annualised_return",
                "discrete_return",
                "rolling_return",
                "trailing_return",
                "volatility",
                "sharpe",
                "sortino",
                "max_drawdown",
                "beta",
                "treynor",
                "up_capture",
                "down_capture"
              ]
            },
            "type": "array",
            "minItems": 1,
            "title": "Metrics",
            "description": "One or more metric tokens",
            "default": [
              "cumulative_return",
              "volatility"
            ]
          },
          "benchmark_id": {
            "type": "string",
            "title": "Benchmark Id",
            "description": "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": {
            "type": "string",
            "enum": [
              "3M",
              "6M",
              "1Y"
            ],
            "title": "Rolling Window",
            "description": "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": {
            "type": "string",
            "enum": [
              "monthly",
              "quarterly",
              "annual"
            ],
            "title": "Discrete Returns Frequency",
            "description": "Bucket cadence for discrete_return (calendar-aligned). Required when 'discrete_return' is in metrics; ignored otherwise. Options: monthly | quarterly | annual."
          },
          "risk_frequency": {
            "type": "string",
            "enum": [
              "monthly",
              "daily"
            ],
            "title": "Risk Frequency",
            "description": "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.",
            "default": "monthly"
          },
          "include_category": {
            "type": "boolean",
            "title": "Include Category",
            "description": "If true, every point in every metric series carries a 'category_avg' field with the peer average for that metric at that step.",
            "default": false
          },
          "include_ranking": {
            "type": "boolean",
            "title": "Include Ranking",
            "description": "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.",
            "default": false
          },
          "as_of": {
            "type": "string",
            "format": "date",
            "title": "As Of",
            "description": "Mode A: last evaluation point / trailing anchor",
            "example": "2026-06-30"
          },
          "horizon": {
            "type": "string",
            "enum": [
              "1M",
              "3M",
              "6M",
              "YTD",
              "1Y",
              "3Y",
              "5Y",
              "10Y",
              "MAX"
            ],
            "title": "Horizon",
            "description": "Mode A: outer window size — ``as_of − horizon`` becomes the evaluation window start. Ignored by trailing_return. Full ``HorizonToken`` set including ``10Y``, ``YTD``, ``MAX``.",
            "example": "1Y"
          },
          "start_date": {
            "type": "string",
            "format": "date",
            "title": "Start Date",
            "description": "Mode B: first evaluation point",
            "example": "2025-06-30"
          },
          "end_date": {
            "type": "string",
            "format": "date",
            "title": "End Date",
            "description": "Mode B: last evaluation point / trailing anchor",
            "example": "2026-06-30"
          }
        },
        "type": "object",
        "required": [
          "instrument_ids",
          "metrics"
        ],
        "title": "PerformanceAnalyticsRequest",
        "description": "Request body for POST /api/portfolio/performance-analytics.\n\nTwo mutually exclusive date-range modes:\n- **Mode A** — ``as_of`` + ``horizon``: evaluation window ends at\n  ``as_of``, starts ``horizon`` before it.\n- **Mode B** — ``start_date`` + ``end_date``: explicit window.\n\nTrailing-only callers still send a full Mode A or Mode B payload;\ntrailing ignores ``horizon`` (Mode A) or ``start_date`` (Mode B) and\nalways emits its 9 fixed-horizon points anchored at ``as_of`` (Mode A)\nor ``end_date`` (Mode B).\n\n- ``rolling_window`` is required when ``rolling_return`` in metrics.\n- ``discrete_returns_frequency`` is required when ``discrete_return``\n  in metrics.\n\n``frequency`` (the old top-level cadence field) is gone: rolling is\nhardcoded daily, discrete uses ``discrete_returns_frequency``, trailing\nhas no cadence, and non-return metrics (volatility / sharpe / sortino /\nmax_drawdown) never used it."
      },
      "PerformanceAnalyticsResponse": {
        "properties": {
          "requested_start": {
            "type": "string",
            "format": "date",
            "title": "Requested Start"
          },
          "requested_end": {
            "type": "string",
            "format": "date",
            "title": "Requested End"
          },
          "effective_start": {
            "type": "string",
            "format": "date",
            "title": "Effective Start"
          },
          "effective_end": {
            "type": "string",
            "format": "date",
            "title": "Effective End"
          },
          "as_of": {
            "type": "string",
            "format": "date",
            "title": "As Of"
          },
          "horizon": {
            "type": "string",
            "enum": [
              "1M",
              "3M",
              "6M",
              "YTD",
              "1Y",
              "3Y",
              "5Y",
              "10Y",
              "MAX"
            ],
            "title": "Horizon"
          },
          "start_date": {
            "type": "string",
            "format": "date",
            "title": "Start Date"
          },
          "end_date": {
            "type": "string",
            "format": "date",
            "title": "End Date"
          },
          "discrete_returns_frequency": {
            "type": "string",
            "enum": [
              "monthly",
              "quarterly",
              "annual"
            ],
            "title": "Discrete Returns Frequency"
          },
          "rolling_window": {
            "type": "string",
            "enum": [
              "3M",
              "6M",
              "1Y"
            ],
            "title": "Rolling Window"
          },
          "metrics": {
            "items": {
              "type": "string",
              "enum": [
                "cumulative_return",
                "annualised_return",
                "discrete_return",
                "rolling_return",
                "trailing_return",
                "volatility",
                "sharpe",
                "sortino",
                "max_drawdown",
                "beta",
                "treynor",
                "up_capture",
                "down_capture"
              ]
            },
            "type": "array",
            "title": "Metrics"
          },
          "benchmark_name": {
            "type": "string",
            "title": "Benchmark Name"
          },
          "instruments": {
            "items": {
              "$ref": "#/components/schemas/InstrumentPerformance"
            },
            "type": "array",
            "title": "Instruments"
          }
        },
        "type": "object",
        "required": [
          "requested_start",
          "requested_end",
          "metrics",
          "instruments"
        ],
        "title": "PerformanceAnalyticsResponse",
        "description": "Response for POST /api/portfolio/performance-analytics.\n\n``effective_start`` / ``effective_end`` are the batch-level union\n(``min(effective_start)``, ``max(effective_end)``) across all funds\nthat returned data. Per-fund ``series[].points`` are padded at\nserialization time to the shared date axis so every fund's metric\nseries covers the same set of anchors; anchors outside a fund's own\ncomputed span emit ``null_reason='insufficient_data'`` points. Per-\nfund entries still carry their own ``effective_start`` /\n``effective_end`` — the actual window each metric was computed\nover. ``null`` when no fund resolved."
      },
      "ValidationError": {
        "properties": {
          "loc": {
            "items": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "integer"
                }
              ]
            },
            "type": "array",
            "title": "Location"
          },
          "msg": {
            "type": "string",
            "title": "Message"
          },
          "type": {
            "type": "string",
            "title": "Error Type"
          },
          "input": {
            "title": "Input"
          },
          "ctx": {
            "type": "object",
            "title": "Context"
          }
        },
        "type": "object",
        "required": [
          "loc",
          "msg",
          "type"
        ],
        "title": "ValidationError"
      },
      "MetricPoint": {
        "description": "A single {date, value} point in a metric series.\n\nOptional enrichments (only serialized when set):\n- ``null_reason`` — populated when ``value`` is ``None``.\n- ``horizon`` — populated only for trailing_return points; identifies\n  the fixed horizon (`\"1M\"`, `\"3M\"`, `\"YTD\"`, `\"10Y\"`, `\"MAX\"`, …).\n- ``category_avg`` — populated when the request has ``include_category=true``.\n- ``rank`` + ``out_of`` — populated when the request has ``include_ranking=true``.",
        "properties": {
          "date": {
            "format": "date",
            "title": "Date",
            "type": "string"
          },
          "value": {
            "type": "number",
            "default": null,
            "title": "Value"
          },
          "null_reason": {
            "type": "string",
            "default": null,
            "title": "Null Reason"
          },
          "horizon": {
            "enum": [
              "1M",
              "3M",
              "6M",
              "YTD",
              "1Y",
              "3Y",
              "5Y",
              "10Y",
              "MAX"
            ],
            "type": "string",
            "default": null,
            "title": "Horizon"
          },
          "category_avg": {
            "type": "number",
            "default": null,
            "title": "Category Avg"
          },
          "rank": {
            "type": "integer",
            "default": null,
            "title": "Rank"
          },
          "out_of": {
            "type": "integer",
            "default": null,
            "title": "Out Of"
          }
        },
        "required": [
          "date"
        ],
        "title": "MetricPoint",
        "type": "object"
      }
    }
  },
  "x-readme": {}
}
```