feat(factor): add energy_irpc (IRPC net margin) as 2nd Thai refiner signal

- new energy_irpc collector parsing IRPC performance-highlights table
  (net profit/EBITDA/ROE margins, latest period 3M26: +10.27%)
- factor energy_irpc_net_margin (sign +1) wired into refining_energy/
  exploration/utilities, extending the energy theme beyond TOP
- scheduler job + dashboard fetch + sources table row (now 9 sources)
- tests: parse (incl paren-negatives), value-key resolution, direction;
  suite 368 OK. Independent review passed: true
- Phase B feasibility: REIC/EPPO/NBTC/PTTEP are JS-rendered or anti-bot
  (recorded deferred in plan); IRPC was the clean server-rendered win
This commit is contained in:
Kunthawat Greethong
2026-08-29 11:13:17 +07:00
parent da671a9ba2
commit 12b34929d7
14 changed files with 309 additions and 24 deletions

File diff suppressed because one or more lines are too long

View File

@@ -5,7 +5,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="theme-color" content="#0b1018" />
<title>SET50 Signal Lab</title>
<script type="module" crossorigin src="/assets/index-eGeNIixN.js"></script>
<script type="module" crossorigin src="/assets/index-Bymd5oSf.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-CUx7tUuk.css">
</head>
<body>

View File

@@ -571,6 +571,7 @@ onMounted(async () => { await loadDashboard(); await Promise.all([loadBacktestRu
<div v-if="theme.id === 'auto_credit' && theme.read.new_car_sales_yoy != null" class="theme-read-value">{{ formatNumber(theme.read.new_car_sales_yoy) }}% YoY ยอดขายรถ</div>
<div v-else-if="theme.id === 'auto_credit' && theme.read.auto_npl_pct != null" class="theme-read-value">NPL {{ formatNumber(theme.read.auto_npl_pct) }}%</div>
<div v-else-if="theme.id === 'refining_energy' && (theme.read.quarterly || theme.read.net_profit)" class="theme-read-value">กำไรสุทธิ TOP (รายไตรมาส)</div>
<div v-else-if="theme.id === 'refining_energy' && theme.read.irpc_net_margin_pct != null" class="theme-read-value">กำไรสุทธิ IRPC {{ formatNumber(theme.read.irpc_net_margin_pct) }}%</div>
<div v-else-if="theme.id === 'tourism'" class="theme-read-value">signal tourism {{ theme.surprise != null ? formatNumber(theme.surprise,2) : '' }}σ</div>
<div v-else-if="theme.id === 'banks' && theme.read.interest_rate_pct != null" class="theme-read-value">ดอกเบี้ย {{ formatNumber(theme.read.interest_rate_pct) }}%</div>
<div v-else-if="theme.id === 'banks' && theme.read.bank_npl_pct != null" class="theme-read-value">NPL ภาคการเงิน {{ formatNumber(theme.read.bank_npl_pct) }}%</div>