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.
| Method | Path | Cache TTL |
|---|---|---|
GET | /api/nepse/companies/{symbol}/fundamentals/snapshot | 5 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
| Field | Type | Notes |
|---|---|---|
symbol / name | string | From nepse_companies |
sector | string | Omitted when null on the company row |
listingDate | {ad, bs} | Whole object omitted when both calendar values are blank |
outstandingShares | int64 | Nullable — omitted when MDP hasn't filled the column |
promoterPercent / publicPercent | float | 0–100 scale; raw MDP-derived columns |
paidUpCapital | float | NPR; raw MDP column |
ltp | float | Live price; null until first poller tick |
marketCap | float | Prefers the precomputed live column; falls back to LTP × outstandingShares |
bookValuePerShare | MetricFloat64 | Computed from Total Equity / Outstanding Shares |
epsTtm | MetricFloat64 | Reported EPS from the latest IS quarter (TTM treatment lands when 4Q history exists) |
peRatio | MetricFloat64 | LTP / EPS; propagates EPS status when EPS is invalid |
dividendYield | MetricFloat64 | Σ cash% × par / LTP, where par = 100 NPR |
dataAsOf | RFC3339 NPT | Oldest of: LTP fetch time, any report's updated_at |
servedAt | RFC3339 NPT | Response 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×sharesbsItems / 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:
| LTP | EPS | peRatio.status |
|---|---|---|
| null | * | upstream_missing |
| value | upstream_missing | upstream_missing |
| value | insufficient_history | insufficient_history |
| value | negative_input (loss-making) | negative_input |
| value | valid (positive EPS) | valid |
The FE renders the same way regardless of which upstream input failed.
Caching
| Key | TTL | Bust trigger |
|---|---|---|
nepse:fundamentals:snapshot:{SYMBOL} | 5 min | TTL 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
| Code | Reason |
|---|---|
200 | OK |
404 | Symbol not in nepse_companies (Company not found) |
500 | DB 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).