Analyze your solar export against historical Swedish spot prices — including negative prices — and see what your electricity was actually worth. The web app runs entirely in your browser; your production file never leaves your device.
When you have solar panels you sell excess electricity to the grid, but spot prices sometimes go negative — meaning you pay to export. Since the 60 öre/kWh tax credit ended on 1 January 2026, the spot price alone decides what your export is worth. Upload your meter export and the tool reports:
- Total export and revenue at realized spot prices.
- Negative-price exposure: quarters, kWh and cost of exporting at negative prices.
- Grid-connection load: how often export was pinned at your main-fuse limit.
- Effective export pay from both your elnätsbolag (förlustersättning) and elhandelsbolag (påslag/avdrag), each a fixed (öre/kWh) + variable (% of spot) part, plus VAT.
- Loss-making quarters where the effective price fell below zero, with a chart and a table.
- Self-consumption value: what a kWh is worth used yourself vs. exported.
- Whether upgrading or downgrading the main fuse would pay off.
- Optional Swedish AI summary, generated in the browser with your own key.
- JSON / CSV export of the results.
- Private and serverless: all parsing, price-matching and analysis run client-side.
- No API key for prices: uses the free elprisetjustnu.se API (CORS-enabled, native 15-minute, prices in SEK).
- Interval-aware: handles any mix of hourly / 15-minute / daily data via overlap allocation.
- Swedish bidding zones SE1–SE4.
- Grid-connection analysis: main-fuse flat-peak detection (3-phase, 400 V).
- Export compensation per company (elnät + elhandel), each fixed (öre/kWh) + variable (% of spot) + VAT.
- Loss-making quarters: count, chart and table of quarters exported below break-even.
- Monthly forecast: expected net per full-data month after fixed monthly fees.
- Fuse up/downgrade analysis: extra/lower subscription fee weighed against unlocked or clipped export.
- Optional SMHI STRÅNG solar irradiance for sunlit-hour pricing and a rough potential-production estimate.
- Inputs in öre/kWh; results show kronor for totals and öre for per-kWh values.
- Export your meter data as CSV from your grid/energy company's portal. 15-minute (quarter-hour) data is recommended; hourly and daily are detected automatically. Grid companies often cap 15-minute exports at ~3 months — upload several files and they are combined.
- Upload the file(s), or click Prova med exempeldata to run a bundled 15-minute sample.
- Choose your bidding zone (SE1–SE4).
- Optionally set the main fuse size, VAT, export compensation per company, self-consumption inputs, and a position for STRÅNG.
- Click Analysera. The report appears in the browser and can be downloaded as JSON or CSV.
Sample files are in python/data/samples/; the bundled web example is frontend/public/exempel-15min.csv. The browser app reads CSV (export Excel as CSV first); the Python CLI also reads Excel.
Prices come from the free, no-key elprisetjustnu.se API (CORS-enabled, so it works from the browser):
GET https://www.elprisetjustnu.se/api/v1/prices/{YYYY}/{MM}-{DD}_{ZONE}.json
Values are returned in SEK/kWh (and EUR/kWh) at the market resolution — 15-minute from 2025-10-01, hourly before.
Why not an ENTSO-E key in the browser? ENTSO-E sends no CORS headers, so a static-site browser cannot read its responses, and any client-side key is publicly visible. The browser app therefore uses elprisetjustnu.se. To use an ENTSO-E key, run the Python CLI (ENTSOE_API_KEY), which runs locally where CORS does not apply.
negative-price-calc/
├── frontend/ # Deployed web app (Next.js, static export)
│ ├── public/exempel-15min.csv # Bundled 15-min example
│ └── src/
│ ├── app/page.tsx # Upload UI, settings, results
│ ├── components/ # Results cards, charts, terminal, upload
│ └── lib/ # Client-side engine:
│ ├── parseProduction.ts # CSV parsing + 15-min validation + multi-file combine
│ ├── prices.ts # elprisetjustnu.se price client
│ ├── analyze.ts # interval-aware analysis (overlap allocation)
│ ├── strang.ts # SMHI STRÅNG irradiance client (browser-only)
│ └── aiSummary.ts # optional OpenRouter summary (BYO key)
└── python/ # Python library / CLI (feature parity)
├── core/
│ ├── price_analyzer.py # interval-aware analysis + fuse up/downgrade
│ ├── intervals.py # granularity helpers + 15-min validation + combine
│ ├── price_fetcher.py # ENTSO-E fetch (ENTSOE_API_KEY) + SQLite cache
│ └── db_manager.py # price cache (resolution-aware)
├── cli/main.py # se-cli command-line interface
└── data/samples/ # Example production files
The web app is fully client-side and needs no backend. The Python CLI/library mirrors the analysis for offline/scripted use; STRÅNG is browser-only.
Web app:
cd frontend
npm install
npm run dev # http://localhost:3000Python CLI (optional):
cd python
uv sync
uv run se-cli analyze your_file.csv --area SE_4 --json
uv run se-cli analyze your_file.csv --area SE_4 --vat 25 --energy-tax 0.4282 --transmission-fee 0.25The CLI fetches prices from ENTSO-E (ENTSOE_API_KEY) or uses the bundled SQLite cache. See python/README.md.
GitHub Actions (.github/workflows/deploy-pages.yml) builds frontend/ and publishes frontend/out on every push to main. For a fork: enable Settings → Pages → Source: GitHub Actions, then push to main (the build sets NEXT_PUBLIC_BASE_PATH=/<repo>).
# Python
cd python
uv run pytest
# TypeScript engine (from repo root)
node --experimental-strip-types frontend/scripts/test-analyze.mjsFork, create a feature branch, make the change (keep the TS engine and Python analyzer in parity), run the tests, and open a pull request.
MIT — see LICENSE.
- Price data from elprisetjustnu.se.
- Solar irradiance from SMHI STRÅNG.
- Built for the Swedish solar community by Sourceful Energy.