research: add KSEI ownership data analysis and feature design

- Parse 73-page KSEI/IDX >1% ownership PDF (27-Feb-2026 snapshot)
- 7,257 ownership records across 955 tickers, 5,195 unique investors
- OWNERSHIP_FEATURE_DESIGN.md: SQLite schema, entity graph model, CLI commands,
  data pipeline, entity resolution strategy
- Raw analysis artifacts (extracted text, analysis JSON)
This commit is contained in:
Ciphercat 2026-03-05 16:19:49 +00:00
commit e3fa777e1a
5 changed files with 8538 additions and 0 deletions

View file

@ -0,0 +1,387 @@
# IDX Ownership Intelligence Feature Design (KSEI >1% Dataset)
## 1) What I analyzed
### Source file
- URL: `https://www.idx.co.id/StaticData/NewsAndAnnouncement/ANNOUNCEMENTSTOCK/From_EREP/202603/95f8c4c8bc_848269e900.pdf`
- Saved to: `/var/lib/openclaw/projects/idx-cli/research/ownership_202603.pdf`
- Download note: direct `curl` got Cloudflare block HTML; download succeeded using browser-like headers via Python `urllib`.
### Parsing approach
- `pdftotext` not available in runtime.
- Used Node parser stack:
- `pdf-parse` for full-text sanity check
- `pdf2json` for coordinate-based extraction (critical for column integrity)
- Extracted row-level dataset to:
- `/var/lib/openclaw/projects/idx-cli/research/ownership_202603_rows.ndjson`
- `/var/lib/openclaw/projects/idx-cli/research/ownership_202603_analysis.json`
---
## 2) PDF structure analysis
### High-level structure
- Total pages: **73**
- First pages: cover letter/explanatory text from KSEI.
- Tabular section (core data): repeated row records with these headers:
```text
DATE
SHARE_CODE
ISSUER_NAME
INVESTOR_NAME
INVESTOR_TYPE
LOCAL_FOREIGN
NATIONALITY
DOMICILE
HOLDINGS_SCRIPLESS
HOLDINGS_SCRIP
TOTAL_HOLDING_SHARES
PERCENTAGE
```
### Observed dataset size (from parsed rows)
- Total ownership rows: **7,257**
- Unique tickers (`share_code`): **955**
- Unique issuer names: **956** (1 extra due naming variant/noise)
- Unique investor names (raw uppercased): **5,195**
- As-of date: **27-Feb-2026** for all rows in this release
### Example extracted rows
```json
{
"date": "27-Feb-2026",
"share_code": "AADI",
"issuer_name": "ADARO ANDALAN INDONESIA Tbk",
"investor_name": "ADARO STRATEGIC INVESTMENTS",
"investor_type": "CP",
"local_foreign": "L",
"nationality": "",
"domicile": "INDONESIA",
"holdings_scripless": "3.200.142.830",
"holdings_scrip": "0",
"total_holding_shares": "3.200.142.830",
"percentage": "41,10"
}
```
```json
{
"date": "27-Feb-2026",
"share_code": "AALI",
"issuer_name": "ASTRA AGRO LESTARI Tbk",
"investor_name": "PT ASTRA INTERNATIONAL TBK",
"investor_type": "CP",
"local_foreign": "L",
"nationality": "",
"domicile": "INDONESIA",
"holdings_scripless": "0",
"holdings_scrip": "1.533.682.440",
"total_holding_shares": "1.533.682.440",
"percentage": "79,68"
}
```
### Data quality notes
- Missingness:
- `investor_type` missing: 244 rows
- `local_foreign` missing: 244 rows
- `nationality` missing: 4,240 rows
- `domicile` missing: 1,053 rows
- Investor types observed most: `CP`, `ID`, `IB`, `MF`, `SC`, `OT`, `IS`
- Raw entity names have normalization issues (`PT`, punctuation, case, suffix variations).
---
## 3) Analytical potential from this release
### Cross-holder signal (same investor across many tickers)
Top examples (raw name grouping):
- UOB KAY HIAN PRIVATE LIMITED: **66** tickers
- BANK OF SINGAPORE LIMITED: **38**
- PT. ASABRI (Persero): **33**
- DJS Ketenagakerjaan (JHT): **31**
- UBS AG Singapore Branch: **27**
This already forms a strong bipartite graph: `entity -> owns -> ticker`.
### Concentration metrics per ticker
Examples from parsed results:
- Very concentrated:
- `IBST`: 1 holder >1%, total captured 99.95%
- `SUPR`: largest holder 97.33%
- More dispersed among >1% holders:
- `BBRI`: total >1% captured 5.86%
- `ADHI`: 7.37%
- `BBNI`: 7.95%
### Breadth metric
- Tickers with most >1% holders in this snapshot:
- `CARS` (28), `INPC` (28), `BOGA` (27), etc.
---
## 4) Proposed data model (SQLite-first)
Use SQLite for local analytics in `idx-cli` (fast, portable, no server dependency).
### Core tables
```sql
-- One PDF release/event
CREATE TABLE ownership_release (
id INTEGER PRIMARY KEY,
source_url TEXT NOT NULL,
source_file_sha256 TEXT NOT NULL UNIQUE,
as_of_date TEXT NOT NULL, -- YYYY-MM-DD
published_at TEXT,
fetched_at TEXT NOT NULL,
parser_version TEXT NOT NULL,
row_count INTEGER NOT NULL,
metadata_json TEXT
);
CREATE TABLE issuer (
id INTEGER PRIMARY KEY,
ticker TEXT NOT NULL UNIQUE,
issuer_name_raw TEXT NOT NULL,
issuer_name_norm TEXT NOT NULL
);
CREATE TABLE entity (
id INTEGER PRIMARY KEY,
canonical_name TEXT NOT NULL,
canonical_name_norm TEXT NOT NULL UNIQUE,
entity_kind TEXT, -- company/person/fund/gov/unknown
country_hint TEXT,
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL
);
-- Raw name variants resolved to entity
CREATE TABLE entity_alias (
id INTEGER PRIMARY KEY,
entity_id INTEGER NOT NULL REFERENCES entity(id),
alias_raw TEXT NOT NULL,
alias_norm TEXT NOT NULL,
confidence REAL NOT NULL, -- 0..1
method TEXT NOT NULL, -- exact/manual/fuzzy/rule
UNIQUE(entity_id, alias_norm)
);
CREATE TABLE ownership_fact (
id INTEGER PRIMARY KEY,
release_id INTEGER NOT NULL REFERENCES ownership_release(id),
issuer_id INTEGER NOT NULL REFERENCES issuer(id),
entity_id INTEGER NOT NULL REFERENCES entity(id),
investor_name_raw TEXT NOT NULL,
investor_type TEXT,
local_foreign TEXT,
nationality TEXT,
domicile TEXT,
holdings_scripless INTEGER NOT NULL,
holdings_scrip INTEGER NOT NULL,
total_holding_shares INTEGER NOT NULL,
percentage_bps INTEGER NOT NULL, -- e.g. 41.10% => 4110
-- one row per entity/ticker/release/rawname (can enforce stronger uniqueness later)
UNIQUE(release_id, issuer_id, investor_name_raw)
);
```
### Useful indexes
```sql
CREATE INDEX idx_fact_release_issuer ON ownership_fact(release_id, issuer_id);
CREATE INDEX idx_fact_release_entity ON ownership_fact(release_id, entity_id);
CREATE INDEX idx_fact_pct ON ownership_fact(release_id, percentage_bps DESC);
CREATE INDEX idx_alias_norm ON entity_alias(alias_norm);
```
---
## 5) End-to-end pipeline design (PDF → queryable intelligence)
1. **Fetch**
- Download announcement PDF using robust HTTP headers.
- Store raw file in data dir + SHA256.
2. **Parse (bronze)**
- Coordinate extraction from PDF (x/y text cells).
- Emit raw row JSON with strict schema + parser warnings.
3. **Normalize (silver)**
- Parse numerics:
- `1.533.682.440` → integer shares
- `79,68` → 7968 bps
- Standardize date: `27-Feb-2026``2026-02-27`
- Normalize text fields (trim, whitespace, uppercase key columns).
4. **Resolve entities (gold)**
- Deterministic normalization rules (`PT.`, commas, suffixes, punctuation).
- Alias mapping table + manual overrides.
- Fuzzy match only with high threshold + review queue.
5. **Load SQLite**
- UPSERT `issuer`, `entity`, `entity_alias`, `ownership_fact`.
- Keep release snapshots immutable for time-series diffs.
6. **Derive marts/materialized views**
- `v_ticker_concentration` (HHI, top1, top3, sum>1)
- `v_entity_cross_holdings` (#tickers, total bps)
- `v_pair_coownership` (entity pairs co-appearing across tickers)
---
## 6) Entity graph design
### Graph model
- **Node types**:
- `Entity` (investor)
- `Ticker` (issuer)
- **Edge**: `OWNS` with attributes
- `release_id`, `percentage_bps`, `shares_total`, `investor_type`, `local_foreign`
### Derived graph analytics
1. **Cross-holders**: entities with high ticker degree.
2. **Co-ownership network**:
- Build `Entity --co_owns--> Entity` weighted by number of shared tickers and summed min(%).
3. **Cluster detection**:
- Louvain / connected components on co-ownership graph.
4. **Concentration**:
- per ticker `top1`, `top3`, `sum_pct_gt1`, `HHI`.
5. **Temporal graph** (when monthly releases accumulate):
- edge delta (`+/- bps`), entry/exit events, emerging cluster shifts.
---
## 7) CLI command proposals
Integrate as a new top-level group in `SPEC.md` style:
```text
idx ownership
├── ticker <SYMBOL> # holders >1% for ticker
├── entity <NAME_OR_ID> # what this entity owns
├── cross-holders # entities with widest cross-ownership
│ [--top 20] [--min-tickers 5]
├── concentration # ranking by concentration metrics
│ [--by top1|top3|sum|hhi] [--top 20] [--least]
├── clusters # co-ownership clusters
│ [--min-shared 2]
├── changes # compare two releases
│ --from <YYYY-MM-DD> --to <YYYY-MM-DD>
├── releases # available snapshots
├── import # parse & load latest PDF(s)
│ [--url <PDF_URL>] [--file <PATH>] [--as-of <DATE>] [--force]
└── resolve # alias/entity management
├── list-unresolved
├── map <ALIAS> <ENTITY>
└── merge <ENTITY_A> <ENTITY_B>
```
### Example UX
```bash
$ idx ownership ticker BBCA
AS OF: 2026-02-27 | TICKER: BBCA
RANK INVESTOR TYPE L/F SHARES %
1 PT ... CP L 12,345,678,900 54.32
2 ...
```
```bash
$ idx -o json ownership entity "UOB KAY HIAN PRIVATE LIMITED"
{
"entity": "UOB KAY HIAN PRIVATE LIMITED",
"as_of": "2026-02-27",
"ticker_count": 66,
"holdings": [ ... ]
}
```
---
## 8) Architecture recommendations
### Local-first (recommended MVP)
- DB path: `~/.local/share/idx/ownership.db` (or XDG equivalent)
- Raw files cache: `~/.cache/idx/ownership/raw/`
- Parsed snapshots: `~/.cache/idx/ownership/parsed/`
Pros: offline-capable, instant query, aligns with existing CLI/caching philosophy in `SPEC.md`.
### Update model
- `idx ownership import` checks known URL(s) or accepts explicit URL/file.
- De-duplicate by SHA256 + as_of_date.
- Keep all snapshots to unlock `changes` and trend analytics.
### Optional future API mode
- If multi-user/team usage needed, same schema can back a lightweight API service.
- Keep CLI query layer repository-backed so data source can be local SQLite or remote API.
---
## 9) Entity resolution challenges (critical)
1. **Name variants**: `PT X`, `PT. X`, `X PT`, punctuation/case.
2. **Corporate suffix permutations**: `TBK`, `Tbk`, `(PERSERO)`, etc.
3. **Custodian omnibus names** may mask underlying beneficial owners.
4. **Person name ambiguity** (same personal names).
5. **Cross-language spelling** and abbreviations.
6. **Corporate group mapping** (subsidiary vs parent): separate from exact legal entity identity.
### Practical strategy
- Phase 1: conservative exact+rule normalization (high precision).
- Phase 2: human-reviewed alias map.
- Phase 3: optional fuzzy suggestions with confidence score, never auto-merge below threshold.
---
## 10) Integration with current `idx-cli` SPEC
Current `SPEC.md` is quote/fundamental/technical-centric. Ownership feature fits as a differentiated analytics vertical:
- Add new top-level command group: `ownership`
- Reuse global output modes: `table|json|csv|tsv`
- Reuse config precedence (flags > env > config)
- Extend config:
```toml
[ownership]
db_path = "~/.local/share/idx/ownership.db"
raw_cache_dir = "~/.cache/idx/ownership/raw"
parsed_cache_dir = "~/.cache/idx/ownership/parsed"
entity_resolution_mode = "conservative"
auto_import = false
```
- Add milestone slice (proposed):
- **v0.2.5**: `ownership import`, `ownership ticker`, `ownership entity`
- **v0.3**: concentration/cross-holder rankings, releases/changes
- **v0.4+**: clustering/graph exports and manual resolution workflow
---
## 11) Open questions before implementation
1. Official stable source URL pattern for future monthly releases?
2. Will data always be PDF only, or also XLS/CSV endpoint?
3. Canonical meaning of investor type codes (`CP`, `ID`, `IB`, etc.) — need official codebook.
4. Should ADR/dual-listing/suspended symbols be filtered in CLI output?
5. Entity resolution governance: where to store curated alias mappings in-repo vs user-local?
---
## 12) Key files generated in this research
- `/var/lib/openclaw/projects/idx-cli/research/ownership_202603.pdf`
- `/var/lib/openclaw/projects/idx-cli/research/ownership_202603_extracted.txt`
- `/var/lib/openclaw/projects/idx-cli/research/ownership_202603_rows.ndjson`
- `/var/lib/openclaw/projects/idx-cli/research/ownership_202603_analysis.json`
- `/var/lib/openclaw/projects/idx-cli/research/OWNERSHIP_FEATURE_DESIGN.md`
These provide a concrete parsed sample and can be used directly to bootstrap implementation + tests.

View file

@ -0,0 +1,609 @@
{
"page_count": 73,
"row_count": 7257,
"unique_tickers": 955,
"unique_issuers": 956,
"unique_investors": 5195,
"columns": [
"date",
"share_code",
"issuer_name",
"investor_name",
"investor_type",
"local_foreign",
"nationality",
"domicile",
"holdings_scripless",
"holdings_scrip",
"total_holding_shares",
"percentage"
],
"sample_rows": [
{
"date": "27-Feb-2026",
"share_code": "AADI",
"issuer_name": "ADARO ANDALAN INDONESIA Tbk",
"investor_name": "ADARO STRATEGIC INVESTMENTS",
"investor_type": "CP",
"local_foreign": "L",
"nationality": "",
"domicile": "INDONESIA",
"holdings_scripless": "3.200.142.830",
"holdings_scrip": "0",
"total_holding_shares": "3.200.142.830",
"percentage": "41,10"
},
{
"date": "27-Feb-2026",
"share_code": "AADI",
"issuer_name": "ADARO ANDALAN INDONESIA Tbk",
"investor_name": "ALAMTRI RESOURCES INDONESIA TBK PT",
"investor_type": "CP",
"local_foreign": "L",
"nationality": "",
"domicile": "INDONESIA",
"holdings_scripless": "1.197.023.942",
"holdings_scrip": "0",
"total_holding_shares": "1.197.023.942",
"percentage": "15,37"
},
{
"date": "27-Feb-2026",
"share_code": "AADI",
"issuer_name": "ADARO ANDALAN INDONESIA Tbk",
"investor_name": "GARIBALDI THOHIR",
"investor_type": "ID",
"local_foreign": "L",
"nationality": "INDONESIAN",
"domicile": "INDONESIA",
"holdings_scripless": "454.011.607",
"holdings_scrip": "0",
"total_holding_shares": "454.011.607",
"percentage": "5,83"
},
{
"date": "27-Feb-2026",
"share_code": "AADI",
"issuer_name": "ADARO ANDALAN INDONESIA Tbk",
"investor_name": "SARATOGA INVESTAMA SEDAYA TBK PT",
"investor_type": "CP",
"local_foreign": "L",
"nationality": "",
"domicile": "INDONESIA",
"holdings_scripless": "340.897.429",
"holdings_scrip": "0",
"total_holding_shares": "340.897.429",
"percentage": "4,38"
},
{
"date": "27-Feb-2026",
"share_code": "AADI",
"issuer_name": "ADARO ANDALAN INDONESIA Tbk",
"investor_name": "EDWIN SOERYADJAYA",
"investor_type": "ID",
"local_foreign": "L",
"nationality": "INDONESIAN",
"domicile": "INDONESIA",
"holdings_scripless": "273.955.636",
"holdings_scrip": "0",
"total_holding_shares": "273.955.636",
"percentage": "3,52"
},
{
"date": "27-Feb-2026",
"share_code": "AADI",
"issuer_name": "ADARO ANDALAN INDONESIA Tbk",
"investor_name": "IR. T. PERMADI RACHMAT",
"investor_type": "ID",
"local_foreign": "L",
"nationality": "INDONESIAN",
"domicile": "INDONESIA",
"holdings_scripless": "254.992.918",
"holdings_scrip": "0",
"total_holding_shares": "254.992.918",
"percentage": "3,27"
},
{
"date": "27-Feb-2026",
"share_code": "AADI",
"issuer_name": "ADARO ANDALAN INDONESIA Tbk",
"investor_name": "SANDIAGA SALAHUDDIN UNO",
"investor_type": "ID",
"local_foreign": "L",
"nationality": "INDONESIAN",
"domicile": "INDONESIA",
"holdings_scripless": "159.027.175",
"holdings_scrip": "0",
"total_holding_shares": "159.027.175",
"percentage": "2,04"
},
{
"date": "27-Feb-2026",
"share_code": "AADI",
"issuer_name": "ADARO ANDALAN INDONESIA Tbk",
"investor_name": "PERSADA CAPITAL INVESTAMA",
"investor_type": "CP",
"local_foreign": "L",
"nationality": "",
"domicile": "INDONESIA",
"holdings_scripless": "119.887.170",
"holdings_scrip": "0",
"total_holding_shares": "119.887.170",
"percentage": "1,54"
},
{
"date": "27-Feb-2026",
"share_code": "AADI",
"issuer_name": "ADARO ANDALAN INDONESIA Tbk",
"investor_name": "FTAG INVESTMENT BANK LTD",
"investor_type": "IB",
"local_foreign": "A",
"nationality": "",
"domicile": "MALAYSIA",
"holdings_scripless": "100.722.000",
"holdings_scrip": "0",
"total_holding_shares": "100.722.000",
"percentage": "1,29"
},
{
"date": "27-Feb-2026",
"share_code": "AADI",
"issuer_name": "ADARO ANDALAN INDONESIA Tbk",
"investor_name": "PT TRINUGRAHA THOHIR",
"investor_type": "CP",
"local_foreign": "L",
"nationality": "",
"domicile": "INDONESIA",
"holdings_scripless": "89.926.520",
"holdings_scrip": "0",
"total_holding_shares": "89.926.520",
"percentage": "1,15"
},
{
"date": "27-Feb-2026",
"share_code": "AALI",
"issuer_name": "ASTRA AGRO LESTARI Tbk",
"investor_name": "PT ASTRA INTERNATIONAL TBK",
"investor_type": "CP",
"local_foreign": "L",
"nationality": "",
"domicile": "INDONESIA",
"holdings_scripless": "0",
"holdings_scrip": "1.533.682.440",
"total_holding_shares": "1.533.682.440",
"percentage": "79,68"
},
{
"date": "27-Feb-2026",
"share_code": "AALI",
"issuer_name": "ASTRA AGRO LESTARI Tbk",
"investor_name": "DJS KETENAGAKERJAAN PROGRAM JAMINAN HARI TUA",
"investor_type": "IS",
"local_foreign": "L",
"nationality": "",
"domicile": "INDONESIA",
"holdings_scripless": "41.979.300",
"holdings_scrip": "0",
"total_holding_shares": "41.979.300",
"percentage": "2,18"
},
{
"date": "27-Feb-2026",
"share_code": "ABBA",
"issuer_name": "MAHAKA MEDIA Tbk",
"investor_name": "PT. Beyond Media",
"investor_type": "CP",
"local_foreign": "L",
"nationality": "",
"domicile": "INDONESIA",
"holdings_scripless": "1.592.831.618",
"holdings_scrip": "0",
"total_holding_shares": "1.592.831.618",
"percentage": "40,47"
},
{
"date": "27-Feb-2026",
"share_code": "ABBA",
"issuer_name": "MAHAKA MEDIA Tbk",
"investor_name": "SOLIC KREASI BARU PT",
"investor_type": "CP",
"local_foreign": "L",
"nationality": "",
"domicile": "INDONESIA",
"holdings_scripless": "542.042.122",
"holdings_scrip": "0",
"total_holding_shares": "542.042.122",
"percentage": "13,77"
},
{
"date": "27-Feb-2026",
"share_code": "ABBA",
"issuer_name": "MAHAKA MEDIA Tbk",
"investor_name": "MEDIAHUIS IRELAND LIMITED",
"investor_type": "",
"local_foreign": "",
"nationality": "",
"domicile": "",
"holdings_scripless": "0",
"holdings_scrip": "282.886.300",
"total_holding_shares": "282.886.300",
"percentage": "7,19"
},
{
"date": "27-Feb-2026",
"share_code": "ABBA",
"issuer_name": "MAHAKA MEDIA Tbk",
"investor_name": "DRS. WINARTO",
"investor_type": "ID",
"local_foreign": "L",
"nationality": "INDONESIAN",
"domicile": "",
"holdings_scripless": "178.745.400",
"holdings_scrip": "0",
"total_holding_shares": "178.745.400",
"percentage": "4,54"
},
{
"date": "27-Feb-2026",
"share_code": "ABBA",
"issuer_name": "MAHAKA MEDIA Tbk",
"investor_name": "YAYASAN ABDI BANGSA",
"investor_type": "",
"local_foreign": "",
"nationality": "",
"domicile": "",
"holdings_scripless": "0",
"holdings_scrip": "111.372.886",
"total_holding_shares": "111.372.886",
"percentage": "2,83"
},
{
"date": "27-Feb-2026",
"share_code": "ABBA",
"issuer_name": "MAHAKA MEDIA Tbk",
"investor_name": "YAYASAN BINA SEJAHTERA WARGA BULOG",
"investor_type": "",
"local_foreign": "",
"nationality": "",
"domicile": "",
"holdings_scripless": "0",
"holdings_scrip": "52.975.286",
"total_holding_shares": "52.975.286",
"percentage": "1,35"
},
{
"date": "27-Feb-2026",
"share_code": "ABBA",
"issuer_name": "MAHAKA MEDIA Tbk",
"investor_name": "KAIROS EKSPRES INTERNASIONAL PT",
"investor_type": "CP",
"local_foreign": "L",
"nationality": "",
"domicile": "INDONESIA",
"holdings_scripless": "52.362.500",
"holdings_scrip": "0",
"total_holding_shares": "52.362.500",
"percentage": "1,33"
},
{
"date": "27-Feb-2026",
"share_code": "ABBA",
"issuer_name": "MAHAKA MEDIA Tbk",
"investor_name": "PT.Grid One Media",
"investor_type": "CP",
"local_foreign": "L",
"nationality": "",
"domicile": "INDONESIA",
"holdings_scripless": "43.791.628",
"holdings_scrip": "0",
"total_holding_shares": "43.791.628",
"percentage": "1,11"
}
],
"top_cross_holders": [
{
"investor_name": "UOB KAY HIAN PRIVATE LIMITED",
"ticker_count": 66,
"row_count": 66,
"sum_percentage": 369.59
},
{
"investor_name": "BANK OF SINGAPORE LIMITED",
"ticker_count": 38,
"row_count": 38,
"sum_percentage": 142.42
},
{
"investor_name": "PERUSAHAAN PERSEROAN (PERSERO) PT. ASABRI",
"ticker_count": 33,
"row_count": 33,
"sum_percentage": 224.19
},
{
"investor_name": "DJS KETENAGAKERJAAN PROGRAM JAMINAN HARI TUA",
"ticker_count": 31,
"row_count": 31,
"sum_percentage": 72.96
},
{
"investor_name": "UBS AG SINGAPORE BRANCH",
"ticker_count": 27,
"row_count": 27,
"sum_percentage": 94.61
},
{
"investor_name": "DBS BANK LTD.",
"ticker_count": 25,
"row_count": 25,
"sum_percentage": 84.55
},
{
"investor_name": "CGS INTERNATIONAL SECURITIES SINGAPORE PTE LTD",
"ticker_count": 25,
"row_count": 25,
"sum_percentage": 136.07
},
{
"investor_name": "GOVERNMENT OF NORWAY",
"ticker_count": 24,
"row_count": 24,
"sum_percentage": 38.61
},
{
"investor_name": "MAYBANK SECURITIES PTE. LTD.",
"ticker_count": 22,
"row_count": 22,
"sum_percentage": 62.35
},
{
"investor_name": "EMPLOYEES PROVIDENT FUND BOARD",
"ticker_count": 21,
"row_count": 21,
"sum_percentage": 35.9
},
{
"investor_name": "PANIN SEKURITAS Tbk, PT",
"ticker_count": 18,
"row_count": 18,
"sum_percentage": 48.8
},
{
"investor_name": "FIDELITY FUNDS",
"ticker_count": 18,
"row_count": 18,
"sum_percentage": 57.73
},
{
"investor_name": "DRS SURONO SUBEKTI",
"ticker_count": 17,
"row_count": 17,
"sum_percentage": 50.71
},
{
"investor_name": "JAKSA AGUNG MUDA BIDANG TINDAK PIDANA KHUSUS KEJAKSAAN REPUBLIK INDONESIA KEJAKSAAN REPUBLIK INDONESIA",
"ticker_count": 17,
"row_count": 17,
"sum_percentage": 312.31
},
{
"investor_name": "PT TRIMEGAH SEKURITAS INDONESIA TBK",
"ticker_count": 15,
"row_count": 15,
"sum_percentage": 76.52
}
],
"most_concentrated_tickers": [
{
"share_code": "IBST",
"issuer_name": "INTI BANGUN SEJAHTERA Tbk",
"holders_gt1_count": 1,
"sum_pct_gt1": 99.95,
"largest_holder_pct": 99.95
},
{
"share_code": "PGUN",
"issuer_name": "PRADIKSI GUNATAMA Tbk",
"holders_gt1_count": 6,
"sum_pct_gt1": 99.93,
"largest_holder_pct": 38.44
},
{
"share_code": "HITS",
"issuer_name": "HUMPUSS INTERMODA TRANSPORTASI Tbk",
"holders_gt1_count": 4,
"sum_pct_gt1": 99.92,
"largest_holder_pct": 50.57
},
{
"share_code": "SUPR",
"issuer_name": "SOLUSI TUNAS PRATAMA Tbk",
"holders_gt1_count": 2,
"sum_pct_gt1": 99.92,
"largest_holder_pct": 97.33
},
{
"share_code": "DCII",
"issuer_name": "DCI INDONESIA Tbk",
"holders_gt1_count": 10,
"sum_pct_gt1": 99.85,
"largest_holder_pct": 29.9
},
{
"share_code": "POLU",
"issuer_name": "GOLDEN FLOWER Tbk",
"holders_gt1_count": 5,
"sum_pct_gt1": 99.81,
"largest_holder_pct": 79.99
},
{
"share_code": "ROCK",
"issuer_name": "ROCKFIELDS PROPERTI INDONESIA Tbk",
"holders_gt1_count": 8,
"sum_pct_gt1": 99.8,
"largest_holder_pct": 27
},
{
"share_code": "FASW",
"issuer_name": "FAJAR SURYA WISESA Tbk",
"holders_gt1_count": 2,
"sum_pct_gt1": 99.78,
"largest_holder_pct": 59.85
},
{
"share_code": "BPII",
"issuer_name": "BATAVIA PROSPERINDO INTERNASIONAL Tbk",
"holders_gt1_count": 3,
"sum_pct_gt1": 99.74,
"largest_holder_pct": 89.86
},
{
"share_code": "MORA",
"issuer_name": "MORA TELEMATIKA INDONESIA Tbk",
"holders_gt1_count": 10,
"sum_pct_gt1": 99.73,
"largest_holder_pct": 35.99
},
{
"share_code": "POLI",
"issuer_name": "POLLUX HOTELS GROUP Tbk",
"holders_gt1_count": 7,
"sum_pct_gt1": 99.72,
"largest_holder_pct": 56.95
},
{
"share_code": "BNLI",
"issuer_name": "BANK PERMATA Tbk",
"holders_gt1_count": 4,
"sum_pct_gt1": 99.71,
"largest_holder_pct": 89.12
},
{
"share_code": "ABDA",
"issuer_name": "ASURANSI BINA DANA ARTA Tbk",
"holders_gt1_count": 4,
"sum_pct_gt1": 99.67,
"largest_holder_pct": 86.75
},
{
"share_code": "SOHO",
"issuer_name": "SOHO GLOBAL HEALTH Tbk",
"holders_gt1_count": 7,
"sum_pct_gt1": 99.67,
"largest_holder_pct": 40.03
},
{
"share_code": "TIFA",
"issuer_name": "KDB TIFA FINANCE Tbk",
"holders_gt1_count": 4,
"sum_pct_gt1": 99.61,
"largest_holder_pct": 77.5
}
],
"least_concentrated_tickers": [
{
"share_code": "DEAL",
"issuer_name": "DEWATA FREIGHTINTERNATIONAL Tbk",
"holders_gt1_count": 11,
"sum_pct_gt1": 35.8,
"largest_holder_pct": 10.25
},
{
"share_code": "ELTY",
"issuer_name": "BAKRIELAND DEVELOPMENT Tbk",
"holders_gt1_count": 13,
"sum_pct_gt1": 30.72,
"largest_holder_pct": 5.35
},
{
"share_code": "LMAS",
"issuer_name": "LIMAS INDONESIA MAKMUR Tbk",
"holders_gt1_count": 9,
"sum_pct_gt1": 30.14,
"largest_holder_pct": 7.46
},
{
"share_code": "IKAI",
"issuer_name": "INTIKERAMIK ALAMASRI INDUSTRI Tbk",
"holders_gt1_count": 6,
"sum_pct_gt1": 29.68,
"largest_holder_pct": 19.34
},
{
"share_code": "DADA",
"issuer_name": "DIAMOND CITRA PROPERTINDO Tbk",
"holders_gt1_count": 5,
"sum_pct_gt1": 26.24,
"largest_holder_pct": 21.53
},
{
"share_code": "ENVY",
"issuer_name": "ENVY TECHNOLOGIES INDONESIA Tbk",
"holders_gt1_count": 8,
"sum_pct_gt1": 26.21,
"largest_holder_pct": 7.24
},
{
"share_code": "TAXI",
"issuer_name": "EXPRESS TRANSINDO UTAMA Tbk",
"holders_gt1_count": 12,
"sum_pct_gt1": 25.53,
"largest_holder_pct": 4.89
},
{
"share_code": "WIRG",
"issuer_name": "WIR ASIA Tbk",
"holders_gt1_count": 12,
"sum_pct_gt1": 22.28,
"largest_holder_pct": 4.8
},
{
"share_code": "PADI",
"issuer_name": "MINNA PADI INVESTAMA SEKURITAS Tbk",
"holders_gt1_count": 7,
"sum_pct_gt1": 17.91,
"largest_holder_pct": 5.75
},
{
"share_code": "RMKO",
"issuer_name": "ROYALTAMA MULIA KONTRAKTORINDO Tbk",
"holders_gt1_count": 2,
"sum_pct_gt1": 17.8,
"largest_holder_pct": 15.4
},
{
"share_code": "NCKL",
"issuer_name": "TRIMEGAH BANGUN PERSADA Tbk",
"holders_gt1_count": 3,
"sum_pct_gt1": 12.03,
"largest_holder_pct": 6.5
},
{
"share_code": "BBTN",
"issuer_name": "BANK TABUNGAN NEGARA (PERSERO) Tbk",
"holders_gt1_count": 4,
"sum_pct_gt1": 9.98,
"largest_holder_pct": 4.95
},
{
"share_code": "BBNI",
"issuer_name": "BANK NEGARA INDONESIA Tbk",
"holders_gt1_count": 4,
"sum_pct_gt1": 7.95,
"largest_holder_pct": 3.51
},
{
"share_code": "ADHI",
"issuer_name": "ADHI KARYA (PERSERO) Tbk",
"holders_gt1_count": 4,
"sum_pct_gt1": 7.37,
"largest_holder_pct": 2.68
},
{
"share_code": "BBRI",
"issuer_name": "BANK RAKYAT INDONESIA (PERSERO) Tbk",
"holders_gt1_count": 3,
"sum_pct_gt1": 5.86,
"largest_holder_pct": 3.63
}
]
}

File diff suppressed because it is too large Load diff

63
research/package-lock.json generated Normal file
View file

@ -0,0 +1,63 @@
{
"name": "research",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "research",
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"pdf-parse": "^1.1.1",
"pdf2json": "^4.0.2"
}
},
"node_modules/debug": {
"version": "3.2.7",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
"integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
"license": "MIT",
"dependencies": {
"ms": "^2.1.1"
}
},
"node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"license": "MIT"
},
"node_modules/node-ensure": {
"version": "0.0.0",
"resolved": "https://registry.npmjs.org/node-ensure/-/node-ensure-0.0.0.tgz",
"integrity": "sha512-DRI60hzo2oKN1ma0ckc6nQWlHU69RH6xN0sjQTjMpChPfTYvKZdcQFfdYK2RWbJcKyUizSIy/l8OTGxMAM1QDw==",
"license": "MIT"
},
"node_modules/pdf-parse": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/pdf-parse/-/pdf-parse-1.1.1.tgz",
"integrity": "sha512-v6ZJ/efsBpGrGGknjtq9J/oC8tZWq0KWL5vQrk2GlzLEQPUDB1ex+13Rmidl1neNN358Jn9EHZw5y07FFtaC7A==",
"license": "MIT",
"dependencies": {
"debug": "^3.1.0",
"node-ensure": "^0.0.0"
},
"engines": {
"node": ">=6.8.1"
}
},
"node_modules/pdf2json": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/pdf2json/-/pdf2json-4.0.2.tgz",
"integrity": "sha512-iiRSuRmLihoEJ4YGkoqSq3/r4MR0OmkMTYDda0Pq7DAWqJwMylTilXu46T16gfS3DUp3fhiVuz7NtRMbk3uBhw==",
"license": "Apache-2.0",
"bin": {
"pdf2json": "bin/pdf2json.js"
},
"engines": {
"node": ">=20.18.0"
}
}
}
}

16
research/package.json Normal file
View file

@ -0,0 +1,16 @@
{
"name": "research",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"pdf-parse": "^1.1.1",
"pdf2json": "^4.0.2"
}
}