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)
Schema
Three tables work together: a fund reference table, and two returns tables keyed bycode (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.
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.
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.
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: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.
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, areturn_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.What's the difference between trailing returns and calendar year returns?
What's the difference between trailing returns and calendar year returns?
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.
Why are some returns annualized and others aren't?
Why are some returns annualized and others aren't?
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.
How often is the data refreshed?
How often is the data refreshed?
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.
How far back does the historical data go?
How far back does the historical data go?
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.What does it cost to build this ourselves vs. buy the listing?
What does it cost to build this ourselves vs. buy the listing?
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.
Can I request additional funds or ETFs to be made available in Snowflake?
Can I request additional funds or ETFs to be made available in Snowflake?
Yes! Please reach out to contact@fruitstand.dev with the requirements. We are more than happy to make it available.