I built an AI agent that predicts the next fuel-price hike

Every Indonesian knows the feeling: you pull up to the pump and Pertamax is suddenly Rp800 more than last month. It feels random. It isn't.
Background, why I built this
Sudden fuel-price jumps are stressful precisely because they feel arbitrary. But market-priced fuel (Pertamax, Turbo, Dex) is re-priced on a published formula tied to world oil and the rupiah. If the inputs are public, the surprise is optional, you just have to do the math before Pertamina does. So I turned that math into an agent.
What
BBM Price Predictor, an agent that forecasts the next adjustment for each market-priced fuel: direction (↑/↓/→), the likely date, and an estimated price, with the drivers and a confidence number.
⛽ BBM forecast - effective Jul 2026
Pertamax Turbo (RON 98)
Verdict: ↓ TURUN est ~Rp20,000 (range Rp18,900-21,050)
Now: Rp20,750 → Δ Rp-762
Drivers: world oil + USD/IDR over the pricing window
Confidence:90% (verified Apr-Jun 2026 data)
Here's every market-priced fuel through 2026, the agent tracks them all, and you can see the hikes it has to explain:

World oil spiked from ~28 Feb 2026 (Israel-Iran war). Turbo and Dexlite jumped +48% and +66% on 18 April. Pertamax and Pertamax Green were held through March-May, then leapt +32% on 10 June. Same shock, four different timings, exactly what the model has to untangle.
Why it matters
Market fuels reprice monthly, effective ~the 1st, via a regulated formula: a Singapore fuel benchmark (MOPS) plus margin, converted at USD/IDR, plus tax. That means the next move isn't a coin flip, it's mostly determined by oil and the rupiah over a known window before the announcement. The hike is knowable in advance.
Who it's for
Anyone tired of being ambushed at the pump, and developers who want a clean template for a forecasting agent that turns public signals into a dated, directional call.
When & where
It runs from the command line on free data, any time. Its forecasts target the monthly adjustment date (the 1st), so you get a heads-up roughly a week before Pertamina announces.
How, the method, in detail
The agent is deliberately transparent. Six steps, no black box:
1. Pull the public signal. Two oil futures via Yahoo Finance, RBOB gasoline (RB=F) for the Pertamax grades, Brent (BZ=F) for diesel, plus USD/IDR (IDR=X). Roughly 500 daily closes each, cached locally.
2. Average over the pricing window. Pertamina's formula doesn't react to today's oil, it reflects a trailing window (≈ the 25th of two months ago to the 24th of last month). For each target month the agent averages the oil proxy and the rupiah over that exact window, not the spot price.
3. Convert oil to rupiah-per-litre. oil_idr_per_litre = (proxy_avg_usd_per_barrel / 159) · USDIDR. 159 litres per barrel. This single number is the model's one driver.
4. Fit a transparent line per fuel. price ≈ A · oil_idr_per_litre + B, with A and B found by least-squares on each fuel's verified price history. A captures pass-through + tax; B captures fixed margins. You can read off exactly why a forecast moves.
5. Forecast next month. Run step 2-4 for the upcoming window, compare the estimate to the current price → direction (↑/↓/→), magnitude rounded to Rp50, date = the next adjustment. A Google-Trends + headline overlay ("harga bbm naik") nudges the confidence when the public is already bracing.
6. Backtest, honestly. Replay the model month-by-month vs verified 2026 prices:
| Fuel | Direction hit | Mean error |
|---|---|---|
| Pertamax Turbo (98) | 80% | ~Rp770 |
| Pertamax (92) | 60% | ~Rp800 |
| Pertamax Green (95) | 60% | ~Rp830 |
| Dexlite (51) | 40% | ~Rp1,540 |
The honest finding: the model is strongest where price tracks oil (Turbo caught the +48% April jump), and weakest where Pertamina holds price below the formula for political reasons, Pertamax sat flat at Rp12,300 from March to May while oil was spiking, then snapped +32% on 10 June. A pure-formula model can't see a subsidy decision coming; it flags lower confidence instead of pretending.
Each fuel, its own chart
Model estimate (dashed) vs actual price (solid), with next month's forecast (★ with an error bar):




