Imagine a dashboard reporting that a company's revenue grew 75% in one year. The numbers came from financial statements. The arithmetic checks out. Nothing crashed.
There's just one problem: the dashboard compared standalone revenue from one year with consolidated revenue from the next. The resulting growth rate describes neither business consistently.
At MarketDeck, we're building a connected financial research workspace for Indian markets, including filing-backed company research, screening, interactive charts, and quantitative analysis. One design principle behind our company research is simple: a financial figure is not meaningful without its reporting context.
This article walks through a small, runnable Python example of that principle. It's a standalone teaching example using fictional numbers, not a copy of MarketDeck's production code or a claim about any real listed company.
The invisible data bug
Suppose a fictional company reports the following revenue figures (all in ₹ crore):
| Reporting year | Accounting basis | Revenue (₹ crore) |
|---|---|---|
| FY2024 | Standalone | 800 |
| FY2024 | Consolidated | 1,100 |
| FY2025 | Consolidated | 1,400 |
Two tempting calculations produce completely different stories:
- ❌ Wrong comparison: 1,400 ÷ 800 − 1 = 75% growth
- ✅ Like-for-like comparison: 1,400 ÷ 1,100 − 1 = 27.27% growth
The first calculation mixes reporting bases; the second compares consolidated annual revenue with consolidated annual revenue. Even the second figure would need further review if the company's consolidation perimeter or accounting policies changed significantly.
This isn't an exotic edge case. Indian listed companies can file results in both standalone and consolidated formats. NSE also supports structured XBRL financial reporting, where units, periods and taxonomy elements matter. A dashboard that discards those fields loses information it needs to compare figures responsibly.
Treat every number as a record, not a float
The usual toy data model is something like:
revenue = 1400
That's fine for a one-line calculation. For a research application, it is under-specified.
We should be able to answer:
- Which issuer and metric does this number belong to?
- Which fiscal period does it represent: quarter, full year or trailing twelve months?
- Is it standalone or consolidated?
- Which currency and unit are being used?
- When did the result become publicly available?
- Which filing or record supports it?
Here's one deliberately minimal Python model that keeps those answers attached. It uses only the standard library and runs on Python 3.10+.
"""Standalone, synthetic demonstration for the MarketDeck DEV article.
Not production MarketDeck source code.
Python 3.10+; no external dependencies.
"""
from dataclasses import dataclass
from datetime import date, datetime
from decimal import Decimal
@dataclass(frozen=True)
class Fact:
issuer: str
metric: str
period_end: date
period_type: str
basis: str
units: str
amount: Decimal
published_at: datetime
source_id: str
def find_fact(
facts, *, issuer, metric,
period_end, basis, as_of
):
if as_of.tzinfo is None or as_of.utcoffset() is None:
raise ValueError("as_of must have a timezone")
eligible = [
f for f in facts
if f.issuer == issuer
and f.metric == metric
and f.period_end == period_end
and f.period_type == "FY"
and f.basis == basis
and f.units == "INR crore"
and f.published_at <= as_of
]
if not eligible:
raise LookupError(
"No comparable fact known by this date"
)
# Real datasets need explicit revision handling.
return max(eligible, key=lambda f: f.published_at)
facts = [
Fact(
"FictionalCo", "revenue",
date(2024, 3, 31),
"FY", "standalone",
"INR crore", Decimal("800"),
datetime.fromisoformat(
"2024-05-10T18:00:00+05:30"
),
"DEMO-2024-ST"
),
Fact(
"FictionalCo", "revenue",
date(2024, 3, 31),
"FY", "consolidated",
"INR crore", Decimal("1100"),
datetime.fromisoformat(
"2024-05-15T18:00:00+05:30"
),
"DEMO-2024-CON"
),
Fact(
"FictionalCo", "revenue",
date(2025, 3, 31),
"FY", "consolidated",
"INR crore", Decimal("1400"),
datetime.fromisoformat(
"2025-05-20T18:00:00+05:30"
),
"DEMO-2025-CON"
)
]
as_of = datetime.fromisoformat(
"2025-06-01T12:00:00+05:30"
)
prior = find_fact(
facts,
issuer="FictionalCo",
metric="revenue",
period_end=date(2024, 3, 31),
basis="consolidated",
as_of=as_of
)
current = find_fact(
facts,
issuer="FictionalCo",
metric="revenue",
period_end=date(2025, 3, 31),
basis="consolidated",
as_of=as_of
)
growth = (
current.amount / prior.amount - Decimal("1")
) * Decimal("100")
print(f"Comparable revenue growth: {growth:.2f}%")
print(
f"Sources: {prior.source_id} -> {current.source_id}"
)
# Check that unpublished information is excluded.
try:
find_fact(
facts,
issuer="FictionalCo",
metric="revenue",
period_end=date(2025, 3, 31),
basis="consolidated",
as_of=datetime.fromisoformat(
"2025-04-01T12:00:00+05:30"
)
)
except LookupError:
print(
"Early query: correctly rejected "
"an unpublished figure"
)
else:
raise AssertionError("Look-ahead check failed")
naive_growth = (
Decimal("1400") / Decimal("800") - 1
) * 100
assert naive_growth == Decimal("75")
assert growth.quantize(Decimal(".01")) == Decimal("27.27")
Expected output:
Comparable revenue growth: 27.27%
Sources: DEMO-2024-CON -> DEMO-2025-CON
Early query: correctly rejected an unpublished figure
All DEMO-* identifiers and numbers above are invented for this tutorial. They are not exchange filing identifiers or actual stock-market data.
What the code protects against
1. Mixed accounting bases
The selector requires the same basis for both years.
A standalone figure cannot quietly enter a consolidated comparison.
2. Mixed reporting periods
The code asks explicitly for an FY observation and matches a specified fiscal year-end.
In a production system, quarters, year-to-date amounts and trailing-twelve-month values need equally explicit period types and duration checks.
The same date alone is not sufficient to establish that two figures have the same reporting duration.
3. Mixed units
The example requires a declared unit.
A production implementation should also normalise values carefully because ₹ lakh, ₹ crore, INR and USD are not interchangeable.
The unit filter here is deliberately strict rather than performing conversions silently.
4. Look-ahead leakage
The condition:
f.published_at <= as_of
keeps figures unavailable at the simulated query time out of the result.
Fiscal year-end is not the same thing as publication date.
For event-driven simulations, the exact publication time and the next executable market session can both matter.
5. Untraceable output
The calculation returns source identifiers beside the result.
In a real application, those identifiers should resolve to specific original filings and, where possible, the relevant financial statements and accounting elements.
There's an important limitation here:
A source link is necessary, but not enough.
A restatement, changed consolidation perimeter, incorrect taxonomy mapping or missing filing could still make a number economically non-comparable.
If your system ingests amendments, it needs explicit revision and supersession handling.
Simply choosing the latest available record works only if your dataset models and validates that policy.
How that changes the UI
A trustworthy financial dashboard shouldn't make readers reverse-engineer a headline metric.
Alongside a growth percentage, I'd want to display something like this:
| Field | Research UI should explain |
|---|---|
| Value | 27.27% (illustrative) |
| Comparison | FY2025 vs FY2024 |
| Basis | Consolidated → Consolidated |
| Inputs | ₹1,400 crore and ₹1,100 crore |
| Availability | Dates both records were first public |
| Evidence | Original filings and financial-statement elements |
| Exceptions | Missing data, revisions or comparability warnings |
This isn't about making interfaces unnecessarily complicated.
It's about giving users a clean headline and a way to inspect the evidence when the detail matters.
At MarketDeck, our existing Research Terminal connects financial history with reporting context, valuation, peer research and source tracing.
Our company research also includes Source Trace ratio cards designed to show formulas, periods and missing-input explanations.
The example in this post is intentionally simplified. It illustrates the design reasoning rather than documenting our internal implementation line-for-line.
Three test cases I'd add before shipping
The script already tests one incorrect accounting comparison and one too-early query.
A production financial data pipeline needs more checks.
1. Restatement test
A later amended filing must not overwrite the earlier as-of history retroactively.
2. Context test
Annual, quarterly, year-to-date and trailing values must not become substitutes simply because their end dates align.
3. Provenance test
Missing source records, mismatched currencies or incompatible reporting bases must produce a visible missing or uncertain result—not a fabricated zero or silent fallback.
Also worth testing:
- Fiscal-year changes
- Mergers and acquisitions
- Revised taxonomy mappings
- Stale observation windows
- Timezone handling around market close
The aim is not to promise that every financial number can be made perfectly comparable.
It is to make the conditions under which it is comparable inspectable.
The bigger lesson for developers
It's easy to spend most of our time polishing the front end of a financial dashboard: chart animations, filters and fast search.
Those things matter.
But a chart can be beautifully rendered and still answer the wrong question.
Once a system tracks what was reported, for which period, on which basis, when it became known and where it came from, the product becomes more useful for far more than charts.
The same structured evidence can support:
- Human financial research
- Company screening
- Reproducible quantitative experiments
- Historical comparisons
- AI-assisted interfaces grounded in verifiable financial information
That's the direction we're building toward at MarketDeck: accessible quantitative research, with the context needed to question the output.
Our broader AI-connected experimentation and data-access vision remains future work, not something this tutorial claims is already live.
Explore MarketDeck — Financial Research Beyond the Numbers
If you're interested in financial markets, quantitative analysis or building data-driven applications, take a look at MarketDeck.
We're building an India-first quantitative financial research platform that brings together company fundamentals, stock screening, advanced charting, derivatives research, portfolio analytics and interactive mathematical tools.
Instead of switching between disconnected websites, spreadsheets and analytical tools, our goal is to make financial research more connected, transparent and accessible.
What you can explore today
Explore Indian listed companies, financial metrics, research filters and company fundamentals.
Investigate financial history, reporting periods, valuation context, peer comparisons and source-linked research.
Explore charting, derivatives research, portfolio analytics and interactive learning experiences from one connected platform.
Learn more about our approach to methodology, source transparency, research limitations and financial data quality.
Where we're going next
Our long-term vision is to build an integrated quantitative research workspace with AI-assisted research, programmable computation and permissioned financial data services.
These broader capabilities are part of our development direction and are not all available as a finished end-to-end workflow today.
MarketDeck is currently free to use.
👉 Explore MarketDeck — https://marketdeck.in/
One question for fellow developers
If you build data-heavy products, what's the most subtle "valid data, wrong interpretation" bug you've encountered?
I'd love to hear how other developers deal with source tracking, data revisions and inconsistent reporting formats.
References and further reading
- NSE: XBRL filing information — Financial-report taxonomy, period and unit context.
- NSE: Corporate filings announcements — Filing and dissemination timestamps.
- NSE: Integrated Financial Filing circular (April 2025) — Evolving PDF and XBRL filing processes.
- MarketDeck Research Terminal — Company research with sources and reporting context.
Educational and software-engineering content only. No investment recommendations. All demonstration amounts are fictional.
Top comments (0)