What each of the three institution types actually does, how big is big, and three misreadings that measured data takes apart.
The index rose on a day foreign investors bought, so you think you found a signal. But their buying is itself part of that day's turnover — the move and the net buying are the same event counted twice. This article covers the official definition of institutional net buy/sell, its real range, and the three places it is most often misread, all with measured numbers.
Institutional net buy/sell is a set of numbers the Taiwan Stock Exchange publishes every trading day: the amount (or share count) bought minus the amount (or share count) sold that day by three types of institution — foreign and mainland investors, investment trusts, and dealers. A positive value means that type was a net buyer; a negative value means a net seller.
TWSE defines the three types by who they are, not by what they do (report footnotes, verbatim, retrieved 2026-09-17):
| Institution | TWSE definition (verbatim) |
|---|---|
| Dealers | "Dealers means securities dealers' proprietary accounts." |
| Investment trusts | "Investment trusts means domestic securities investment trust funds." |
| Foreign and mainland investors | "Foreign and mainland investors means investors registered under the Regulations Governing Investment in Securities by Overseas Chinese and Foreign Nationals and the Regulations Governing Investment in Securities and Futures Trading in Taiwan by Mainland Area Investors." |
The market-wide institutional trading value report (BFI82U) returns 6 rows and is denominated in TWD; the per-stock daily institutional report (T86) discloses every listed stock and is denominated in shares (a live call on 2026-09-15 returned 15,840 stocks). One of BFI82U's 6 rows is foreign dealers on its own; in Blave's data series that row has been 0 every day since 2024-08-16.
No. TWSE spells it out in the report footnotes:
In other words, institutional net buy/sell is a snapshot of original trades, and it is not revised afterwards for booking corrections. That is the exact opposite of margin balance — the lenders behind margin balance are still adjusting their books the next day, and TWSE explicitly says to use the "previous-day balance" (see How to Use Margin Balance). Both are flow-of-funds data, but the two have different data properties, so research should not treat them the same way.
Publication is the same afternoon after the close. TWSE's own pages do not commit to a fixed clock time, so this article does not quote one to the minute.
Distribution of daily net amounts, in units of 100M TWD. Window 2025-09-17 to 2026-09-16, n=242, from Blave's institutional data series (listed market):
| Institution | p05 | p25 | Median | p75 | p95 | Mean | Net-buy days |
|---|---|---|---|---|---|---|---|
| Foreign | −892.6 | −377.0 | −52.3 | +165.2 | +603.3 | −86.2 | 43.8% |
| Investment trusts | −77.0 | −20.0 | +14.6 | +71.0 | +160.9 | +27.6 | 59.9% |
| Dealers | −301.1 | −104.9 | −14.3 | +60.5 | +153.3 | −34.6 | 47.1% |
| Total | −1,077.3 | −380.7 | −45.4 | +227.0 | +683.8 | −93.1 | 46.3% |
To answer "is today's number big," the absolute-value brackets are more useful than the sign (same window, n=242):
| Institution (100M TWD) | Median absolute | p80 | p90 | p99 | Period max |
|---|---|---|---|---|---|
| Foreign | 262 | 545 | 757 | 1,340 | 1,883 |
| Investment trusts | 42 | 88 | 135 | 267 | 383 |
| Dealers | 75 | 156 | 206 | 548 | 822 |
A daily foreign net around 260 (100M TWD) is routine; it takes more than 757 to crack the top 10% of this window. Investment trusts run a bracket smaller, with a median of just 42 — measure all three institution types with the same yardstick and a big move by the trusts looks like nothing at all.
Most people reading institutional data treat the dealer net as a directional call by brokers' proprietary desks. But TWSE splits dealers into two separately disclosed columns, "proprietary" and "hedging," and the second is far larger than the first.
Measured over the last 60 trading days (TWSE BFI82U pulled day by day, 2026-06-24 to 2026-09-16, n=60):
| Observation | Value |
|---|---|
| Hedging share of dealer turnover (buys + sells) | 78.0% |
| Hedging net as a share of absolute dealer net (daily median) | 76.6% |
| Average daily hedging turnover vs proprietary | 769 vs 218 (100M TWD) |
| Average net over the period | Hedging −81.1/day, proprietary −8.3/day (100M TWD) |
| Days pointing the same way / daily correlation | 73.3% / r=0.716 |
Put differently, close to eight tenths of the "dealer net buying" you see comes from the hedging column. Read together, hedging dominates the number without fully determining it (r=0.716) — to read dealer direction at all, you have to look at the two columns separately.
No. Add the foreign, investment_trust and dealer columns together and the result will not match the "institutional total" in the news — and you did not do the arithmetic wrong.
TWSE's official total is the sum of four items: foreign and mainland investors (excluding foreign dealers) + investment trusts + dealers (proprietary) + dealers (hedging); the foreign-dealer column is not counted in the official total. Blave's API, however, folds foreign dealers into its dealer column, so the three-column sum = the official total + that day's foreign-dealer net.
Take the whole market on 2019-06-03 (FinMind raw data, in TWD):
| Item | Net | In official total |
|---|---|---|
| Foreign and mainland investors | +4,256,940,836 | Yes |
| Investment trusts | −470,794,770 | Yes |
| Dealers (proprietary) | +234,212,750 | Yes |
| Dealers (hedging) | −634,731,645 | Yes |
| Foreign dealers | −1,635,530 | No |
| Official total | +3,385,627,171 | Sum of the four above |
The first four items sum to the official total exactly; what is left out is that −1,635,530 of foreign dealers — and that sits inside Blave's API dealer column. Across 2018–2024 there are 1,553 trading days where the three-column sum does not match the official total; since 2024-08-16 the column has been 0, so the recent gap is zero, but the gap over the historical range is real.
So to match the news or the official release, read the total column directly instead of summing the three yourself — total is the official total, not a sum of the other columns. For recent data only, both methods agree; if your window reaches back before 2024, or you want foreign dealers broken out on their own, go back to the raw BFI82U report, where it is a row of its own and for which Blave's API has no matching column.
dealer is Blave's own convention. When you use this data for research reaching back before 2024, account for the difference yourself.High correlation the same day, close to a coin flip the next. This is the one thing to take away from this article.
Window 2025-09-17 to 2026-09-16, correlation of net buy/sell with TAIEX returns, n=230 (the correlation sample is 12 days shorter than the 242 in the range table because the index data is missing 12 trading days; do not mix the two sample sizes):
| Series | r vs same-day index return | r vs next-day index return |
|---|---|---|
| Foreign | +0.773 | +0.097 |
| Investment trusts | +0.119 | +0.004 |
| Dealers | +0.716 | +0.003 |
| Total | +0.824 | +0.079 |
The same-day correlation is mechanical: institutional buying is itself part of that day's turnover, so a rising price and institutional net buying are two ways of recording one event. The question worth asking is about the next day, and there the correlation is down to +0.097.
Hit rate says the same thing: after a foreign net-buy day the index rose the next day 59.0% of the time (n=100), after a net-sell day 52.7% (n=129), against a full-sample base rate of 55.5%. The gap is real, but stretch the sample to 5 years (n=1,200) and it narrows to 56.4% vs 54.4% (base 55.3%). And the next-day average return is actually higher after net-sell days — +0.286% after selling versus +0.256% after buying. Slightly better hit rate, slightly worse average return: the two cancel out.
Separately. Over the same window (2025-09-17 to 2026-09-16, n=242) the three rarely point the same way:
| Observation | Value |
|---|---|
| Days foreign investors and trusts pointed the same way | 47.5% |
| Days foreign investors and dealers pointed the same way | 75.2% |
| Days all three pointed the same way | 32.6% |
| Days "Total" points against foreign investors | 9.9% |
| Foreign share of absolute institutional net (median weight) | 67.4% |
| Foreign share of institutional turnover (buys + sells) | 83.7% |
"The institutions are buying" is not one thing in the data — all three point the same way on only a third of days. And "Total" is essentially the shadow of foreign investors: they account for 83.7% of institutional turnover, and on only 9.9% of days does the total point against them. You think you are reading a consensus of three institutions; nine times out of ten you are reading one of them.
The market-wide layer is in currency, the per-stock layer is in shares, and the field names differ too — mixing them computes the wrong thing.
from lib.data import fetch_twmarket_institutional, fetch_twstock_institutional
# Market-wide: unit is TWD, fields foreign / investment_trust / dealer / total, from 2004-04-07
mkt = fetch_twmarket_institutional('2025-09-17', '2026-09-16', headers)
# Per-stock: unit is shares, buys and sells in separate columns; lib gives you foreign_net directly
df = fetch_twstock_institutional('2330', '2025-09-17', '2026-09-16', headers)
foreign_net = df['foreign_net'] # foreign shares bought − shares sold
The per-stock layer also gives you the split fields: dealer proprietary (dealer_self_*) and hedging (dealer_hedge_*) are separate, so the "strip the hedging out" judgement from the section above is available at the per-stock layer.
The practical use is to turn "are the institutions moving big today" into a testable condition that gates your own primary signal, rather than entering and exiting on it directly.
# brackets from absolute daily foreign net quantiles over 2025-09-17 to 2026-09-16: p50 262, p90 757 (100M TWD, n=242) BIG = 75_700_000_000 # TWD; this is the data's bracket, not a backtested parameter big_buy = mkt['foreign'] > BIG signal = primary.copy() # primary is your own main signal signal[~big_buy] = 0.0 # no longs on days without big foreign buying
To be clear: this threshold is a distribution bracket, not a parameter validated by a backtest. It answers "where does today's number rank historically," not "will this make money" — only a backtest answers the second, and it has to avoid the trap of tuning parameters over and over on the same stretch of data (see How to Avoid Overfitting).
自營商買賣超股數 (the dealer total) comes before the three "proprietary" columns (index 11), while the proprietary group is buy → sell → net (index 12 / 13 / 14). Assuming the intuitive "proprietary first, then hedging, then total" shifts the whole group. Parse by field name, not by position.Institutional data is daily only, so there is no timeframe to tune; what you can choose is which layer to read and over how many days.
| Approach | Good for | Watch out |
|---|---|---|
| Market-wide daily net | Gauging the strength of index-level fund flows | Listed market only; "Total" is 83.7% the shadow of foreign investors, so don't read it as consensus |
| Market-wide streaks | Describing states like "bought for N days running" | Over 2025-09-17 to 2026-09-16: 49 net-buy streaks, 2.16 days average, 6 days longest; 50 net-sell streaks, 2.72 days average, 13 days longest (n=242) — a five-day buying streak is rarer than you think |
| Per-stock daily net | Per-stock flow conditions and screening filters | Unit is shares; listed stocks come from T86, OTC from TPEx, and both are available |
| Per-stock split fields | When you need hedging taken out of the dealer number | Only the per-stock layer keeps the split fields |
The examples here use the market-wide daily net for a simple reason: the range and correlation measurements were all made at that layer, so the thresholds line up. Move to the per-stock layer and the brackets have to be recomputed from that stock's own distribution.
Now that the definition is clear, the next step is turning it into a condition you can verify: ask Blave Agent to pull this data, write it into a filter, and backtest it for you — the data layer and the fields are already wired up, so you only have to say what you want tested. You can also see the market-wide and per-stock charts directly in Studio: market institutional flows, per-stock flows.