> Source: https://ashareapi.com/en/docs/guides/shareholder-structure/  ·  Markdown version for LLMs / AI agents

Guide

# Reading A-share shareholder counts: chip concentration
 Holder count is the most direct public signal of "whose hands are the chips in": a falling count = concentration in fewer hands (often positive), a surging count = dispersion (retail crowding in). This guide covers the three tables, the fields, and a real case.

## 1. Why look at shareholder counts (30 seconds)
 Short-term moves are driven by money; **medium-term moves are decided by chip structure**. The holder count is the clearest public signal of that structure:

-
 **Count falling** → chips moving from retail to a few hands (big money / institutions) — usually read as **accumulation**

-
 **Count rising** → chips dispersing (more retail taking over) — usually read as **distribution / fading**

-
 **Average shares held** = total shares / count, inversely related, also measures concentration

 **Note**: "usually read" is not a hard signal — combine with price level and who is on both sides

## 2. One request, three tables
 `/v1/shareholder` is a paid endpoint. One parameter: `code`. The `data` is an **object** with `tables` (three tables).

 Python: fetch shareholder structure (three tables)
```
import requests

BASE = "https://api.ashareapi.com/v1"
H = {"Authorization": "Bearer ct-your-key"}

b = requests.get(f"{BASE}/shareholder",
 params={"code": "sh600667"}, headers=H, timeout=60).json()
d = b["data"] # note: data is an object, not an array

for t in d["tables"]: # three tables, each with title/slug/rows
 print("== [%s] %s ==" % (t["slug"], t["title"]))
 for row in t["rows"][:5]:
 print(" ", row)
```

-
 **`data` is an object** (with `tables`), not a plain array — iterate with `data["tables"]`

-
 **Do not use `body["structured"]`** — shareholder data is a dict; that key is absent

## 3. What each of the three tables tells you
 |
| | Table (slug) | Content | Use

| | `top10_holders` | Top-10 shareholders | Who controls / whether big institutions are there

| | `top10_float_holders` | Top-10 float holders | Who is in the tradable float (closer to trading)

| | `holder_count` | Holder-count history | **Chip concentration core**: count trend over time

 `top10_holders`
 Top-10 shareholders
 Who controls / whether big institutions are there

 `top10_float_holders`
 Top-10 float holders
 Who is in the tradable float (closer to trading)

 `holder_count`
 Holder-count history
 **Chip concentration core**: count trend over time

 **`holder_count` is the most valuable** — it is reported per quarter and shows the count **trend** (not a single point).

## 4. Reading the fields
 |
| | Field | Meaning | Unit | Note

| | holdShares | Shares held | shares | How many the holder owns

| | holdPct | Holding % | % | Share of total shares

| | holdChange | Holding change | shares | + = added / - = reduced / 0 = unchanged

| | totalSHNum | Total holder count | holders | Count at the period

| | avgHoldShares | Avg shares per holder | shares | Total shares / count (inverse to count)

| | date | As-of date | - | Report date (important: lags)

 holdShares
 Shares held
 shares
 How many the holder owns

 holdPct
 Holding %
 %
 Share of total shares

 holdChange
 Holding change
 shares
 + = added / - = reduced / 0 = unchanged

 totalSHNum
 Total holder count
 holders
 Count at the period

 avgHoldShares
 Avg shares per holder
 shares
 Total shares / count (inverse to count)

 date
 As-of date
 -
 Report date (important: lags)

 **Two counts**: `totalSHNum` (total) and `aSHNum` (A-share) are usually equal; `avgHoldShares` / `aAvgHoldShares` likewise.

## 5. Real case: Tai Ji Industry (600667) count triples in a year
 Live holder_count table returned 2026-09-29:

-
 **Trend**: 153.6k → 178.2k → **548.9k**, a 3.5x jump; avg shares fell from 13,614 to 3,810

-
 **Meaning**: **lots of new retail flooded in, chips moved from concentrated to heavily dispersed** — a classic "high-level distribution / retailisation" pattern

