Shop It Docs
Stock Analysis (Fundamentals)

Snapshot

Top-of-page header card — sector, listing date, paid-up capital, LTP, market cap, book value, EPS, P/E, dividend yield

The snapshot endpoint backs the small block of bare numbers above the chart on every stock-detail page. It is the cheapest fundamentals call — three sqlc reads, no taxonomy iteration over multiple statements — and the most frequently hit.

MethodPathCache TTL
GET/api/nepse/companies/{symbol}/fundamentals/snapshot5 min

Request

curl "$BASE/api/nepse/companies/NABIL/fundamentals/snapshot"

No query parameters. symbol is case-folded to upper before lookup.

Response

{
  "message": "ok",
  "data": {
    "symbol": "NABIL",
    "name": "Nabil Bank Limited",
    "sector": "Commercial Banks",
    "listingDate": { "ad": "2017-01-04", "bs": "2073-09-21" },
    "outstandingShares": 100000000,
    "promoterPercent": 51,
    "publicPercent": 49,
    "paidUpCapital": 6000000000,
    "ltp": 542.5,
    "marketCap": 54250000000,
    "bookValuePerShare": { "value": 100, "source": "computed", "status": "valid" },
    "epsTtm":            { "value": 42.5, "source": "mdp",      "status": "valid" },
    "peRatio":           { "value": 12.76, "source": "computed", "status": "valid" },
    "dividendYield":     { "value": 2.76, "source": "computed", "status": "valid" },
    "dataAsOf": "2026-05-23T14:55:00+05:45",
    "servedAt": "2026-05-23T14:56:30+05:45"
  }
}

Field rules

FieldTypeNotes
symbol / namestringFrom nepse_companies
sectorstringOmitted when null on the company row
listingDate{ad, bs}Whole object omitted when both calendar values are blank
outstandingSharesint64Nullable — omitted when MDP hasn't filled the column
promoterPercent / publicPercentfloat0–100 scale; raw MDP-derived columns
paidUpCapitalfloatNPR; raw MDP column
ltpfloatLive price; null until first poller tick
marketCapfloatPrefers the precomputed live column; falls back to LTP × outstandingShares
bookValuePerShareMetricFloat64Computed from Total Equity / Outstanding Shares
epsTtmMetricFloat64Reported EPS from the latest IS quarter (TTM treatment lands when 4Q history exists)
peRatioMetricFloat64LTP / EPS; propagates EPS status when EPS is invalid
dividendYieldMetricFloat64Σ cash% × par / LTP, where par = 100 NPR
dataAsOfRFC3339 NPTOldest of: LTP fetch time, any report's updated_at
servedAtRFC3339 NPTResponse wall-clock

bookValuePerShare, epsTtm, peRatio, and dividendYield are always emitted as MetricFloat64 envelopes — never as bare numbers — so the FE can render a dash with a tooltip when any input is missing without per-field branching.

Computation

core      ← GetFundamentalsSnapshotCore(symbol)               // 1 row from fundamentals_snapshot view
reports   ← GetFundamentalsSnapshotReports(symbol)            // most-recent reported quarter per report_type
dividends ← GetFundamentalsSnapshotDividends(symbol)          // dividend events for yield aggregation

bookValuePerShare = compute.BookValuePerShare(taxonomy, bsItems, outstanding, sector)
epsTtm            = compute.EPSCurrent(taxonomy, isItems, sector)        // most recent quarter under v4.5
peRatio           = LTP / epsTtm                                          // status propagates from epsTtm
dividendYield     = compute.ComputeDividendYield(dividends, LTP)
marketCap         = ComputeMarketCap(core)                                // pre-computed or LTP×shares

bsItems / isItems are decoded from each report's items_map JSONB and indexed by the canonical-row vocabulary in financial_reports/taxonomy/.

Status propagation

The peRatio row is the simplest example of how MetricFloat64.status propagates through the compute chain:

LTPEPSpeRatio.status
null*upstream_missing
valueupstream_missingupstream_missing
valueinsufficient_historyinsufficient_history
valuenegative_input (loss-making)negative_input
valuevalid (positive EPS)valid

The FE renders the same way regardless of which upstream input failed.

Caching

KeyTTLBust trigger
nepse:fundamentals:snapshot:{SYMBOL}5 minTTL only — no write-side invalidation

Concurrent requests for the same symbol coalesce through cache.GetOrSetTyped (singleflight), so a stampede during a popular ticker spike triggers exactly one DB round-trip set.

Errors

CodeReason
200OK
404Symbol not in nepse_companies (Company not found)
500DB error during one of the three reads

There is no 400 — symbol is the only input and missing/empty values are unreachable through the chi router (the route pattern requires a non-empty path segment).