§ DESK · METHODOLOGY

How this desk gets its numbers.

Institutional data is easy to present and hard to get right. This page lists every input the Smart Money desk reads, how often it moves, which file does the arithmetic, and what the result cannot tell you. Each claim below carries its source: a path in the codebase, a table, a measurement with the date it was taken, or a known defect we have not fixed yet.

Newest filing quarter · Q1 2026 (2026-03-31), 129 days oldCompared against · Q4 2025 (2025-12-31)Tracked funds · 2 filersNewest mood reading · 2026-08-05, 2 days old
§ 01 · WHAT WE READ

The inputs, and what each one is good for

7 SOURCES

Quarterly holdings

institutional_positions

A manager with at least 100 million dollars of US listed securities has to file a Form 13F listing what it held on the last day of the quarter. We ingest the SEC bulk files into a filer table and a position table. The ingest itself runs outside this application, so a quarter shows up on the site only after that run has happened, not on the filing deadline.

  • table institutional_positions
  • table institutional_filers
  • SEC Form 13F, quarterly, managers above 100 million dollars
  • docs/how-it-works/feature-registry.md

CUSIP to ticker

cusip_ticker_map

A 13F names securities by CUSIP, not by ticker, so every position has to be resolved before it can be aggregated. Three layers do it: a small manual override map for share class oddities, then OpenFIGI (foreign identifiers are CINS numbers and need a different lookup type), then name matching against the SEC company list. 27,643 of 33,780 CUSIPs resolve, which is 81.8 percent of the identifiers and 99.58 percent of the position rows, because what stays unresolved is the small and obscure tail.

  • table cusip_ticker_map
  • docs/how-it-works/institutional-xray/overview.md
  • measured 2026-04-04, 27,643 of 33,780 CUSIPs resolved, 99.58 percent of position rows

Insider trades

insider_transactions

SEC Form 4 filings, pulled every weekday morning. Only code P (open market purchase) and code S (open market sale) carry a direction. Grants, exercises and gifts are left out on purpose: they say something about compensation, not about conviction.

  • table insider_transactions
  • acidcapitalist/lib/institutional/divergence.ts

Prices

stock_quotes

Quotes refresh on a cron through the trading day. The change column on that table is a one day move, so it is never used as a quarterly change anywhere on this desk. The quarterly price move comes from the 13F marks themselves: market value divided by share count is the quarter end price each filer reported, and the spread of that number across filers on the same ticker is zero, so it is a real price rather than an estimate.

  • table stock_quotes
  • acidcapitalist/lib/institutional/quarter-diff.ts
  • measured 2026-08-06, mark dispersion across filers on one ticker: 0.0000 of the median

Sectors

stock_fundamentals

Sector labels join by ticker. A ticker with no sector is not quietly folded into a neighbouring one: it is counted under Unclassified and reported separately, so a sector chart cannot borrow weight it did not earn.

  • table stock_fundamentals
  • acidcapitalist/lib/institutional/sector-flow.ts

The comparison universe

stock_ownership

An ownership snapshot ranks tickers by total institutional value. The top 100 of that ranking is what the rotation block compares across two quarters. Foreign board codes that appear in the same column are filtered out, because they carry no US institutional flow story.

  • table stock_ownership
  • acidcapitalist/lib/institutional/hub-flows.ts

Market mood

regime_history

The mood reading on the hub is the stored regime score, written every weekday evening by the pressure job and read straight back out. It is not recomputed while the page renders, because that path needs a service role key and a public page must never depend on one. When the table has nothing usable, the block is left out rather than shown as neutral: no reading and a calm reading are different statements.

  • table regime_history
  • acidcapitalist/lib/institutional/mood.ts
§ 02 · WHEN IT MOVES

Every schedule, quoted from the deployment config

CRON · UTC
JobRouteScheduleFeeds
13F ingestmanual step, nothing schedules iton demand
institutional_filers, institutional_positions
Run by hand from outside this application, once a filing quarter is available. Nothing on the site schedules it, which is why the quarter shown above can lag the filing deadline.
Institutional pressure/api/cron/institutional-pressure
0 23 * * 1-5
regime_history
Writes the regime reading the mood block shows.
Insider transactions/api/cron/insider-transactions
30 7,8,9 * * 1-5
insider_transactions
Three passes on weekday mornings, because Form 4 filings land in waves.
Quotes/api/cron/stock-quotes
*/5 13-20 * * 1-5
0 0-12,21-23 * * 1-5
stock_quotes
Every five minutes while US cash equities trade, hourly the rest of the weekday.
Fundamentals and sectors/api/cron/stock-fundamentals
0 12 * * 6
stock_fundamentals
Weekly. Sector labels move rarely, so the flow chart inherits a weekly clock for its labels and a quarterly clock for its numbers.

Cron expressions are UTC. A test compares every line of this table against the deployment config on each build, so a schedule that changes there and not here fails the build instead of quietly misinforming you.

  • acidcapitalist/vercel.json
  • docs/how-it-works/infrastructure.md