-
 **Combine with price**: if price rose then stalled, "count surge + price stalling" is a distribution risk; if it happens at a low after volume expansion, it may start a new rotation (needs more context; not a conclusion here)

 |
| | Date | Holder count | Avg shares | Read

| | 2025-12-31 | 153,627 | 13,614 | Baseline

| | 2026-03-31 | 178,193 | 11,738 | +16%, chips starting to spread

| | 2026-06-30 | 548,947 | 3,810 | **Count tripled — chips heavily dispersed**

 2025-12-31
 153,627
 13,614
 Baseline

 2026-03-31
 178,193
 11,738
 +16%, chips starting to spread

 2026-06-30
 548,947
 3,810
 **Count tripled — chips heavily dispersed**

 **Why this is a good case**: it shows the proper use of the metric — read the **trend**, not a single point, and **pair it with the price level**.

## 6. Bulk scan (find "chips concentrating")

 Python: scan a list for holder counts falling notably
```
CODES = ["sh600667", "sh600519", "sz300750", "sh601318",
 "sh600036", "sz000858", "sh600030", "sh601899"]

for code in CODES:
 b = requests.get(f"{BASE}/shareholder", params={"code": code},
 headers=H, timeout=60).json()
 d = b.get("data") or {}
 for t in d.get("tables", []):
 if t.get("slug") != "holder_count":
 continue
 rows = t.get("rows", []) # latest first
 if len(rows) < 2:
 continue
 latest = int(rows[0].get("totalSHNum") or 0)
 prev = int(rows[1].get("totalSHNum") or 0)
 if prev > 0 and latest < prev * 0.9: # count down >10% = concentrating
 print("%s %s count %d → %d [concentrating]" % (
 code, rows[0].get("date"), prev, latest))
```

-
 **Find concentration**: `latest 10% from prior) — chips moving to fewer hands

-
 **Find dispersion** (reverse): `latest > prev * 1.2` (up >20%) — retail crowding in (can be a avoid signal)

-
 **Mind the lag**: counts are quarterly (a 2026-06-30 count only appears by end of August) — not a "today" signal

## 7. Two common misreads (important)

-
 **1. Count data lags** — quarterly, not real-time. Look at the `date` (as-of) field and do not treat it as the latest

-
 **2. Falling count is not always bullish, rising not always bearish** — it is a **mirror of chip structure**. Combine with: price level (high-level dispersion is risky / low-level concentration may accumulate), who is on both sides (institution vs retail), and the overall market

## FAQ
 Is the holder count real-time?
 No. Disclosed per quarterly report (with lag). The date field marks the as-of date — use it to know which period the data is, not the latest.

 Is a falling count bullish?
 Usually a positive "chip concentration" signal, but not absolute. Combine with price level: low-level concentration (may accumulate) differs from high-level concentration (may already have run). It is a structural mirror, not a buy/sell conclusion.

 Why not just look at top-10 holders?
 Top-10 holders are a single point (who holds now); holder count is a trend (how concentration is changing). They complement: top-10 shows "who is there", count shows "concentrating or dispersing".

 Why is data an object not an array?
 shareholder returns multiple tables (top-10 / float / count), carried in an object with a tables array. Iterate with data["tables"], not body["structured"].

 Last updated: 2026-09-29
 Fields and structure from live ashareapi /v1/shareholder responses (2026-09-29 measured: three-table structure, field semantics); case data is the real holder_count series of Tai Ji Industry (600667) across 2025-12-31 / 2026-03-31 / 2026-06-30.

 Related

-
[Endpoint reference (shareholder)](/en/docs/endpoints/shareholder)

-
[Reading A-share block trades](/en/docs/guides/block-trade-signals)

-
[Factor screening basics (incl. health check)](/en/docs/guides/factor-screening)

-
[Error codes & rate limits](/en/docs/errors)

 [← All tutorials](/en/docs/guides)
