Skip to main content

Overview

This product delivers trailing and calendar year total returns for approximately 32,000 US-listed mutual funds and ETFs, computed from adjusted end-of-day pricing data. Data is standardized into analytic‑ready tables (fund reference, trailing returns, calendar year returns) with automated pipeline quality checks (price validation, date ordering, return sanity bounds, cross-table consistency checks) so you can query, join, model, and build dashboards immediately without building or maintaining your own fund pricing and returns infrastructure.

Get it on the Snowflake Marketplace

$250/month flat rate — no pipelines to build.

Prefer a REST API?

The same data over HTTP — no Snowflake required. See the Fund Returns API →
  • ~32,000 US mutual funds and ETFs, continuously ingested
  • Trailing returns from 1-day to 20-year, plus since-inception
  • Calendar year returns, broken out year by year
  • Refreshed regularly with incremental updates and periodic full rebuilds
  • Survivorship-bias-free — delisted funds keep their full historical returns rather than being dropped
  • Automated pipeline quality checks (price validation, date ordering, return sanity bounds)
Curious how this stacks up against other fund and ETF data on Snowflake Marketplace? See Fund and ETF Returns Data on Snowflake, Compared on the blog.

Schema

Three tables work together: a fund reference table, and two returns tables keyed by code (the fund/ETF ticker).

Fund Reference

One row per fund or ETF: When a fund is delisted or otherwise stops trading, it’s marked is_inactive rather than removed, and its full trailing and calendar year return history remains available in the returns tables below. Nothing is silently dropped from the dataset when a fund goes inactive, so historical analysis stays free of survivorship bias.
Example output (illustrative):

Trailing Returns

One row per fund per as-of date, with one column per trailing period: Periods of 2 years or longer are annualized (CAGR); everything shorter, including YTD, is cumulative rather than annualized.
Example output (illustrative):

Calendar Year Returns

One row per fund per calendar year: Calendar year returns are always cumulative, never annualized. The current year’s row is a partial, YTD-equivalent return, and a fund’s inception year is a partial return from its first trading day to year-end.
Example output (illustrative):

Return Calculations

Adjusted closing price: every return in this dataset is calculated from adjusted closing prices, not raw closing prices. The adjusted close accounts for stock splits and dividend/distribution reinvestment, so it reflects total return rather than just price change. Whenever a fund posts a new split or dividend, its adjusted close is backward-adjusted across its entire price history, which is one reason we run a periodic full history rebuild rather than relying on incremental updates alone. Cumulative return: the plain percentage change between two adjusted closing prices:
This is used for every calendar year return, and for trailing periods shorter than 2 years (1-day through 1-year, including YTD). Annualized return (CAGR): for longer trailing periods, returns are annualized to a compound annual growth rate so windows of different lengths can be compared on the same basis:
This applies to trailing periods of 2 years or longer and to the since-inception return, following SEC/Morningstar convention: a span under 365 days is never annualized, since extrapolating a partial period into an annual rate can be misleading. If a period that would normally be annualized spans less than a year (e.g. a fund that IPO’d recently), it falls back to the cumulative formula instead.

Data Ingestion

Data is ingested into Snowflake with best practices in mind, across three chained stages.
1

Fund universe

The list of US funds and ETFs is pulled from the pricing API’s exchange symbol list and loaded into Snowflake, then standardized through staging and internal tables into the fund reference table.
2

Price history

For every active fund, end-of-day pricing (open, high, low, close, and adjusted close) is fetched from the pricing API, written to parquet, and staged in a dated S3 folder before being copied into Snowflake and standardized into an internal price history table. Corporate-action feeds (dividends and splits) are checked on every run, and any fund with a new dividend or split triggers a full price history reload for that fund, since the provider backward-adjusts its entire adjusted-close history whenever one posts.
3

Returns computation

Once fresh price history lands, trailing and calendar year returns are recomputed, following the calculations described above, and merged into the curated final tables and secure views.
Each stage is chained: the fund universe refresh triggers the price history pull, which in turn triggers the returns computation, so returns are always computed from that run’s freshest pricing. Refresh cadence: an incremental bulk price update runs five days a week (Sunday, Monday, Tuesday, Thursday, Friday), pulling only recent price changes, plus a full price history reload for any fund with a new dividend or split that day. Twice a week (Wednesday and Saturday), every mutual fund and ETF in the universe is fully reloaded and the return tables are fully rebuilt. For a deeper look at how this pipeline is built (S3 staging, the Snowflake COPY INTO, and the dbt models behind the final views), see How Fund Returns Data Moves from source to Snowflake on the blog.

Data Quality

  • Positive price validation: every closing and adjusted closing price must be strictly positive; this is checked at the earliest point in the pipeline, before it can propagate into any return figure.
  • Return floor check: no return can mathematically fall below -100% (a ratio of two positive prices can’t produce anything lower) — a violation signals bad upstream price data and is caught automatically.
  • Short-term sanity band: 1-day and 1-week returns beyond ±50% are flagged for investigation. A swing that large over that short a window is almost always a data issue, most commonly a missed split or distribution adjustment, though rare legitimate cases exist (leveraged/inverse funds, genuine crash days).

Disclosures

Fruit Stand Data LLC is not endorsed by or affiliated with any of the underlying pricing data providers. Use contact@fruitstand.dev for questions. Price availability and return staleness: on a date where a fund has zero trading volume, no closing price is produced for that date. Trailing returns still compute a value for every period by falling back to the nearest earlier date that has an actual price — for thinly-traded funds with real gaps in their price history, that base price can be older than the period’s nominal window implies (for example, a return_1w value may reflect the change over more than 7 calendar days if the fund didn’t trade for part of that stretch), even though the column keeps its standard period label.

F.A.Q.

Frequently asked questions from our clients.
Trailing returns measure performance over a fixed lookback window ending on a given as-of date (e.g. the 1-year or 5-year return as of today). Calendar year returns instead measure performance within each calendar year (e.g. how a fund performed in 2024, in 2025, and so on), which is useful for comparing year-over-year performance rather than a rolling window.
Trailing periods of 2 years or longer are annualized (compound annual growth rate), which is the standard convention for comparing multi-year performance on an apples-to-apples basis. Periods shorter than that, including year-to-date, are reported as cumulative returns rather than annualized, since annualizing a sub-year return can be misleading.
Prices are updated with an incremental bulk pull five days a week, plus a full history rebuild twice a week. Trailing and calendar year returns are recomputed automatically each time new pricing lands.
History starts at each fund’s own inception, whenever its first trading day was, rather than a fixed cutoff date shared across the universe — that’s what the return_earliest_available trailing-return column and each fund’s earliest calendar_year row represent. Delisted funds keep their full history too, so older or discontinued funds aren’t cut off early.
Building it yourself means standing up a pipeline to pull end-of-day pricing for a broad fund and ETF universe, computing annualized and cumulative returns correctly across many lookback periods, backfilling history, and maintaining it as funds get added, delisted, or revised. Our Snowflake listing is $250/month with all of that already built, computed, and kept current, no pipeline to build or maintain.
Yes! Please reach out to contact@fruitstand.dev with the requirements. We are more than happy to make it available.