§ 03 · WHAT COMPUTES WHAT

One question per module

5 MODULES
What actually changed between two filings?
acidcapitalist/lib/institutional/quarter-diff.ts

Aggregates each quarter by filer and security first, then subtracts. Reads none of the stored change columns; they are not even in its input type. The four rules below are what it has to survive.

computeQuarterDiffNORMAL_SHARE_RATIO_BANDSPLIT_FACTORS
  • known defect #19, stored quarter over quarter columns
Which way did money move between sectors?
acidcapitalist/lib/institutional/sector-flow.ts

Flow is the share change priced at the quarter end mark, not the change in market value. Those are different numbers: market value also moves with the price, so a fund that touched nothing in a rising quarter would read as a buyer. Share change times one price is the part somebody actually decided.

computeSectorFlowscomputeTickerFlowsPOSITION_VALUE_UNIT_USD
  • table institutional_positions
Where do institutions, price and insiders disagree?
acidcapitalist/lib/institutional/divergence.ts

An alert needs a net institutional flow of at least 50 million dollars and a price move of at least 10 percent in the opposite direction. The price change always travels with the window it was measured over, so a one day move can never be quietly presented as a quarter.

detectDivergencestoDivergenceAlertsPropsDIVERGENCE_DEFAULTS
  • known defect #18, insider dollar values are empty
What regime is the tape in, and how old is that reading?
acidcapitalist/lib/institutional/mood.ts

Takes stored regime rows and the date to measure staleness against, and returns the score, the short series behind it, and the age in days. The clock is an input, not a call inside the function, which is what makes the freshness claim testable.

toMoodBlock
  • table regime_history
What does the hub run when you load it?
acidcapitalist/lib/institutional/hub-flows.ts

Fetches two quarters for the bounded universe, runs the diff, the sector flow and the divergence detector, and returns the counts of everything that was excluded on the way. Returns nothing at all when there is no honest answer, and the hub then omits the section. Cached for 3600 seconds.

fetchHubFlowsgetHubFlowsselectUniverseUNIVERSE_SIZESECTORS_SHOWNHUB_FLOWS_REVALIDATE_SECONDS
  • table stock_ownership
§ 04 · THE QUARTER OVER QUARTER DIFF

Four rules, each one paid for by a wrong number

4 RULES

Comparing two filings sounds like subtraction. It is not. Each rule below exists because the naive version produced a figure that was plausible on the page and wrong in reality, and the measurement that caught it is cited with it.

RULE 01

Add up the buckets before subtracting

The same security appears more than once inside a single filing, once per investment discretion bucket. On the tracked universe, 52.5 percent of filer and security pairs have more than one row. The stored change columns pair each current row with one arbitrary row from the previous quarter, which is wrong wherever that happens: one tracked fund and one mega cap came out as a change of 2,039.8 million shares against a true 43.1 million, a factor of 47. The read side sums inside each quarter first, then subtracts. Pairing rows by their bucket label does not work either, because that label is not stable across quarters.

  • acidcapitalist/lib/institutional/quarter-diff.ts
  • known defect #19, stored diff is wrong on multi row pairs
  • measured 2026-08-06, 52.5 percent of pairs carry more than one row, worst case off by 47x
RULE 02

A fund that did not file last quarter is not a buyer

Of the tracked filers, 50 had rows in the newer quarter and only 33 in the older one. Counting the other 17 would have read each of their entire books as a fresh purchase, which is the single easiest way to invent a buying wave that never happened. A filer missing either quarter is dropped whole, and the hub prints how many funds were left in the comparison.

  • acidcapitalist/lib/institutional/quarter-diff.ts
  • measured 2026-08-06, 50 tracked filers in the newer quarter, 33 in the older
RULE 03

Bond principal is not a share count

A 13F row is either a share count or a principal amount in dollars, and the column that says which is easy to ignore. One filer reported 794,117,000 of principal in a single convertible bond; counted as shares it moved one sector by roughly 385 billion dollars on its own. Only share rows are treated as share flow. Option rows, puts and calls, are excluded the same way and counted separately, because an option position is not ownership.

  • acidcapitalist/lib/institutional/quarter-diff.ts
  • measured 2026-08-06, one principal row alone distorted a sector by about 385 billion dollars
RULE 04

Undo the split before comparing

NFLX split 10 for 1 and NOW 5 for 1 inside the compared quarter. A split multiplies every holder's share count by the same factor and divides the mark by it, and trading never does that to every holder at once. That is the detector: the median share ratio across holders lands on a clean factor, and undoing that factor brings the price move back into a normal range. Across the 100 ticker universe it found exactly two splits and no false positives. When a jump has no clean factor behind it, the ticker is dropped and counted rather than shown as zero, because we cannot compare this and nothing happened are different statements.

  • acidcapitalist/lib/institutional/quarter-diff.ts
  • measured 2026-08-06, 2 splits detected across 100 tickers, 0 false positives
§ 05 · WHAT THIS CANNOT TELL YOU

The limits, including the ones that are our fault

10 LIMITS

13F is late by design