The data-science, in theory
There's no deep learning here, and that's a deliberate choice, not a shortcut. Here's the reasoning:
- Functional form: affine, by design. Pertamina's regulated price is an affine function of the benchmark, roughly
price = (MOPS + margin)·(1+tax)·kurs. Collapse oil and kurs into one term and the true relationship is a straight line. So the right model is ordinary least-squares (OLS) simple linear regression,y = A·x + B, not because it's the simplest, but because it matches the actual generating process. - Feature engineering. The two raw signals (oil in USD/barrel, USD/IDR) are folded into a single physically-meaningful feature,
x = oil_idr_per_litre = (oil_usd_per_bbl / 159) · kurs. One feature, one coefficient, no multicollinearity, fully interpretable. - Calibration = least squares.
AandBare fit per fuel by minimising squared error over the price history (numpy.polyfit, degree 1).A= pass-through × tax (the slope of how oil reaches the pump);B= fixed distribution + margin (the intercept). - Time-series care: the pricing window. Fuel prices lag oil. Instead of spot oil, each month uses the trailing averaging window the regulator actually uses (~25th of two months prior → 24th of last month). This is the single most important modelling choice, get the window wrong and the whole thing is noise.
- Validation = walk-forward backtest. Score the model month-by-month against verified prices, reporting direction accuracy (did it call ↑/↓ right?) and MAE (rupiah error). Direction matters more than the exact number for a "should I fill up now?" decision.
- Sentiment overlay = z-score. Google-Trends interest in "harga bbm naik" is standardised to a z-score (
(recent − mean) / std); a z above ~1 means the public is bracing, which nudges the confidence on upward calls. - Confidence. Derived from the model's relative error:
100 − 100·MAE/price, clamped to [35, 95], then nudged by the sentiment z-score. It's a self-honesty number, not a guarantee.
Why not a neural net or XGBoost? With n = 6 months per fuel and an affine ground truth, a heavy model would overfit noise and hide why it predicts. Linear regression here is more accurate and fully auditable, you can trace every rupiah of a forecast back to oil, kurs, and two fitted constants. The honest limit is the same one any model hits: when Pertamina holds price below the formula for political reasons (Pertamax flat Mar-May while oil spiked), no formula model sees the subsidy decision coming, so it lowers confidence instead of pretending.
Every parameter, explained
| Parameter | Value / source | Role |
|---|---|---|
RB=F (RBOB gasoline) | Yahoo Finance, daily | Oil proxy for Pertamax/Green/Turbo |
BZ=F (Brent crude) | Yahoo Finance, daily | Oil proxy for Dexlite (diesel) |
IDR=X (USD/IDR) | Yahoo Finance, daily | Rupiah conversion |
| Pricing window | ~25th (M-2) → 24th (M-1) | Which days of oil/kurs feed month M |
159 | litres per barrel | Convert USD/barrel → per-litre |
A, B | fit per fuel (OLS) | Slope (pass-through×tax) + intercept (margin) |
| Direction threshold | ±Rp150 | Below this Δ = "→ flat" |
| Rounding | Rp50 | Forecast rounded to the nearest Rp50 |
| MAE | from backtest | Mean rupiah error → sets the ± range + confidence |
| Trends z-score | (recent−mean)/std | Public-anticipation overlay |
| Confidence | 100−100·MAE/price (+z nudge), 35-95 | Self-reported certainty |
And here's the agent running live, end to end, fetch → backtest → forecast:

And the subsidised ones, how long can it hold?
Pertalite and Biosolar don't follow the formula, their price is a political-fiscal decision, frozen at Rp10,000 and Rp6,800. So the agent doesn't forecast a price; it gauges strain: how expensive the subsidy is to keep, from the gap to the real market price plus the state's fiscal load.

- Pertalite (RON 90) at Rp10,000, a Rp6,250/L gap to Pertamax, 38% of the real price. Strain: HIGH.
- Biosolar (CN 48) at Rp6,800, a Rp16,200/L gap to Dexlite, 70% of the real price. Strain: EXTREME.
The fiscal backdrop is the real story. Energy subsidy + compensation already hit Rp118.7T, 26.6% of the APBN allocation, in Q1 alone, against a 2.9% deficit, with crude above $100 (every +$1 of oil adds ~Rp6.7T to the bill).
Verdict, how long? Through 2026, it holds: the government has committed to no increase and is absorbing the strain with quotas and engine-capacity limits, not price (a 50 L/day cap ran Apr-May). But the pressure is structural, the gap is wide and rising oil keeps the bill climbing. The hike risk concentrates in 2027, or a sharper oil break, when it's the APBN gap, not the pump, that forces the decision.
The takeaway
The formula is public, so the surprise is optional. Swap "fuel" for any regulated or derived price, electricity tariffs, toll fees, commodity-linked goods, and it's the same agent: public signal in, a dated directional call out.
Honest limits: prices here are verified from news on Pertamina's Apr-Jun 2026 adjustments, but the deeper back-history is thin, only Turbo and Dexlite had enough sourced months to calibrate; Pertamax and Pertamax Green need a fuller table. It uses a free oil proxy, not the paid MOPS/Argus data Pertamina actually uses, so estimates are directional. Adjustments aren't always on the 1st, 2026 saw mid-month moves (10 Jun, 18 Apr). Subsidized fuels (Pertalite, Biosolar) are political, not formula-driven, so the agent gauges strain (pressure), never a price or a date. Not financial advice, a thinking tool, not an oracle.
Price sources: Kompas, CNBC Indonesia, InvestorTrust, Kompas (18 Apr). Subsidy & fiscal: Kompas/ESDM, Kontan (quota).
Building an AI agent?
I'm packaging how I ship them into one kit. Early access:
AI Agent Starter Kit →