Selamat datang di repositori resmi Skriner Berita & Teknikal 1D—sebuah dashboard pemantauan teknikal dan keterbukaan informasi saham Bursa Efek Indonesia (BEI) yang berbasis halaman tunggal (Single-Page Application / SPA).
Dokumentasi ini ditulis dalam Bahasa Indonesia untuk menjadi keterangan resmi repositori GitHub Anda dan mempermudah pemahaman sistem, serta siap diimpor sebagai konteks komprehensif bagi model AI lainnya.
- Library Skill
.claude/skills/untuk Kontributor/Sesi AI (Baru): Repositori kini memiliki 10 skill terdokumentasi (onboarding,guardrails,pipeline-debugging,idx-scraping,add-data-source,data-validation,frontend-dev,infra-deploy,design-taste,roadmap) plus aturan baku diCLAUDE.md. Setiap sesi AI atau kontributor baru wajib memulai dari.claude/skills/onboarding/SKILL.mdsebelum menyentuh kode atau data apa pun. - Perbaikan Kartu IHSG (commit
bbaeffd): Parsing tanggal pada kartu IHSG kini di-anchor ke zona waktu WIB, memperbaiki selisih 1 hari yang dilihat pengunjung di zona waktu barat. Hari tanpa data nilai transaksi kini tampil sebagai celah jujur (garis putus-putus) alih-alih hilang diam-diam dari grafik. Kartu juga menampilkan catatan kecil saat data yang tampil berasal dari fallback/datayang basi (bukan CDN langsung). - Perbaikan Pipeline & Observabilitas: Bug variable-shadowing pada variabel
metadiskriner_sync.pysudah diperbaiki (di-rename menjadiyf_meta), sehingga field kesehatanihsg_*didata/update_metadata.jsonkini benar-benar tersimpan alih-alih hanya ditulis oleh script rescue. Field observabilitas barulapbul_last_attempt_at/_ok/_reason(ditulis olehscraper/fetch_lapbul_full.py) danfree_float_scrape_last_attempt_at/_ok/_reason+_reports_discovered_count(ditulis olehscripts/scrape_free_float.py) kini merekam setiap percobaan scrape, termasuk yang gagal senyap. - Isu Diketahui (BELUM selesai): Scraping LBRE/Lapbul mati sejak 14 Juni 2026 — tidak ada commit baru dari
sync_daily_lapbul.ymlwalau cron harian tetap berjalan. Analisis akar masalah lengkap dan tindakan yang perlu dilakukan pemilik (menambah langkah instalasi Playwright kesync_daily_lapbul.yml, memeriksa riwayat run di GitHub Actions) ada diBUGS_AND_FIXES_2026-07-12.md. - README Dirapikan: Duplikasi seksi §8–§13 (akibat merge sebelumnya) dihapus sehingga masing-masing seksi kini hanya muncul sekali, dan jadwal workflow di §7 disinkronkan ulang dengan YAML aktual di
.github/workflows/.
- Deskripsi Perusahaan Berbahasa Indonesia (Baru): Menggantikan ringkasan profil Yahoo Finance berbahasa Inggris dengan deskripsi perusahaan komprehensif asli berbahasa Indonesia yang ditarik dari IDNFinancials. Fitur ini menggunakan integrasi khusus (
scraper/fetch_idn_desc.py) yang berjalan secara mingguan otomatis untuk 900+ emiten, sekaligus dirotasi dalam pembaruan harian. Tampilan pada antarmuka kini dilengkapi atribusi sumber (misal: "Sumber: IDNFinancials (Diperbarui: 22 Jun 2026)"). - Migrasi ke Next.js SPA: Menggantikan berkas HTML tunggal (legacy
skriner_v8.html) dengan arsitektur Next.js di dalam folderskriner-light/. Ini memberikan performa rendering yang lebih cepat, navigasi tab yang mulus, dan pengelolaan status yang efisien. - Tampilan Pencarian (Search View) Disempurnakan:
- Pada perangkat seluler, posisi bilah pencarian kini berada di urutan teratas.
- Hasil pencarian diurutkan dengan cerdas (Prioritas: kecocokan awalan kode saham > kandungan kode saham > nama perusahaan / nama pemilik).
- Mengeklik hasil pencarian akan langsung membuka kartu saham (
StockCard) di tab Pencarian tersebut tanpa harus melompat kembali ke tab Home.
- Pengalaman Navigasi Seluler: Tombol navigasi bawah (bottom navbar) telah dirapikan. Menu
FilterdanUrutkan(Sort) sekarang terbuka sebagai panel slide-out tanpa memindahkan Anda dari tab Home. TombolCariditempatkan di posisi paling kanan agar mudah dijangkau. - Integrasi TradingView: Sekarang, mengklik kode saham (ticker) atau logo perusahaan pada kartu akan langsung membuka grafik riwayat saham di TradingView.
- Perbaikan Tampilan Logo Emiten: Alamat CDN penyedia logo diperbaiki ke
assets.stockbit.comsehingga logo dapat dimuat tanpa kendala. - Kalkulator Lot Semakin Lengkap: Menambahkan informasi "Ref. Entri Senyap (1% Trx)" di bawah kalkulasi total dana, yang mengacu pada 1% rata-rata nilai transaksi saham harian.
- Integrasi Broker Research & Market News: Ditambahkan fitur untuk secara otomatis merayapi (scrape) ringkasan pasar dari sekuritas lokal (IndoPremier IPOT News, Phintraco Sekuritas, Samuel Sekuritas, Henan Putihrai/HP Sekuritas) agar investor bisa melihat ringkasan harian langsung di halaman utama. Modul ini sekarang memiliki retensi pintar 30 hari berdasarkan stempel waktu publikasi sebenarnya. Pada kartu IHSG, item IPOT ditampilkan selektif hanya untuk headline ringkasan pasar seperti IHSG, Bursa Pagi, Indonesia Market Summary, Wall Street, dan Bursa Eropa agar feed tidak didominasi trafik IPOT umum.
- True "Nilai Transaksi" & Konsistensi Kartu IHSG 60 Hari: Grafik volume IHSG ditarik langsung dari API Ringkasan Perdagangan BEI resmi untuk menampilkan transaksi harian aktual dalam Triliun/Miliar Rupiah (T/B). Khusus pada kartu IHSG ini, logika perhitungan volume rata-rata harian dan keterangan di bawah grafik distandarkan ketat menggunakan acuan 60 Hari Terakhir (
Avg 60 Days), didukung kapasitas penyimpanan riwayat backend hingga 60 hari bursa. - Label Tanggal Jujur Terpisah (Decoupled Date Labels - Baru): Menghilangkan potensi misinformasi dengan memisahkan keterangan tanggal pembaruan di header kartu secara independen: label Harga (
data_dateYahoo Finance per saham), label IHSG (ihsgData.date), dan label Sektoral (sektorDate), sehingga setiap elemen mencerminkan tanggal transaksi aktual datanya secara jujur. - Perbaikan Riset Broker & PDF Lampiran (Baru): Pemulihan parameter URL IPOTnews (
jdldangroup_news) agar tidak mengarah ke halaman kosong, serta penambahan ekstraksi PDF lampiran otomatis (PDF scraping) untuk Phintraco Sekuritas, Samuel Sekuritas, dan Henan Putihrai (HP) Sekuritas yang terintegrasi dengan gaya "Lampiran" di halaman utama. - Penyempurnaan Antarmuka Berita & Flex-Clipping (Baru): Memperkecil dan merapikan tombol "Lihat kabar lainnya" agar tidak menggunakan warna mencolok (neon) melainkan warna abu-abu redup solid (muted gray) yang lebih menyatu dengan kartu. Desain kartu diperbarui dengan border-radius lebih tajam (
8pxdari sebelumnya12px), dan tinggi kontainer berita ketika kolaps diselaraskan menjadi310pxdengan sistem flex-clipping (overflow: hiddenpada.news-items-wrapper). Hal ini memungkinkan area kosong di kartu yang memanjang (seperti DSSA) otomatis terisi dengan berita tambahan (sampai dengan 8 berita) tanpa merusak kerapian grid. - Perbaikan Navigasi Tag Syariah (Baru): Menambahkan penanganan
preventDefault()pada tombol filterISSIdanNON-ISSIpada kartu emiten, sehingga menekan tombol tag tersebut kini menyaring daftar emiten sharia secara instan dan tidak lagi memicu navigasi paksa ke halaman TradingView dari tautan kartu induk. - Dukungan & Resiliensi Windows Task Scheduler (Terbaru): Memperbaiki masalah eksekusi di latar belakang Windows Task Scheduler dengan memicu perintah penggantian direktori kerja (
cd /d) ke direktori utama proyek sebelum menjalankan python melalui skrip batch otomatis (run_yfinance.batandrun_news_hourly.bat). Selain itu, penjadwal dikonfigurasi kokoh dengan opsiStartWhenAvailable = $truevia PowerShell untuk memastikan tugas yang terlewat (misalnya saat laptop tertidur/mati) akan langsung dijalankan secara otomatis saat perangkat menyala kembali.
Skriner dirancang menggunakan arsitektur modular yang terpisah antara pengambilan data (backend sync) dan penyajian visual (frontend SPA).
graph TD
%% Scraper Data Collection
IDX[Official IDX GET API / Pengumuman] -->|Data Keterbukaan Saham| Scraper[skriner_sync.py Scraper]
IDX -->|Pengumuman Status Pemenuhan Free Float bulk PDF| FFStatusScraper[parse_idx_freefloat_status_pdf.py]
IDX -->|Laporan Bulanan Registrasi Pemegang Saham| FFScraper[scrape_free_float.py Lapbul fallback]
IDX -->|Metadata emiten resmi / DES / konstituen indeks| MetadataScraper[scraper/fetch_metadata.py]
IDX -->|Pemegang Saham di atas 1% KSEI + Lapbul| OwnershipScraper[scraper/fetch_1pct.py + fetch_lapbul_full.py]
MetadataScraper -->|Staging/cache| MetadataStage[docs/data/ihsg_tags.*]
MetadataStage -->|Publish dashboard catalog| MetadataDB[data/ownership_ihsg_tags.*]
MetadataDB -->|Katalog utama ticker: name/sector/board/IPO/tags| Scraper
FFStatusScraper -->|Snapshot resmi bulk| FFStatus[data/idx_free_float_status.json]
FFStatus -->|Prioritas utama Free Float resmi IDX| Scraper
FFScraper -->|Fallback resmi per-emiten| FFTracker[data/free_float_tracker.json]
FFTracker -->|Fallback Free Float resmi IDX/Lapbul| Scraper
YF[Yahoo Finance API 2Y Chart] -->|"Harga, RSI, MACD, EMA/SMA/VMA, ATR, ADR, Vol; bukan Free Float"| Scraper
IDN[IDNFinancials] -->|"Profil Singkat Perusahaan Berbahasa Indonesia"| Scraper
News[CNBC, Kontan, Bisnis, IDX Channel, Bloomberg Technoz, EmitenNews, Katadata, IDN Financials, SWA] -->|RSS/HTML News Crawling| Scraper
MarketNews[IPOT News, Phintraco Sekuritas, Samuel Sekuritas, HP Sekuritas] -->|"Market Summaries & Broker Research"| MarketScraper[scripts/fetch_market_news.py]
Catalog[Unified_Daftar_Saham_IHSG_dan_Indeks.csv] -->|Fallback/supplement shares & old free float only| Scraper
%% Consolidated compilation
Scraper -->|Self-Contained Indicator Engine| Compile{JSON Compiler}
MarketScraper --> Compile
Compile -->|Ekspor JSON| DisclosuresDB[data/skriner_data.json & market_news.json]
OwnershipScraper -->|Staging/cache| OwnershipStage[docs/data/latest*.json/csv + governance csv]
OwnershipStage -->|Publish dashboard layer| OwnershipDB[data/ownership_*]
%% Web App consumption
DisclosuresDB -->|Fetch teknikal/news| WebApp["Next.js Frontend SPA (skriner-light)"]
OwnershipDB -->|Fetch kepemilikan keyed by ticker| WebApp
%% UI Presentation
WebApp -->|Filtering & Sorting Reaktif| View[Next.js Client Grid View]
WebApp -->|Kepemilikan block per ticker| OwnershipView[Ownership block inside card]
WebApp -->|Modal Detail Kabar Efek| Modal[Popup Keterbukaan Emiten]
%% GitHub Actions - Scheduled Workflows
GA1[sync_technical.yml] -->|"Tanpa cron; dispatch iPhone ~17:15 WIB + metadata pre-refresh"| MetadataScraper
GA1 --> Scraper
GA2[sync_news.yml] -->|"Tanpa cron; dispatch iPhone tiap jam"| Scraper
GA3[sync_freefloat.yml] -->|"Otomatis mingguan (Senin 01:21 WIB): bulk IDX status PDF; Lapbul manual ticker/limit"| FFStatusScraper
GA3 -->|"Manual fallback only"| FFScraper
GA3 --> MetadataScraper
GA3 --> Scraper
GA4[sync_ownership.yml] -->|"Bulanan otomatis (tanggal 5, 13:00 WIB): 1% + full Lapbul governance, tanpa input"| OwnershipScraper
GA5[sync_metadata.yml] -->|"Mingguan (Senin 01:11 WIB)/manual"| MetadataScraper
GA6[sync_daily_lapbul.yml] -->|"Harian 18:30 WIB"| FFStatusScraper
GA7[data_sync.yml] -->|"Harian 08:00, 12:00, 17:00 WIB"| Scraper
- Backend Sync Core (
scripts/skriner_sync.py): Modul Python mandiri penuh yang berisi engine gabungan untuk indikator teknikal Yahoo Finance, Kabar, dan IDX Keterbukaan Informasi. Entry harian dipisah menjadiscripts/scrape_yahoofinance.pyuntuk teknikal (bukan Free Float) danscripts/scrape_kabar_keterbukaan.pyuntuk Kabar + pengumuman resmi IDX. Free Float dashboard hanya memakai sumber resmi IDX:data/idx_free_float_status.jsonsebagai prioritas utama dandata/free_float_tracker.jsonLapbul sebagai fallback. Katalog ticker dibaca dari snapshot metadata resmi IDX (data/ownership_ihsg_tags.json/docs/data/ihsg_tags.json); CSV lama hanya fallback/supplement untuk field yang belum tersedia sepertisharesdan free-float awal. - Free Float Scraper (
scripts/scrape_free_float.py): Scraper otomatis bertenaga tinggi yang memindai pengumuman keterbukaan informasi bulanan BEI untuk mengidentifikasi LBRE pemegang saham terverifikasi, mengekstrak data kepatuhan, dan merekam tautan bukti fisik PDF laporan resmi. Menggunakan fungsi discovery Lapbul yang sama denganscraper/fetch_lapbul_full.py(discover_lapbul_reports), sehingga kedua feed berbagi risiko blokir/fallback yang sama. - Official IDX Metadata & Ownership Scraper (
scraper/): Modul mandiri yang sudah terintegrasi ke repo ini.fetch_metadata.pymengambil metadata ticker resmi IDX/DES/index (nama emiten, papan, sektor, IPO, ISSI, LQ45, KOMPAS100) sebagai katalog utama dashboard;fetch_1pct.pymengambil Pemegang Saham di atas 1% dari KSEI. Output staged didocs/data/lalu dipublikasikan ke layer dashboarddata/ownership_*.⚠️ Pengendali (PG) dan UBO di-drop sementara dari rendering dashboard karena data masih tidak lengkap dan metode Lapbul terlalu intensif resource. - Frontend SPA (
skriner-light/): Aplikasi dashboard reaktif berbasis Next.js React SPA yang dikembangkan dalam folder terpisahskriner-light/. Kode produksi dikompilasi secara otomatis oleh Vercel pada saat kode didorong (push) ke GitHub. Data JSON hasil perayapan scraper disimpan langsung di subdirektori publikskriner-light/public/data/agar situs web dapat menyajikan informasi secara statis dengan kinerja tinggi tanpa membutuhkan database server aktif. - Market News Scraper (
scripts/fetch_market_news.py): Script yang merayapi portal investasi publik untuk mendapatkan Market Summary (Bursa Pagi/Siang/Sore) dari IPOT News serta riset harian/lampiran PDF dari Phintraco Sekuritas, Samuel Sekuritas, dan Henan Putihrai (HP) Sekuritas.
Repositori ini menggunakan snapshot metadata resmi IDX sebagai katalog ticker utama, ditambah berkas JSON hasil kompilasi teknikal/news/free-float/ownership.
Merupakan katalog ticker resmi hasil scraper/fetch_metadata.py, bukan lagi CSV/XLSX statis sebagai sumber utama. Field utama: ticker, name, syariah, papan, sector, kompas100, lq45, ipo_year, ipo_date, tags_updated_at.
data/ownership_ihsg_tags.json dipakai oleh scripts/skriner_sync.py sebagai katalog utama untuk data/skriner_data.json. docs/data/ihsg_tags.* adalah staging/cache native scraper. Jika IDX/GitHub Actions sedang diblokir, scraper mempertahankan snapshot lama agar dashboard tetap self-contained. Untuk pengumuman ISSI mayor berbentuk ZIP/XLSX resmi IDX (contoh No. Peng-00089_BEI.POP_05-2026-ID.zip), parser hanya mengambil tabel konstituen aktif pertama dan memperlakukan tabel kedua setelah marker "Konstituen yang keluar dari penghitungan indeks" sebagai daftar exclusion, sehingga ticker seperti MINA/HUMI/GTSI tidak diberi tag ISSI pada periode efektif 2 Juni 2026.
Unified_Daftar_Saham_IHSG_dan_Indeks.csv masih ada hanya sebagai fallback/supplement untuk shares dan free-float lama; bukan lagi sumber utama nama/sektor/papan/IPO/ISSI/LQ45/KOMPAS100. File XLSX manual lama sudah tidak diperlukan oleh pipeline dan tidak menjadi bagian input GitHub Actions.
Berisi rincian harga terakhir, perubahan persentase harian, indikator RSI, ATR%, ADR%, status Moving Average harian, skor teknikal, dan metrik Vol Pengali terbaru.
{
"last_updated": "2026-05-29T11:23:00+07:00",
"stocks": {
"BBCA": {
"code": "BBCA",
"price": 10250,
"pct": 1.48,
"rsi": 54.83,
"atrPct": 1.84,
"adrPct": 1.72,
"macdBull": true,
"vol_mult_1d": 1.45,
"vol_mult_20d": 2.10,
"skor": 7.5,
"maStatus": {
"ema3": true, "ema5": true, "ema10": true
}
}
}
}Berisi snapshot bulk resmi dari pengumuman IDX Status Pemenuhan Kewajiban Jumlah Saham Free Float dan Jumlah Pemegang Saham. Field penting: idx_status_free_float_display, period, source_url, dan evidence. Snapshot ini adalah sumber utama free_float di dashboard.
Berisi basis data penyerahan LBRE/Lapbul dari emiten hasil crawling resmi BEI. Sekarang hanya dipakai sebagai fallback resmi jika ticker belum tersedia pada bulk status Free Float IDX.
Dashboard juga memuat layer tambahan dari scraper resmi IDX/KSEI yang sudah terintegrasi di repo ini (scraper/):
data/ownership_latest.json/.csv: tabel Pemegang Saham di atas 1% per ticker, berisi pemilik, klasifikasi investor, lokal/asing, jumlah saham, dan persentase. Ini adalah sumber utama kepemilikan karena satu dokumen KSEI mencakup hampir seluruh ticker; snapshot 2 Juni 2026 berisi data PDF per 29-May-2026 dan menggantikan snapshot April untuk ticker seperti MINA.data/ownership_pengendali.csvdandata/ownership_ubo.csv:⚠️ tidak lagi difetch oleh frontend per Juni 2026. Data PG/UBO di-drop sementara karena Lapbul tidak mencakup semua emiten dan metode scraping resource-intensive. File fisik tetap ada di repo untuk keperluan staging.data/ownership_summary.json: metadata tanggal/sumber scrape Pemegang Saham di atas 1%;data/ownership_governance_summary.jsondisimpan terpisah tapi tidak dikonsumsi frontend saat ini.data/ownership_ihsg_tags.*: metadata ticker resmi tambahan dari IDX/DES/index konstituen.docs/data/latest*,docs/data/ihsg_tags*: staging/cache native output scraper. File ini sengaja ikut disimpan di repo agar workflow tetap self-contained dan bisa mempertahankan snapshot lama jika GitHub Actions sedang diblokir IDX/Cloudflare.
Layer ini dipakai secara terpisah dari data/skriner_data.json agar data teknikal/news tetap bersih. Frontend menggabungkan data berdasarkan code/share_code dan menampilkan seluruh pemilik di atas 1% pada setiap card; pencarian juga bisa menemukan nama investor. Pada markup card, blok Kepemilikan berada di dalam .card-left-col namun di luar .card-mini-tech, sehingga kepemilikan tampil sebagai panel tersendiri, bukan bagian dari indikator teknikal.
Prinsip utama repo ini: dashboard harus self-sufficient. Semua scraper, workflow, snapshot, dan dependensi Python yang diperlukan untuk memperbarui data harus berada di repo ini. GitHub Actions tidak boleh bergantung pada file XLSX/CSV yang harus ditempel manual dari laptop. Jika IDX/Cloudflare memblokir IP GitHub Actions, workflow harus mempertahankan snapshot terakhir yang sudah tersimpan di repo, bukan membuat dashboard kosong.
| Kebutuhan dashboard | File runtime | Field penting | Sumber utama | Cara mendapatkan / workflow |
|---|---|---|---|---|
| Katalog ticker, nama, sektor, papan, IPO, ISSI/non-ISSI, LQ45, KOMPAS100 | data/skriner_data.json hasil merge dari data/ownership_ihsg_tags.json; staging docs/data/ihsg_tags.* |
code, name, sector, board, listing_date, ipo_year, tags, metadata_source, metadata_updated_at |
Resmi IDX: GetCompanyProfiles, DES/syariah resmi IDX, ZIP/announcement konstituen LQ45/KOMPAS100 |
python scraper/fetch_metadata.py → copy docs/data/ihsg_tags.* ke data/ownership_ihsg_tags.*; otomatis di sync_metadata.yml, sync_technical.yml, sync_freefloat.yml, `sync_owners |
| Keterbukaan informasi emiten dan berita pasar | data/skriner_data.json |
announcement, announcements[].title/date/url/summary/source/category |
Utama: IDX GetAnnouncement; tambahan konteks berita: CNBC, Kontan, Bisnis, IDX Channel, IDN Financials, Bloomberg Technoz, EmitenNews, Katadata, SWA. Parser EmitenNews memprioritaskan timestamp publikasi eksplisit halaman artikel (dd/mm/yyyy HH:mm WIB) dan menolak tanggal publikasi masa depan agar tanggal aksi korporasi di judul (mis. cum/cair dividen) tidak salah dipakai sebagai tanggal berita. Guardrail final sebelum JSON output juga memperbaiki/menolak seluruh announcement future-date, termasuk existing record dari sync sebelumnya. |
python scripts/scrape_kabar_keterbukaan.py; otomatis sync_news.yml tiap jam pada menit 17. Entry ini menjaga indikator Yahoo lama via mode --only-news, sekaligus memicu update portal market news (Phintraco, MNC, IPOT, Samuel). |
| Pemegang Saham di atas 1% | data/ownership_latest.json, data/ownership_latest.csv; staging docs/data/latest.* |
date, share_code, issuer_name, investor_name, investor_classification, local_foreign, nationality, domicile, holdings_scripless, holdings_scrip, total_holding_shares, percentage |
Resmi KSEI via IDX announcement: PDF "Pemegang Saham di atas 1%" attachment _lamp1.pdf / _lamp.pdf |
python scraper/fetch_1pct.py; workflow sync_ownership.yml manual-only agar tidak menghabiskan kuota Actions |
Pengendali (PG) |
data/ownership_pengendali.csv; staging docs/data/latest_pengendali.csv |
date, share_code, issuer_name, investor_name, investor_type, role |
Resmi IDX: per-emiten Laporan Bulanan Registrasi Pemegang Efek; semua tabel yang memiliki kolom Nama + Pengendali/Afiliasi Pengendali bertanda X/checkmark, termasuk Direksi/Komisaris dan pemegang saham 5%+ |
python scraper/fetch_lapbul_full.py --ticker BOLT untuk murah; full all-emiten berjalan otomatis setiap bulan lewat cron sync_ownership.yml (tanggal 5, 13:00 WIB), tanpa input manual |
| UBO / Pemilik Manfaat Akhir | data/ownership_ubo.csv; staging docs/data/latest_ubo.csv |
date, share_code, investor_name, investor_type, direct_ownership, direct_shareholder_name, percentage, evidence |
Resmi IDX: per-emiten Laporan Bulanan Registrasi Pemegang Efek; tabel Pemilik Manfaat / Penerima Manfaat Akhir / Pemilik Manfaat Akhir. Jika Nama Pemegang Saham Langsung terisi, nilainya disimpan sebagai evidence perusahaan pengendali langsung |
python scraper/fetch_lapbul_full.py --ticker BOLT untuk murah; full all-emiten berjalan otomatis setiap bulan lewat cron sync_ownership.yml (tanggal 5, 13:00 WIB), tanpa input manual |
| Latest Free Float / public ownership ratio | data/free_float_tracker.json, lalu merged ke data/skriner_data.json[*].free_float |
ticker, date, benchmark_ratio, source, method, evidence, pdf_attachments |
Resmi IDX: per-emiten Laporan Bulanan Registrasi Pemegang Efek, parser mengambil baris eksak % Saham Free Float / % Free Float Share kolom Bulan Ini / This Month; baris Masyarakat/Publik hanya fallback |
python scripts/scrape_free_float.py --ticker BOLT untuk murah; workflow sync_freefloat.yml manual-only, default skip all-emiten dan mempertahankan snapshot |
| Timestamp versi data | data/update_metadata.json |
technical_updated, disclosures_updated, official_metadata_updated, official_metadata_rows |
Generated by sync scripts from run time + metadata scrape report | technical_updated ditulis oleh scripts/scrape_yahoofinance.py; disclosures_updated ditulis oleh scripts/scrape_kabar_keterbukaan.py |
| Snapshot/cache agar CI tahan blokir IDX | docs/data/*, data/ownership_*, data/idx_free_float_status.*, data/free_float_tracker.json |
snapshot terakhir yang valid | Repo sendiri | Disimpan dalam Git. Workflow memakai fallback snapshot; tidak membutuhkan laptop user. |
File lama Unified_Daftar_Saham_IHSG_dan_Indeks.csv tetap ada hanya sebagai fallback sementara untuk shares dan free-float lama jika sumber resmi belum tersedia. File tersebut bukan lagi sumber utama metadata ticker dan tidak boleh menjadi syarat manual untuk menjalankan GitHub Actions. File XLSX sektoral/indeks manual lama dihapus dari repo karena seluruh metadata aktif sekarang diambil oleh scraper resmi IDX di dalam repo.
Skriner dilengkapi dengan modul crawler otomatis resmi untuk melacak dan memverifikasi persentase free float kepatuhan bursa secara berkala langsung dari laporan Kustodian Sentral Efek Indonesia (KSEI) dan emiten tercatat (LBRE):
Modul ini sekarang self-contained dan GitHub-Actionable: tidak lagi membutuhkan file XLSX lokal LQ45/KOMPAS100. Alurnya:
- API Target:
https://www.idx.co.id/primary/ListedCompany/GetAnnouncementdengan warmup ke halaman keterbukaan informasi IDX. - Sumber PDF: per-emiten Laporan Bulanan Registrasi Pemegang Efek terbaru, ditemukan lewat discovery client-side tanpa bergantung pada filter keyword API yang sering tidak konsisten.
- Ekstraksi Rasio: parser membaca PDF Lapbul dengan
pdfplumberdan mengambil target eksplisit dari tabel Informasi Saham Free Float: baris% Saham Free Float, kolomBulan Inisebagai nilai terbarubenchmark_ratio. PencarianMasyarakat/Publik/Publichanya menjadi fallback jika format Lapbul berbeda. - Satu PDF untuk Governance: parser Lapbul yang sama juga mengekstrak Pengendali dari setiap baris
Namayang memiliki tandaX/checkmark pada kolomPengendaliatauAfiliasi Pengendali, termasuk tabel Direksi/Komisaris dan tabel pemegang saham 5%+. Section UBO mendukung labelPemilik Manfaat,Penerima Manfaat Akhir, atauPemilik Manfaat Akhir, dan menyimpanNama Pemegang Saham Langsungsebagai evidence perusahaan pengendali langsung jika kolom itu terisi. - Evidence: setiap output menyimpan
source,method, potonganevidence, halaman PDF, danpdf_attachmentssehingga nilai free float/governance bisa ditelusuri kembali ke dokumen resmi IDX. - Fallback CI: jika IDX memblokir GitHub Actions dan snapshot
data/free_float_tracker.jsonsudah ada, script exit 0 dan mempertahankan snapshot lama agar dashboard tidak kosong.
Free Float dashboard sekarang IDX-only. Yahoo Finance floatShares / sharesOutstanding tidak dipakai karena definisinya berbeda dari Free Float regulatori IDX. Modul sinkronisasi (scripts/skriner_sync.py) menerapkan prioritas:
- Laporan LBRE/Lapbul per-emiten (
data/free_float_tracker.json): prioritas utama. Jika emiten memiliki data LBRE bulanan di tracker (pada tanggal/bulan berapa pun), dashboard akan menggunakan tanggal, tautan dokumen bukti PDF, dan nilai dari LBRE tersebut. - Bulk IDX Status Free Float (
data/idx_free_float_status.json): jika data LBRE per-emiten tidak tersedia di tracker, dashboard akan menggunakan data dari pengumuman bulk IDX status per 31 Maret 2026. - Unavailable: jika kedua sumber resmi di atas belum punya data untuk ticker tersebut, dashboard menampilkan
currently not available.
Label UI pada Teknikal Box memiliki ikon peringatan (warning icon) berwarna emas di sebelah nilainya. Jika diklik, ikon ini menampilkan popup alert yang bertuliskan (berdasar Keterbukaan Informasi <tanggal_laporan>) untuk menunjukkan tanggal rilis resmi dari keterbukaan informasi/laporan bulanan (LBRE) dari emiten tersebut. Nilai Free Float di-update dari database crawling LBRE terbaru (seperti free_float_tracker.json).
Sistem ini mengkategorikan ukuran dan likuiditas saham secara dinamis namun tetap stabil (anti-flicker) berdasarkan kombinasi keanggotaan indeks dan Kapitalisasi Pasar (Harga × Total Saham), sesuai logika skriner_sync.py (blok "Stock Liner Classification"):
- First Liner (Saham Lapis Satu): Otomatis untuk konstituen resmi indeks LQ45 atau IDX30. Saham non-indeks juga bisa naik ke First Liner murni lewat Kapitalisasi Pasar bila melewati ambang histeresis di bawah.
- Histeresis First ↔ Second Liner: Saham yang berstatus First Liner (dari indeks maupun kapitalisasi) hanya turun ke Second Liner jika Kapitalisasi Pasar anjlok di bawah Rp 8 Triliun. Saham Second/Third Liner naik ke First Liner begitu Kapitalisasi Pasar melewati Rp 12 Triliun.
- Histeresis Second ↔ Third Liner: Saham Second Liner terdegradasi ke Third Liner hanya jika Kapitalisasi Pasar anjlok di bawah Rp 800 Miliar; saham Third Liner naik ke Second Liner begitu Kapitalisasi Pasar melewati Rp 1,2 Triliun.
- Inisialisasi (saham tanpa riwayat
liner): Kapitalisasi Pasar ≥ Rp 10 Triliun langsung First Liner, ≥ Rp 1 Triliun Second Liner, sisanya Third Liner. - Mekanisme Buffer Zone ini sengaja dibuat asimetris di sekitar ambang ekuilibrium (Rp 10T dan Rp 1T) agar saham tidak bolak-balik mengubah kelas/tag-nya setiap hari akibat volatilitas harga jangka pendek.
Semua perhitungan teknikal menggunakan data historis 2 tahun (500+ hari bursa) ke belakang untuk menjamin akurasi Moving Average jangka panjang (hingga EMA/SMA 224). Seluruh indikator dihitung mandiri (self-contained) dari data chart Yahoo Finance tanpa dependensi database eksternal.
Indikator ini dirancang untuk mendeteksi lonjakan volume transaksi tidak wajar (abnormal volume surge) yang mengindikasikan partisipasi institusi besar (Smart Money). Perhitungan indikator ini kebal terhadap akhir pekan dan hari libur nasional karena hanya membandingkan hari-hari perdagangan aktif bursa (hari dengan volume
-
Vol Pengali 1D (vs Kemarin): Perbandingan volume transaksi hari ini (
$Volume_t$ ) terhadap volume transaksi hari perdagangan aktif terakhir sebelum hari ini ($Volume_{\text{active_t-1}}$ ), mengabaikan hari libur bursa dan akhir pekan. $$\text{Vol Pengali 1D} = \frac{\text{Volume}t}{Volume{\text{active_t-1}}}$$ Interpretasi: Nilai$> 2.0x$ menunjukkan volume hari ini melonjak lebih dari 2 kali lipat dibandingkan hari aktif sebelumnya (sekalipun terpisah oleh libur panjang). -
Vol Pengali 20D (vs Rata-rata 20 Hari Sebelumnya): Perbandingan volume transaksi hari ini (
$Volume_t$ ) terhadap rata-rata volume transaksi selama 20 hari perdagangan aktif bursa sebelumnya (tidak termasuk hari ini, libur nasional, dan akhir pekan). $$\text{Vol Pengali 20D} = \frac{\text{Volume}t}{\frac{1}{20} \sum{i=1}^{20} Volume_{\text{active_prev_i}}}$$ Interpretasi: Mengukur kelipatan volume hari ini terhadap rata-rata partisipasi bulanan struktural emiten tersebut berdasarkan 20 hari aktif perdagangan bursa ke belakang.
Sistem penilaian teknikal yang secara otomatis memberikan poin terhadap keunggulan tren, momentum, dan volume emiten:
-
Poin Exponential Moving Average (Poin_EMA): Maksimal 10.0 poin.
- Menguji 10 periode EMA harian:
$\text{EMA} \in {3, 5, 10, 20, 50, 60, 100, 112, 200, 224}$ . - Memberikan
$+1.0$ poin untuk setiap garis EMA di mana harga penutupan terakhir berada di atas EMA tersebut:$$\text{Harga Terakhir} > \text{EMA}_d \implies +1.0$$
- Menguji 10 periode EMA harian:
-
Momentum RSI (Poin_RSI): Maksimal 1.5 poin.
-
Sweet Spot (
$50.0 \le \text{RSI} \le 70.0$ ): Memberikan$+1.5$ poin (momentum bullish yang kuat namun belum jenuh beli). -
Transition Zone (
$40.0 \le \text{RSI} < 50.0$ atau$70.0 < \text{RSI} \le 80.0$ ): Memberikan$+0.5$ poin.
-
Sweet Spot (
-
Tren MACD (Poin_MACD): Maksimal 1.0 poin.
- Memberikan
$+1.0$ poin jika Histogram MACD bernilai positif ($> 0$ ), menandakan tren kenaikan jangka pendek yang dominan.
- Memberikan
-
Volume VMA20 (Poin_VMA): Jaminan
$+0.5$ poin.- Memberikan
$+0.5$ poin jika volume transaksi hari ini berada di atas Volume Moving Average 20 hari ($\text{Volume}t > \text{VMA}{20}$).
- Memberikan
Untuk menjamin integritas data sistem, Skriner menerapkan sistem penyaringan otomatis (self-healing) terhadap saham-saham yang sedang berada dalam status suspensi bursa (seperti emiten BAPA) atau saham tidak aktif/tidur (seperti emiten AKKU).
-
Kriteria Deteksi: Jika sebuah saham terdeteksi memiliki tingkat volatilitas nol (
$\text{ADR}% = 0.0%$ atau$\text{ATR}% = 0.0%$ ) atau tidak memiliki volume transaksi sama sekali ($\text{Volume} = 0$ ), saham tersebut diklasifikasikan sebagai saham tidak aktif/suspensi. -
Pembersihan Data Konsisten: Untuk menghindari disinformasi (misal, menampilkan Skor 10.0 atau RSI 100% akibat data stagnan), sistem secara otomatis:
- Mereset Skor Teknikal menjadi
0.0. - Mengosongkan status RSI dan MACD menjadi
None(ditampilkan sebagai-). - Mengosongkan daftar ceklis Moving Averages (MA) yang aktif.
- Mengosongkan nilai Vol Pengali (1D dan 20D) menjadi
None(ditampilkan sebagai-).
- Mereset Skor Teknikal menjadi
Perhitungan teknikal harian pada Skriner terikat secara ketat dengan Hari Perdagangan Bursa Efek Indonesia (IDX) untuk menghindari distorsi nilai rata-rata dan kehilangan data saat libur bursa:
- Deteksi Otomatis Hari Libur Bursa Kerja (Weekday Holiday Auto-Detection):
Jika sebuah hari libur nasional jatuh pada hari kerja biasa (Senin-Jumat), alur kerja GitHub Actions pada pukul 17:13 WIB tetap akan terpicu. Untuk mencegah penghapusan/pembersihan data teknikal aktif akibat volume pasar nol (
0) hari itu, skrip secara pintar memeriksa volume harian emiten acuan BBCA (Bank Central Asia Tbk.) terlebih dahulu. Jika volume BBCA terdeteksi0, sistem mengenali hari tersebut sebagai hari libur perdagangan resmi. Skrip secara otomatis membatalkan sinkronisasi Yahoo Finance hari itu, sehingga seluruh indikator teknikal, skor, dan rating aktif hari perdagangan bursa sebelumnya tetap terjaga utuh, sementara perayapan berita ringan tetap dilanjutkan. - Pengabaian Otomatis Akhir Pekan/Libur: Kueri riwayat bursa memuat akhiran bursa Indonesia (
.JK). Pada hari Sabtu, Minggu, dan Hari Libur Nasional di mana bursa BEI tutup, data bursa tidak merekam lilin harga baru. - Pembersihan Entri Kosong & Pengisian Metadata: Scraper menyaring barisan data dari Yahoo Finance dan membuang baris non-perdagangan yang kosong. Jika lilin terakhir memuat volume namun harga penutupan (
Close) bernilaiNone(biasa terjadi pada akhir sesi bursa sebelum penyelesaian data harian Yahoo), sistem secara otomatis mengambil harga dari metadataregularMarketPricesebagai pengisi cadangan agar data lilin hari aktif tidak terbuang. - Komputasi Berbasis Hari Bursa Aktif (
active_days): Seluruh metrik rata-rata harian (ATR 14, ADR 20, Volume 20, dan Vol Pengali 1D/20D) dihitung secara eksklusif menggunakan barisan hari perdagangan bursa aktif (volume > 0atau lilin aktif hari ini). Hal ini membuang lilin-lilin kosong hari libur yang sesekali disisipkan Yahoo Finance, sehingga rata-rata pergerakan tidak terseret turun secara salah.
Mengukur kecepatan dan perubahan momentum pergerakan harga:
Mengukur tingkat volatilitas harian saham secara persentase terhadap harga saham saat ini, sehingga saham berharga Rp100 dan Rp10.000 dapat dibandingkan secara adil:
Mengukur tingkat keaktifan (aktivitas intraday) murni tanpa dipengaruhi oleh celah harga buka (gaps):
Metrik likuiditas yang menghitung jumlah nilai transaksi Rupiah yang dibutuhkan untuk menggerakkan harga saham sebesar 1% di pasar:
pct1today: Nilai transaksi 1% pada hari penutupan terakhir.pct120d: Rata-rata 20 hari dari nilai transaksi 1% untuk mengukur likuiditas struktural.
4. Fitur UI Interaktif & Fitur Tersembunyi (Hidden UI)
Dashboard premium Skriner memuat komponen interaktif yang dirancang untuk menjaga kesederhanaan tampilan luar sekaligus menyajikan detail mendalam secara instan:
- Tooltip Sumber Data Terintegrasi:
Mengarahkan kursor (hover) atau mengetuk status
"Data versi"atau"Kabar versi"di header akan menampilkan rincian data satelit: status sambungan database, waktu pembaruan IDX GET API, riwayat crawler media, dan seluruh atribusi dependensi visual. - Slide-Out Laci Indikator Saham: Setiap kartu emiten memiliki ikon panah detail. Ketika diketuk, kartu akan meluas ke bawah dan memunculkan status neon-green ceklis indikator EMA, SMA, dan VMA yang sedang aktif untuk emiten tersebut.
- Popup Modal Riwayat Kabar Efek:
Jika emiten memiliki lebih dari 1 pengumuman, mengeklik tautan
+ Lihat x Kabar Lainnyaakan memicu modal blur latar belakang (backdrop glassmorphism) berisi daftar seluruh kabar korporat harian lengkap dengan ringkasan isi pengumuman dan tautan PDF aslinya. - Respon Cepat Filter Summary Bar:
Setiap kali filter aktif, barisan pil filter akan meluncur di bawah kontrol utama. Pengguna dapat menghapus filter tertentu dengan mengeklik tombol silang
(X)pada pil tersebut atau mereset seluruh filter sekaligus lewat tombol"Reset All". - Kalkulator Lot (Money Management Simulator):
Setiap kartu saham memiliki tombol
"Kalkulator Lot". Jika diklik, ia akan menampilkan modal simulator kalkulator lot yang default ke Stop Loss Manual (dengan pilihan ATR sebagai alternatif). Slider persentase Stop Loss manual dapat diatur dalam kelipatan bulat 1% (bukan desimal) untuk kenyamanan perhitungan posisi lot maksimal, dana bersih (termasuk fee beli/jual), dan level target profit 1R hingga 6R. - Mode Aksesibilitas Khusus (Accessibility Toggle): Melalui tombol ikon mata di header, pengguna dapat mengaktifkan Mode Aksesibilitas. Mode ini mengaktifkan style kontras tinggi dan border solid pada kartu grid saham. Secara khusus, semua garis pembatas horizontal (border) di dalam kartu grid saham secara default disembunyikan dan hanya akan muncul saat Mode Aksesibilitas ini diaktifkan.
- Default Tema Light Mode: Dashboard sekarang secara default di-load menggunakan Light Mode (default theme light, dark mode nonaktif secara bawaan) demi kenyamanan pembacaan retro archive ala koran warm paper. Pengguna tetap dapat mengganti ke tema gelap secara manual lewat tombol ikon lingkaran/bulan di header.
- Visualisasi Jaring Gurita UBO (Force Graph): Tombol "Relasi" pada bagian Kepemilikan akan membuka modal visualisasi interaktif (D3 Force Graph). Grafik ini murni berfokus pada ekosistem UBO (Ultimate Beneficial Owner), di mana ia hanya akan menarik saham-saham lain ke dalam grafik jika saham tersebut memiliki UBO yang sama (ditandai dengan ikon mahkota kuning).
- Logo Emiten Terintegrasi: Dashboard secara otomatis menarik dan menampilkan logo resolusi tinggi dari masing-masing emiten (bersumber dari Stockbit) di sebelah nama ticker pada Stock Card untuk mempermudah identifikasi visual dengan cepat.
Sistem Skriner mengklasifikasikan setiap pengumuman keterbukaan informasi emiten ke dalam 10 Kategori Terintegrasi yang dirancang dengan menggabungkan dua pendekatan:
- Pendekatan Formal (Regulasi OJK/BEI): Berdasarkan klasifikasi resmi Peraturan Otoritas Jasa Keuangan (OJK) dan Peraturan Bursa Efek Indonesia (BEI), termasuk POJK No. 31/POJK.04/2015 tentang Keterbukaan Informasi Fakta Material, POJK No. 29/POJK.04/2016 tentang Laporan Keuangan Berkala, dan Peraturan Pencatatan BEI I-A serta II-A.
- Pendekatan Praktis (Klasifikasi Scraper): Menyesuaikan kategori formal dengan kebutuhan skrining dan penyaringan visual pada dashboard, mengeliminasi tumpang tindih (overlap) antar-kategori agar setiap pengumuman hanya masuk ke satu kategori tunggal.
Analisis lengkap mengenai resolusi tumpang tindih, sinergi antar-kategori, serta landasan hukum untuk setiap kategori didokumentasikan pada berkas riset internal studi_keterbukaan_informasi.md.
| No. | Kategori | Label Sistem | Deskripsi Ringkas | Landasan Regulasi |
|---|---|---|---|---|
| 1 | Kinerja Keuangan & Laporan Berkala | Kinerja Keuangan & Laporan Berkala |
Laporan keuangan tahunan/kuartalan, laba/rugi bersih | POJK No. 29/POJK.04/2016 |
| 2 | Aksi Korporasi & Dividen | Aksi Korporasi & Dividen |
RUPS, dividen, stock split, rights issue, waran | Ketentuan RUPS OJK & Peraturan Aksi Korporasi BEI |
| 3 | Insider Activity & Buyback | Insider Activity & Buyback |
Transaksi saham direksi/komisaris, share buyback | POJK No. 11/POJK.04/2017 |
| 4 | Ekspansi & Kontrak Bisnis | Ekspansi & Kontrak Bisnis |
Tender, akuisisi, MoU, joint venture, investasi baru | POJK No. 31/POJK.04/2015 (Fakta Material - Operasional) |
| 5 | Peringatan Regulasi & Suspensi | Peringatan Regulasi & Suspensi |
Suspensi, UMA, sanksi, notasi khusus (E/L/M/X) | Peraturan Perdagangan BEI II-A |
| 6 | Status Listing & Papan Pencatatan | Status Listing & Papan Pencatatan |
IPO, delisting, perpindahan papan, registrasi pemegang efek (LBRE) | Peraturan Pencatatan BEI I-A |
| 7 | Penerbitan Utang & Pembiayaan | Penerbitan Utang & Pembiayaan |
Obligasi, sukuk, credit rating, pembayaran kupon | Peraturan BEI EBUS |
| 8 | Sengketa Hukum & Kepailitan | Sengketa Hukum & Kepailitan |
Gugatan, PKPU, pailit, investigasi hukum | POJK No. 31/POJK.04/2015 (Fakta Material - Hukum) |
| 9 | Laporan Sektoral & Eksplorasi | Laporan Sektoral & Eksplorasi |
Eksplorasi tambang/migas bulanan, DMO batubara | Ketentuan Pelaporan Khusus Sektoral BEI |
| 10 | Keberlanjutan & ESG | Keberlanjutan & ESG |
Sustainability report, CSR, emisi karbon, SRI-KEHATI | POJK No. 51/POJK.03/2017 |
Pengumuman yang tidak cocok dengan kata kunci kategori manapun akan diklasifikasikan sebagai Lain-lain / Umum.
Klasifikasi dilakukan secara otomatis oleh fungsi classify_announcement_category(title, summary) di skriner_sync.py menggunakan metode pencocokan kata kunci (keyword matching) terhadap gabungan teks judul dan ringkasan pengumuman:
# Contoh: Kategori "Aksi Korporasi & Dividen" cocok jika teks mengandung salah satu kata kunci:
keywords = ["dividen", "rups", "rupslb", "aksi korporasi", "stock split",
"right issue", "rights issue", "saham bonus", "waran", "mesop", "esop"]Urutan Prioritas Pencocokan: Kategori dievaluasi secara berurutan (1-10) dengan short-circuit—pengumuman yang cocok pada kategori lebih awal tidak akan dievaluasi ulang untuk kategori berikutnya. Kategori Keberlanjutan & ESG sengaja dievaluasi paling awal untuk menghindari false positive terhadap kata kunci yang sering muncul di kategori lain (misal, "lingkungan" yang bisa bermakna "lingkungan bisnis").
Penanganan Khusus: Pengumuman yang mengandung kata "registrasi pemegang" pada aturan Insider Activity secara eksplisit dialihkan ke kategori Status Listing & Papan Pencatatan, karena laporan "registrasi pemegang efek" (LBRE) bersifat kepatuhan regulasi pencatatan, bukan transaksi orang dalam.
Widget visualisasi volatilitas (Price Volatility Range Bar) pada setiap kartu emiten dirancang berdasarkan studi teknis mendalam tentang relasi fungsional antara Average True Range (ATR%) dan Average Daily Range (ADR%). Studi lengkap meliputi pemodelan matematika, perbandingan karakteristik, konsep Gap Risk, dan implementasi fraksi harga BEI didokumentasikan pada berkas riset internal studi_atr_adr.md.
Perbedaan Fundamental:
- ATR% (14 hari) — mengukur volatilitas total termasuk gap pembukaan pasar (celah harga antara penutupan kemarin dan pembukaan hari ini). Sensitif terhadap berita global overnight.
- ADR% (20 hari) — mengukur rentang pergerakan intraday murni (high - low) tanpa memperhitungkan gap. Mengukur aktivitas jam perdagangan aktif.
- Gap Risk = ATR% − ADR% — selisih keduanya mengukur risiko celah harga pembukaan.
Sistem Skriner mengklasifikasikan volatilitas saham menjadi tiga tingkat berdasarkan nilai ATR% dengan ambang batas berikut:
| Label Visual | Rentang ATR% | Warna | Justifikasi |
|---|---|---|---|
| Rendah | < 2.0% | 🟢 Hijau (--color-accent-green) |
Saham blue chip berkapitalisasi besar dengan pergerakan harga stabil dan terprediksi. Cocok untuk investor konservatif. Contoh tipikal: BBCA (~1.8%), BBRI (~1.9%). |
| Sedang | 2.0% – 5.0% | 🟡 Emas (--color-accent-gold) |
Mayoritas saham lapis kedua dan menengah. Menawarkan keseimbangan antara potensi keuntungan dan risiko yang terkelola. |
| Tinggi | > 5.0% | 🔴 Merah (--color-accent-red) |
Saham bervolatilitas ekstrem—sering kali saham lapis ketiga, saham spekulatif, atau emiten dengan kapitalisasi kecil. Memerlukan manajemen risiko ketat. Contoh tipikal: GOTO (~6.5%). |
Alasan Pemilihan Ambang Batas:
- 2.0% sebagai batas bawah "Sedang" dipilih karena saham-saham indeks acuan utama Indonesia (LQ45, KOMPAS100) umumnya memiliki ATR% di bawah 2%, menjadikannya tolok ukur pasar yang stabil.
- 5.0% sebagai batas bawah "Tinggi" dipilih karena saham dengan pergerakan harian rata-rata lebih dari 5% dari harga penutupan menunjukkan fluktuasi yang signifikan secara statistik—potensi pergerakan Rp500 per Rp10.000 saham per hari, yang mengindikasikan risiko tinggi bagi investor ritel.
Widget ditampilkan langsung di bawah informasi harga pada setiap kartu emiten dengan struktur horizontal:
[ Price - ATR ] <===( [ Price - ADR ] <=== [ Price ] ===> [ Price + ADR ] )====> [ Price + ATR ]
|<--- ATR- --->| |<--- ADR- --->| (Tengah) |<--- ADR+ --->| |<--- ATR+ --->|
- Pita Luar Merah (ATR Band): Rentang volatilitas total—batas ekstrem pergerakan harga harian.
- Pita Dalam Cyan (ADR Band): Rentang intraday normal—area pergerakan harga aktif jam bursa.
- Pin Titik Tengah: Posisi harga penutupan terakhir sebagai jangkar visual.
Semua harga proyeksi nominal Rupiah di ujung pita dibulatkan secara otomatis menggunakan fungsi roundToIdxFraction() sesuai Fraksi Harga Resmi BEI (tick size: Rp1/2/5/10/25 tergantung rentang harga), sehingga angka yang ditampilkan selalu merupakan harga yang sah untuk diinput sebagai order beli/jual di sistem perdagangan bursa.
Jika sebuah saham tidak memiliki data ATR% atau ADR% yang valid (bernilai 0, null, atau saham dalam status suspensi), widget menampilkan status abu-abu bertuliskan "Suspensi/Stagnan" dengan opacity rendah dan label "Data tidak tersedia", mencegah pengguna membuat keputusan trading berdasarkan data volatilitas yang tidak representatif.
Untuk menjaga kesegaran data tanpa memerlukan server VPS berbayar, sistem ini menggunakan GitHub Actions untuk menjalankan pipa pembaruan secara otomatis. Eksekusi dibagi menjadi 6 workflow terpisah yang masing-masing dapat dipicu manual via workflow_dispatch:
- Jadwal Cron: Tidak ada —
workflow_dispatchONLY, dipicu oleh Apple Shortcut di iPhone owner (~17:15 WIB). Tidak ada cron GitHub Actions sama sekali untuk workflow ini. - Mode: Teknikal (Yahoo Finance 2Y Chart + Indikator), tanpa refresh Kabar/Keterbukaan
- Perintah:
python scraper/fetch_metadata.py→ publishdata/ownership_ihsg_tags.*→python scripts/scrape_yahoofinance.py - Fungsi: Dipicu sesaat setelah bursa BEI ditutup, memperbarui katalog metadata resmi IDX terlebih dahulu, lalu menghitung seluruh indikator teknikal (RSI, MACD, 27 MA booleans, ATR%, ADR%, Vol Pengali, avgValue20) dari data chart 2 tahun Yahoo Finance. Pada hari libur bursa/volume BBCA
0, indikator lama dipreservasi. Jika iPhone owner berhenti memicu shortcut ini, teknikal berhenti diperbarui tanpa peringatan di status workflow.
- Jadwal Cron: Tidak ada —
workflow_dispatchONLY, dipicu oleh Apple Shortcut di iPhone owner setiap jam (24/7 termasuk weekend/libur). Tidak ada cron GitHub Actions. - Mode: Ringan (Hanya Berita & Kabar, tanpa Yahoo Finance)
- Perintah:
python scripts/scrape_kabar_keterbukaan.py - Fungsi: Memperbarui pengumuman Keterbukaan Informasi IDX dan artikel portal berita utama. Seluruh indikator teknikal dari sinkronisasi terakhir dipreservasi utuh.
- Jadwal Cron:
21 18 * * 0(Mingguan, Minggu 18:21 UTC / Senin 01:21 WIB), plus manual viaworkflow_dispatchdengan inputticker,limit, danrefresh_technical. - Mode: Quota-safe. Cron mingguan otomatis hanya menjalankan
scripts/parse_idx_freefloat_status_pdf.py(bulk IDX status PDF) lalu republish metadata; scrape Lapbul per-emiten (scripts/scrape_free_float.py --ticker/--limit) hanya berjalan saat dispatch manual mengisi input tersebut — tidak ada all-emiten scrape otomatis. - Perintah murah:
python scripts/parse_idx_freefloat_status_pdf.py→ (dispatch only)python scripts/scrape_free_float.py --ticker BOLT→python scraper/fetch_metadata.py→ publishdata/ownership_ihsg_tags.*.refresh_technical=truehanya dipakai jika ingin lanjut menjalankan Yahoo technical sync. - Fungsi: Memperbarui free-float resmi dari bulk status IDX setiap minggu tanpa menjalankan crawl ratusan PDF Lapbul secara otomatis. Refresh Lapbul per-ticker hanya dilakukan manual saat benar-benar dibutuhkan.
- Jadwal Cron:
0 6 5 * *(Bulanan, tanggal 5 pukul 06:00 UTC / 13:00 WIB), plus manual viaworkflow_dispatch— dispatch ini tidak memiliki input apa pun (tidak ada opsi untuk memilih ticker atau membatasi scope governance). - Mode: Full ownership + governance refresh setiap bulan — tidak bergantung pada repo lain. Setiap run (cron maupun manual) menjalankan
fetch_1pct.py(±25 menit) lalufetch_lapbul_full.pyall-emiten penuh (±120 menit) tanpa opsi skip. - Perintah:
python scraper/fetch_1pct.py→python scraper/fetch_lapbul_full.py(full, semua emiten) → copy_if_exists kedata/ownership_*. - Fungsi: Mengambil dokumen resmi Pemegang Saham di atas 1% sebagai tabel kepemilikan utama dan menambahkan governance dari Lapbul (
PG,UBO, direksi/komisaris) untuk seluruh emiten setiap bulan. Metadata/ISSI sengaja dikelola oleh workflow metadata/technical/freefloat agar update ISSI tidak tertimpa oleh refresh ownership bulanan. - Output scraper native:
docs/data/latest.json,docs/data/latest.csv,docs/data/latest_pengendali.csv,docs/data/latest_ubo.csv,docs/data/summary.json,docs/data/summary_1pct.json,docs/data/summary_lapbul.json. - Output dashboard: workflow memublikasikan file tersebut ke
data/ownership_*, yang kemudian dimuat langsung oleh Next.js client di browser. - Resiliensi CI: karena IP GitHub Actions kadang diblokir IDX/Cloudflare, snapshot
docs/data/dandata/ownership_*disimpan di repo. Jika scrape gagal tetapi snapshot lama tersedia, workflow dapat mempertahankan data terakhir alih-alih membuat dashboard kosong. Job timeout 150 menit.
- Jadwal Cron:
11 18 * * 0(Mingguan, Minggu 18:11 UTC / Senin 01:11 WIB), plus manual viaworkflow_dispatchdan triggerpushpada path terkait (fetch_metadata.py,ihsg_tags/**,requirements.txt, file workflow itu sendiri). - Mode: Metadata-only refresh untuk katalog emiten resmi.
- Perintah:
python scraper/fetch_metadata.py→ publishdocs/data/ihsg_tags.*dandata/ownership_ihsg_tags.*. - Fungsi: Menjaga
name,sector,papan,ipo_date,ISSI,LQ45, danKOMPAS100tetap mengikuti sumber resmi IDX/DES/index tanpa mengandalkan CSV/XLSX statis.
- Jadwal Cron:
30 11 * * *(Harian, pukul 18:30 WIB / 11:30 UTC) - Mode: Incremental daily scrape (past 14 hari)
- Perintah:
python scraper/fetch_lapbul_full.py --days 14→python scripts/scrape_free_float.py --days 14→python scripts/skriner_sync.py --skip-yfinance --skip-disclosures - Fungsi: Memindai keterbukaan informasi LBRE dalam 14 hari terakhir untuk mengekstrak data Free Float dan kepemilikan/governance (
PG/pengendali,UBO/penerima manfaat akhir). Melakukan penggabungan kumulatif pada database CSV/JSON di repositori dan mempublikasikannya secara otomatis. ⚠️ Isu diketahui (belum selesai, sejak 14 Juni 2026): scraping LBRE/Lapbul workflow ini berhenti menghasilkan commit baru. Hipotesis utama:sync_daily_lapbul.ymltidak memiliki langkah instalasi Playwright Chromium (berbeda darisync_news.yml), sehingga fallback headless browser saat IDX memblokir discovery gagal senyap dan guardrail snapshot exit 0 tanpa data baru. Detail investigasi dan tindakan pemilik yang diperlukan ada diBUGS_AND_FIXES_2026-07-12.md.
- Jadwal Cron:
0 1,5,10 * * *(Harian, pukul 08:00, 12:00, dan 17:00 WIB) - Mode: Full Skriner Data Update (Technical Indicators, Disclosures, News, IHSG, and Sector Performance Indices)
- Perintah:
python scripts/skriner_sync.py - Fungsi: Alur kerja pembaruan utama bursa harian yang menyinkronkan seluruh database skriner. Ini menghitung indikator teknikal dari Yahoo Finance (jika market open), mengumpulkan keterbukaan informasi IDX serta portal berita, mengambil data chart IHSG beserta nilai transaksi harian resmi (Nilai Transaksi) dari API IDX, memperbarui data sektoral, menyalin data ke folder Next.js, dan melakukan komit/dorong ke repositori secara otomatis (dengan izin
contents: write) untuk memicu build Vercel secara mandiri di cloud.
Setiap workflow dilengkapi dengan perlindungan penyerahan berkas otomatis:
- Perintah eksekusi memeriksa perubahan database lokal menggunakan
git diff --cached --quietsebelum membuat komit baru. - Hasil: Komit ke repositori hanya dikirim jika ada perubahan data aktual. Selama periode sepi, alur kerja selesai tanpa komit sampah, menjaga histori repositori bersih dan meminimalkan rebuild Vercel.
Seluruh modul pengambilan data backend scraper Skriner dirancang menggunakan koneksi aman ke sumber-sumber tepercaya berikut untuk memastikan integritas data bursa efek Indonesia:
Data persentase free float (saham yang beredar dan dimiliki publik) merupakan metrik kepatuhan penting yang diawasi oleh Bursa Efek Indonesia. Skriner mengambil data ini dari sumber resmi IDX dengan hirarki prioritas:
| Prioritas | Sumber Data | Keterangan |
|---|---|---|
| 1 (Utama) | Laporan Bulanan Registrasi Pemegang Efek (LBRE/Lapbul) — data/free_float_tracker.json |
Data per-emiten yang diekstrak menggunakan parser PDF dari keterbukaan informasi bulanan. Jika tersedia pada tanggal/bulan berapa pun, data ini langsung digunakan sebagai sumber utama. |
| 2 (Fallback) | Bulk IDX Status Free Float — data/idx_free_float_status.json |
Laporan snapshot bulk resmi dari pengumuman IDX “Status Pemenuhan Kewajiban Jumlah Saham Free Float dan Jumlah Pemegang Saham”. Digunakan sebagai fallback jika data LBRE untuk emiten terkait belum tersedia di tracker (default merujuk ke pengumuman bulk status per 31 Maret 2026). |
API Sumber LBRE:
- Endpoint:
https://www.idx.co.id/primary/ListedCompany/GetAnnouncement - Metode Discovery: warmup ke halaman keterbukaan informasi IDX, ambil halaman pengumuman tanpa keyword server-side, lalu filter client-side untuk
Laporan Bulanan Registrasi Pemegang Efekagar tidak kehilangan laporan akibat filter API yang tidak konsisten. - Ekstraksi Free Float: tidak membutuhkan Excel indeks. Nilai diambil dari PDF resmi per-emiten dengan
pdfplumberdan disimpan bersama evidence (method,evidence,page,pdf_attachments).
- Data Historis Transaksi & Lilin Harga: Disediakan oleh Yahoo Finance API dengan kode akhiran bursa Jakarta (
.JK), rentang data 2 tahun (range=2y), timeout 10 detik.- Endpoint Uji Crumb: fc.yahoo.com & getcrumb query2
- Endpoint Grafik Saham: query1.finance.yahoo.com/v8/finance/chart/
- Mesin Indikator Mandiri: Seluruh indikator teknikal (RSI, MACD, EMA/SMA/VMA booleans, ATR%, ADR%, Vol Pengali, avgValue20, shortEmaNearestDistPct, pullbackBreakoutSignal) dihitung langsung dari data chart Yahoo Finance tanpa dependensi database eksternal.
Database Indikator Pra-Komputasi: Dependensi screenerzero telah dihapus sepenuhnya sejak 31 Mei 2026.
- Sumber Resmi: Diperoleh langsung dari Bursa Efek Indonesia (IDX).
- Portal Halaman: Keterbukaan Informasi IDX
- Jalur Get API Announcement: primary/ListedCompany/GetAnnouncement
- Arsitektur WAF-Bypass (Anti-Blokir Cloudflare): Untuk memastikan perayapan stabil di lingkungan datacenter seperti GitHub Actions, scraper dilengkapi dengan strategi bypass multi-layer:
- Rotasi TLS Fingerprint (
curl_cffi): Memutar identitas impersonasi browser (chrome124,safari17_0,chrome120) secara dinamis sekaligus menghapus header statis yang berkonflik agar anomali JA3 tidak terdeteksi oleh Cloudflare. - Playwright Headless Fallback: Jika
curl_cffimenerima 3 kali respons403 Forbiddenakibat JavaScript Turnstile Challenge, scraper akan menyalakan peramban Chromium nirkepala lengkap denganplaywright-stealth. Peramban ini akan mengunjungi beranda IDX untuk menyelesikan tantangan Cloudflare secara otomatis, lalu mengekstrak data JSON langsung dari DOM halaman. Integrasi ini berjalan mulus dan sepenuhnya self-contained pada pelari GitHub.
- Rotasi TLS Fingerprint (
- Sumber resmi utama kepemilikan: Dokumen KSEI via IDX "Pemegang Saham di atas 1%", diekstrak oleh
scraper/fetch_1pct.pykedocs/data/latest.*lalu dipublikasikan sebagaidata/ownership_latest.*. - Sumber governance: Laporan Bulanan Registrasi Pemegang Efek per emiten, diekstrak oleh
scraper/fetch_lapbul_full.pyuntuk menandaiPG/pengendali danUBO/pemilik manfaat akhir. - Sumber metadata resmi: endpoint/download IDX/DES/index konstituen melalui
scraper/fetch_metadata.py, disimpan sebagaidocs/data/ihsg_tags.*dan dipublikasikan kedata/ownership_ihsg_tags.*. Snapshot ini menjadi katalog utamascripts/skriner_sync.py; CSV statis hanya fallback/supplement. - Catatan kualitas: data kepemilikan >1% tetap dipisahkan dari
data/skriner_data.json; dashboard menggabungkan layer ini di browser berdasarkan kode ticker.
Temuan retrain scraper 1% — 02 Juni 2026 11:50:22:
Pada update KSEI terbaru, halaman keterbukaan informasi IDX untuk keyword semua emiten menampilkan dua headline yang sangat mirip pada hari yang sama:
| Waktu IDX | Headline | Attachment data | Status |
|---|---|---|---|
| 02 Juni 2026 14:51:29 | Pemegang Saham di atas 5% (KSEI) [Semua Emiten Saham ] |
20260602_Semua Emiten Saham_Pengumuman Bursa_32096123_lamp1.pdf |
Jangan dipakai untuk dashboard ownership utama |
| 02 Juni 2026 11:50:22 | Pemegang Saham di atas 1% (KSEI) [Semua Emiten Saham ] |
20260602_Semua Emiten Saham_Pengumuman Bursa_32096035_lamp1.pdf |
Sumber benar untuk ownership_latest.* |
Perbaikan scraper/fetch_1pct.py dibuat agar tidak lagi memilih hasil pertama/terbaru secara buta. Jalur discovery sekarang memakai keyword website-style semua emiten, lalu memvalidasi JudulPengumuman secara client-side: harus cocok Pemegang Saham di atas 1% (KSEI) dan eksplisit menolak Pemegang Saham di atas 5% (KSEI). Fallback no-keyword tetap ada, tetapi tidak boleh menjadi satu-satunya jalur karena pada Juni 2026 response no-keyword bisa menemukan bulk 5% namun melewatkan bulk 1%.
PDF lampiran Juni 2026 juga berubah format: pdfplumber.extract_tables() mengembalikan 0 tabel pada file 33 halaman tersebut. Scraper kini memiliki fallback berbasis extract_words() dan posisi kolom tetap untuk membaca text layer yang token awalnya tergabung, misalnya 29-May-2026ALTO. Verifikasi lokal atas lampiran 32096035_lamp1.pdf menghasilkan 7.160 baris, 956 ticker, 5.167 investor, dengan data_date snapshot 20260602 dan tanggal data isi PDF 29-May-2026.
- RSS Ringkasan Pasar: CNBC Indonesia Market RSS Feed & CNBC Indonesia Latest RSS
- Berita Investasi Saham: Kontan Investasi
- Analisis Finansial & Emiten: Bisnis Indonesia Market
- Kabar Saham Harian: IDX Channel Market News
- Profil & Data Pengumuman Terintegrasi: IDN Financials
- Kabar pasar modal tambahan: Bloomberg Technoz, EmitenNews, dan kanal finansial Katadata
Anda dapat mengkloning proyek ini dan menjalankannya secara lokal di komputer Anda:
-
Instalasi Dependensi:
Pastikan Python
$\ge 3.9$ telah terinstal, lalu pasang pustaka pendukung:pip install -r requirements.txt
-
Sinkronisasi Data Free Float (LBRE):
# Murah/aman: satu ticker python scripts/scrape_free_float.py --ticker BOLT # Full all-emiten hanya jalankan lokal/manual saat benar-benar perlu python scripts/scrape_free_float.py
-
Sinkronisasi Kepemilikan Resmi IDX/KSEI:
Hasil native scraper tersimpan di
python scraper/fetch_1pct.py # Murah/aman: governance satu ticker python scraper/fetch_lapbul_full.py --ticker BOLT # Full all-emiten governance hanya jalankan lokal/manual saat benar-benar perlu python scraper/fetch_lapbul_full.py
docs/data/; dashboard memakai salinandata/ownership_*yang dipublikasikan oleh workflowsync_ownership.yml. Untuk menjalankan lokal manual setelah scraper, salin filedocs/data/latest*,latest_pengendali.csv,latest_ubo.csv, dan summary ownership ke namadata/ownership_*sesuai workflow. Metadata/ISSI dijalankan terpisah melaluipython scraper/fetch_metadata.pyatau workflow metadata. -
Sinkronisasi Database Penuh (Yahoo Finance + Berita — Default):
python scripts/skriner_sync.py
-
Sinkronisasi Ringan (Hanya Berita, Tanpa Yahoo Finance):
python scripts/skriner_sync.py --skip-yfinance
-
Menjalankan Server Web Lokal:
Buka penjelajah web Anda di alamat
python -m http.server 8799 --bind 127.0.0.1
http://127.0.0.1:8799/index.html.
Jika Anda ingin mem-porting kode ini ke kerangka kerja modern lainnya (misalnya React, Svelte, Next.js, atau Nuxt.js) menggunakan model AI lain:
-
Logika Pencarian: Harap pertahankan logika pencarian multi-ticker yang memisahkan spasi agar pengguna dapat mencari beberapa kode emiten sekaligus (contoh:
GOTO BBCA BBNI). - Relasi Filter: Filter dropdown Indeks bersifat saling eksklusif (exclusive), Sektor dan Papan bersifat kumulatif (cumulative), sedangkan Moving Averages bersifat AND (semua MA yang dicentang harus terpenuhi). Filter Transaksi 1% 1D bersifat OR (mencocokkan rentang apa saja yang dipilih).
-
Desain Glassmorphism: Gunakan kombinasi warna HSL semi-transparan dengan tingkat keburaman latar belakang (
backdrop-filter: blur(12px)) untuk mempertahankan estetika premium. Pada layar ponsel$\le 768\text{px}$ , pastikan pembungkus filter dropdown diubah menjadiflex-direction: columnagar bertumpuk rapi ke bawah.
Seluruh tampilan tanggal dan waktu di situs Skriner selalu mengacu ke zona waktu Asia/Jakarta (WIB, UTC+7), terlepas dari zona waktu peramban pengunjung. Implementasi menggunakan Intl.DateTimeFormat dengan parameter timeZone: 'Asia/Jakarta' yang didukung oleh seluruh peramban modern.
Format tampilan standar: dd MMM yyyy HH.mm WIB (contoh: 01 Jun 2026 17.00 WIB)
formatDateTimeWIB(): MenggunakangetJakartaParts()yang memanfaatkanIntl.DateTimeFormatuntuk mengekstrak komponen tanggal secara eksplisit dalam zona waktu Jakarta.formatListingDate(): Tanggal pencatatan emiten yang di-parse melalui objekDatejuga dikonversi ke zona waktu Jakarta sebelum diformat.- Logika Fallback Timestamp: Pengecekan jam teknikal (apakah sudah melewati jam 17.00 WIB) menggunakan komponen jam Jakarta, bukan jam lokal peramban.
Untuk mengamankan dan mengoptimalkan pengiriman kode ke peramban pengguna, Skriner memanfaatkan fitur bawaan Next.js:
- Minifikasi & Optimasi Kode Otomatis: Next.js (menggunakan SWC/Turbopack) secara otomatis melakukan minifikasi, pemecahan bundel (code splitting), dan pembersihan kode mati (dead-code elimination) saat proses
npm run builddijalankan. Hal ini menghasilkan berkas chunk JS yang sulit direkayasa balik secara kasual. - Penerapan di Vercel: Proses kompilasi dijalankan langsung di server Vercel, memastikan bahwa repositori GitHub tetap aman dan hanya kode teroptimasi yang dipublikasikan ke publik.
- Strategi Repositori Privat + Hosting Publik: Repositori GitHub dapat tetap private, sedangkan Vercel hanya menyajikan aset terkompilasi statis yang dihasilkan oleh Next.js.
Catatan: Proteksi pada sisi pengguna bersifat pencegahan (deterrent). Pengguna teknis yang sangat termotivasi tetap berpotensi merekayasa balik kode obfuskasi, namun lapisan perlindungan ini secara efektif mencegah replikasi kasual tanpa mengorbankan pengalaman pengguna dashboard.
Skriner dikembangkan dengan memanfaatkan kontribusi kode dan terinspirasi dari proyek sumber terbuka (open source) utama berikut:
- jiprastyo/screenerzero:
- Peran: Proyek inspirasi dasar dan referensi formula teknikal awal.
Dependensi data teknikal aktif telah dihapus sepenuhnya sejak 31 Mei 2026.Seluruh indikator kini dihitung mandiri oleh mesin kalkulasi self-contained diskriner_sync.pymenggunakan data chart 2 tahun Yahoo Finance.
- Peran: Proyek inspirasi dasar dan referensi formula teknikal awal.
- jiprastyo/skriner:
- Peran: Repositori aktif untuk website Skriner Berita & Teknikal 1D. Proyek ini memperkenalkan mesin indikator teknikal mandiri penuh (RSI, MACD, 27 MA booleans), antarmuka visual glassmorphism SPA, filter multi-dimensi, metrik Vol Pengali kebal hari libur, rangkuman korporat bertenaga Gemini AI, dan 4 workflow GitHub Actions terpisah.
- Scraper ownership resmi IDX/KSEI (
scraper/):- Peran: Modul kepemilikan yang kini sudah menjadi bagian self-contained dari repo ini. Modul ini membawa tabel pemegang saham >1%, tag pengendali (
PG), pemilik manfaat akhir (UBO), dan metadata resmi IDX/DES/index ke dashboard utama melalui layerdata/ownership_*.
- Peran: Modul kepemilikan yang kini sudah menjadi bagian self-contained dari repo ini. Modul ini membawa tabel pemegang saham >1%, tag pengendali (
Dokumentasi Sistem Terverifikasi dan Diperbarui secara Resmi pada: 12 Juli 2026
Mengingat agresivitas proteksi WAF (Web Application Firewall) seperti Cloudflare pada website IDX yang sering memblokir IP Datacenter (seperti GitHub Actions), arsitektur pengambilan data (scraping) repositori ini dirancang dengan beberapa lapis fallback dan guardrail ketat:
- Layer 1: TLS Impersonation (curl_cffi) Scraper utama menggunakan paket curl_cffi untuk memalsukan TLS fingerprint browser asli (Chrome/Safari) sehingga anomali JA3 tidak terdeteksi oleh Cloudflare.
- Layer 2: Playwright Headless Fallback Jika metode curl_cffi tetap menerima 3 kali respons 403 Forbidden (akibat tantangan JavaScript Turnstile), scraper akan secara otomatis menyalakan headless browser Chromium yang diinjeksi dengan modul playwright-stealth. Browser ini akan memuat halaman beranda IDX untuk mengeksekusi tantangan JS Cloudflare, lalu mengekstrak muatan JSON langsung dari DOM (Document Object Model).
Untuk mencegah hancurnya data live di dashboard saat seluruh scraper diblokir (atau API IDX sedang down), kami menerapkan guardrail ketat:
- Jika scraper mengembalikan data kosong atau gagal total, skrip akan langsung berhenti (exit 0) sebelum menyentuh file JSON output.
- Skrip tidak akan pernah menimpa data/*.json dengan data kosong. Ini memastikan bahwa situs web (Vercel/GitHub Pages) akan terus menyajikan snapshot data terakhir yang ditarik, bukannya layar kosong.
Sebagai solusi optimalisasi mutlak kuota Vercel Free Tier (100 deploy/hari) sekaligus mengatasi kendala akses HTTP 404 pada repositori Private GitHub, repositori ini mengimplementasikan arsitektur Decoupled Data CDN via Next.js Edge Proxy API (Opsi C):
- 1. Optimalisasi Kuota Vercel (Hemat 100% - Zero Automated News Rebuilds)
- Seluruh komit otomatis dari bot GitHub Actions (
sync_news.yml,data_sync.yml,sync_daily_lapbul.yml, dll.) maupun Apple Shortcuts iPhone disuntik tag senyap[skip ci]. - Konfigurasi
vercel.jsondilengkapi regex matching:"ignoreCommand": "git log -1 --pretty=%B | grep -E -i '\\[skip ci|auto-sync|automated data sync|upload raw idx data'". Begitu terdeteksi komit sinkronisasi data otomatis, Vercel membatalkan proses re-build (Exit Code 0), menghemat kuota build frontend agar hanya berjalan saat ada perubahan kode sumber aplikasi.
- Seluruh komit otomatis dari bot GitHub Actions (
- 2. Real-Time 5-Minute Delivery via Next.js Edge Proxy (
/api/cdn/[filename])- Karena repositori GitHub bersifat Private (tautan
raw.githubusercontent.compublik menghasilkan 404), aplikasi frontend memuat seluruh aset JSON (skriner_data.json,market_news.json, dll.) melalui serverless proxy endpoint/api/cdn/[filename]. - Endpoint proxy ini secara aman mengambil data langsung dari GitHub main branch menggunakan Personal Access Token (
GITHUB_CDN_TOKEN) yang disimpan di Environment Variables Vercel. - Vercel Edge Caching: Proxy menyematkan header
Cache-Control: public, s-maxage=300, stale-while-revalidate=60sehingga data di-cache di jaringan Edge Vercel selama 5 menit. Pembaca menerima keterbukaan informasi instan tanpa menunggu siklus build CI/CD 1 jam ataupun menguras batas rate limit API GitHub. - Hybrid Fallback Protection: Jika API eksternal mengalami gangguan, hook (
useStocksData.ts) otomatis mundur mengambil aset cadangan lokal di/data/....
- Karena repositori GitHub bersifat Private (tautan
- 3. Enterprise Handshake Relay (Apple Shortcuts 100% Untouched)
- Pengguna tidak perlu merubah alur kerja Apple Shortcuts di iPhone sama sekali (Mutlak Zero iPhone Touch):
- Shortcut 1 (Pukul
xx.55 WIB): Scrape keterbukaan informasi lokal dari iPhone lalu pushraw_idx.jsondengan[skip ci]. - Shortcut 2 (Pukul
xx.02 WIB): Memicusync_news.ymldi GitHub untuk merayapi 9 portal berita finansial dan mem-push komit ber-tag[skip ci]. Data langsung dapat diakses lewat/api/cdn. - Shortcut 3 (Pukul
17:15 WIB): Memicusync_technical.ymlpasca bursa tutup untuk memperbarui data gabungan Yahoo Finance + IDX: chart YFinance (^JKSE), teknikal ticker, histori sektoral, serta komponen IHSG resmi IDX (Nilai Transaksi dan perubahan IHSG bila ringkasan IDX untuk tanggal terbaru sudah tersedia). Komit akhir bot ini memicu tepat 1x build resmi harian Vercel sebagai jaring pengaman cadangan. - Shortcut 4 (Pukul
~17:25 WIB): Relay IDX-only IHSG rescue. Shortcut membacaupdate_metadata.json; bilaihsg_transaction_sync_ok=false, iPhone mengambilGetIndexSummaryIDX untuk tanggal gap, mengunggahdata/raw_idx_ihsg_summary.json, lalu memicu workflowsync_idx_ihsg_rescue.yml. Rescue ini tidak menjalankan Yahoo lagi — ia hanya menutup gap Nilai Transaksi dari iPhone (IP Indonesia → Cloudflare IDX lolos).
- Shortcut 1 (Pukul
- 📖 Panduan setup lengkap:
docs/apple-shortcuts-setup.md— step-by-step untuk membuat semua 4 Shortcuts di iPhone. ⚠️ Windows Task Scheduler (skriner_scheduler.py) sudah deprecated. Semua trigger sekarang via Apple Shortcuts → GitHub Actions. Filerun_yfinance.batdanrun_news_hourly.bathanya tersisa sebagai referensi.
- Pengguna tidak perlu merubah alur kerja Apple Shortcuts di iPhone sama sekali (Mutlak Zero iPhone Touch):
Yahoo Finance tidak menyimpan grafik riwayat harian untuk indeks sektoral BEI (IDXBASIC.JK, IDXCYCLIC.JK, dll.) melainkan hanya data 1 hari/5 hari terbaru. Agar visualisasi diagram performa sektor di frontend tetap dapat menampilkan histori pergerakan jangka panjang, skrip sinkronisasi backend menerapkan Cumulative History Sync:
- Skrip memuat file
data/sectors_history.jsonyang sudah ada di repositori sebelum melakukan fetch data baru. - Setelah data harga sektor hari ini ditarik, skrip membandingkan tanggal terakhir. Jika terdeteksi hari perdagangan baru, harga hari ini akan di-append ke dalam array grafik histori (maksimal 40 hari).
- Jika dijalankan beberapa kali pada hari yang sama, skrip hanya memperbarui harga penutupan hari ini di elemen terakhir array untuk menghindari duplikasi data.
Untuk menjamin akurasi dan kesegaran data pada kartu IHSG komposit serta persentase perubahan IHSG (ihsgChange) di setiap kartu emiten, frontend (useStocksData.ts) menerapkan arsitektur penggabungan hibrida (hybrid derivation):
- Komposit & Perubahan Harian (
ihsg_chart.json): Harga penutupan harian dan persentase perubahan komposit ditarik dari Yahoo Finance (^JKSE) saat alur kerja Apple Shortcuts--only-yfinancedijalankan (17:15 WIB). Ini memastikan header kartu IHSG dan tag perubahan bursa di kartu saham selalu sinkron dengan tab Kinerja Sektor. - Bar Volume Nilai Transaksi Aktual (
ihsg_transaction_history.json): Karena Yahoo Finance hanya menyediakan volume lembar saham (tidak mencerminkan nilai transaksi Triliun Rupiah), batang volume ditarik langsung dari API resmi BEI (Ringkasan Perdagangan /GetIndexSummary) dan digabungkan secara dinamis berdasarkan pencocokan tanggal.
Note on Continuous Documentation: README ini dan repositori dokumentasi akan selalu diperbarui secara otomatis setiap kali ada penemuan metode scraping baru, guardrail yang berhasil/gagal, maupun perubahan flow arsitektur (seperti arsitektur Cumulative History Sync atau iterasi Apple Shortcut). Dokumentasi bersifat living document.