A 13F reports what a manager held on the last day of a quarter, and it is due 45 days after that. So the freshest institutional picture on this site is at least six weeks behind the market, and usually more, because the ingest is a separate step. The header on this page prints which quarter is actually being shown and how old it is, rather than leaving you to assume it is current.

  • SEC Form 13F, due within 45 days of the quarter end
  • acidcapitalist/lib/institutional/hub-flows.ts

A 13F says nothing about shorts, cash or timing

It covers long positions in US listed securities and certain options as of one date. Short positions, cash, bonds, foreign listings and derivatives held elsewhere are not in it. Neither is timing: a position opened and closed inside the quarter never appears, and one that shows up as a purchase may have been bought on any day of the three months.

  • SEC Form 13F covers section 13(f) securities only

The rotation block covers 100 tickers, not the market

The tracked funds carry roughly 315,000 position rows in a single quarter, and the public database role times out before it can page through them, so the comparison is bounded on purpose: the top 100 tickers by institutional value, the funds that filed both quarters, and the 10 sectors with the largest absolute flow. Every exclusion is counted and printed next to the chart, so the section says what it is describing instead of implying the whole market.

  • acidcapitalist/lib/institutional/hub-flows.ts
  • measured 2026-08-06, about 315,000 position rows per quarter across the tracked funds

Not every CUSIP becomes a ticker

81.8 percent of the identifiers resolve. The rest, mostly small or foreign issues, never make it onto a stock page and therefore never make it into an aggregate. By position rows the coverage is 99.58 percent, so the gap is a long tail rather than a hole in the middle, but a niche name can be missing entirely.

  • docs/how-it-works/institutional-xray/overview.md
  • measured 2026-04-04, 81.8 percent of CUSIPs, 99.58 percent of position rows

The stored change columns are wrong and we do not read them

The ingest writes its own quarter over quarter columns, and they are unreliable for exactly the rows that matter most, the ones a large fund reports in several buckets. The rotation and divergence blocks recompute the change instead. Older blocks on this desk that still read those columns are the visible cost: they can stand empty, or print a figure with an impossible number of digits, until they are moved over as well.

  • known defect #19, ingest side fix still open
  • acidcapitalist/lib/institutional/quarter-diff.ts

One unit of the stored market value is a tenth of a cent

The value column is not in dollars and not in thousands: one unit is 1/1000 of a dollar, measured against production and cross checked three ways. Two older places in this codebase read the same column as dollars and as thousands, which is why a fund page can still print an absurd trillion figure. New aggregation carries the unit as an explicit constant that a caller can override, so the assumption is visible and testable rather than buried.

  • acidcapitalist/lib/institutional/sector-flow.ts
  • known defect #17, unit mismatch visible on fund pages
  • measured 2026-08-06, one unit is 1/1000 of a dollar

Insider dollar values are empty

The dollar column on insider rows is not populated, so insider tables render zero dollars while the share counts next to them are real. Divergence therefore falls back in three steps, dollar value first, then shares, then the plain count of transactions, and every alert states which basis it used. The dollar threshold of 1,000,000 is the one that currently cannot fire.

  • acidcapitalist/lib/institutional/divergence.ts
  • known defect #18, insider value column empty in production

We count funds here, we do not name them

The short name column on the filer table is attached to the wrong firm on 19 of 56 curated rows in production, verified one at a time against SEC EDGAR. The full legal name matches on all 56, so the rows themselves are sound and only the display name is scrambled. Until the correction has been applied to the database, anything built after that measurement counts funds instead of naming them. Fund pages built before it can still show a wrong short name, including in their title and their generated biography.

  • known defect #16, short name on the wrong firm
  • measured 2026-08-06, 19 of 56 curated rows carry another firm short name, legal name correct on 56 of 56
  • acidcapitalist/lib/institutional/divergence.ts

Fund typing covers the money, not the count

Behavioral categories are assigned to a curated set of filers rather than to all of them. On AAPL, measured through the public API, 169 of 5,937 institutional holders carried a real category. That is 2.85 percent of the holders but 71.29 percent of the institutional value on the name. So a category breakdown tells you where the size sits, not how many firms agree with each other.

  • acidcapitalist/app/api/webmcp/stock/[symbol]/route.ts
  • measured 2026-08-06, 169 of 5,937 holders classified, 2.85 percent of holders, 71.29 percent of value
  • docs/how-it-works/institutional-xray/overview.md

The rotation numbers can be 3600 seconds stale

The diff is expensive, so the whole computation is cached for 3600 seconds. That is a rendering cache and not a data delay: the filings underneath change once a quarter, so an hour of cache costs nothing in freshness and saves a heavy query on every visit.

  • acidcapitalist/lib/institutional/hub-flows.ts
◇ AC DESK · STANDING RULE

A number nobody can trace is a number nobody should trade.

This page is generated from the modules it describes. The constants come from the code, not from a copywriter, and a test opens every path listed here and every cron schedule quoted here. When one of them stops matching reality, the build fails before you read a stale claim. None of it is financial advice.