Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
47dc6fa
Add real-data backtest phases and runners
JohnCCarter May 28, 2026
0496f57
Add trade matrix backtest and risk-adjusted R
JohnCCarter May 28, 2026
5a03603
Add manual label review pack generator
JohnCCarter May 28, 2026
71249ec
Make manual labels editable
JohnCCarter May 28, 2026
43d0cb4
Add first BTC manual label recall
JohnCCarter May 28, 2026
4998b87
Clarify manual drawings as reference material
JohnCCarter May 28, 2026
6641c47
Allow timeframe overrides in label tool
JohnCCarter May 28, 2026
b3d32ae
Upgrade manual labeling workspace
JohnCCarter May 28, 2026
27f4df8
Record latest pivot recall rerun
JohnCCarter May 28, 2026
83bd074
test: reorganize tests to mirror src/fibengine layout.
JohnCCarter May 28, 2026
1f973b8
chore: add CI, pre-commit hooks, and contributing quality gate.
JohnCCarter May 28, 2026
782d8c4
docs: add repo policy, tracks, backtest plan, and premortem index.
JohnCCarter May 28, 2026
028e8dc
refactor: reorganize experiments layout and add archive.
JohnCCarter May 28, 2026
475e722
data: migrate labels to exchange/symbol/timeframe paths.
JohnCCarter May 28, 2026
46679cb
refactor: move shared fibengine modules into core package.
JohnCCarter May 28, 2026
0571989
feat: add label batch checkpoints and improve labeling tool.
JohnCCarter May 28, 2026
98c0091
feat: add Optuna tuning runner and config variants.
JohnCCarter May 28, 2026
58bc228
config: adjust baseline pivot and scoring from labeling round.
JohnCCarter May 28, 2026
e8dcc7e
chore: update README, gitignore, and workspace editor settings.
JohnCCarter May 28, 2026
641b87e
chore: remove label-driven Optuna tuning and artifacts
JohnCCarter May 29, 2026
4146ce2
merge: sync origin/main into feature (worklist, premortem, stability …
JohnCCarter May 29, 2026
a18c79f
Add machine-labeling: tagged provisional candidates that can't become…
claude May 29, 2026
97a93a9
Fix doc regressions flagged in PR review (#7)
claude May 30, 2026
73f42ec
Address review findings 3-4 (leaderboard rows, reflection completeness)
claude May 30, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 20 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,27 +31,30 @@ ZigZag-Fib. Den väljer swingar, ritar Fib automatiskt och förbättras iterativ
uv sync --extra dev # bygg miljö + lockfile
uv run python -m fibengine.data.fetch # hämta + cacha candles (CCXT)
uv run python -m fibengine.labeling.worklist # vad återstår att labela mot 20–30-målet
uv run python -m fibengine.labeling.autolabel # maskin-kandidater (source=machine) att granska
uv run python -m fibengine.labeling.tool # klicka swing high/low -> facit
uv run python -m fibengine.labeling.batch # lättviktig label-checkpoint (manifest/hashar)
uv run python -m fibengine.experiment # kör pipeline + logga resultat
uv run python -m fibengine.backtest.runner # kausalt walk-forward: urvals-stabilitet
uv run python -m fibengine.backtest.matrix # stabilitet över symbol/timeframe-matris
uv run pytest # kör tester
uv run pre-commit install # git hooks (en gång)
uv run pre-commit run --all-files # lint + format + test före push
```

Kvalitetsgate: se [`docs/CONTRIBUTING.md`](docs/CONTRIBUTING.md) och CI i `.github/workflows/ci.yml`.

Använd `--config` för att köra en variant-settings utan att ändra baseline:
Använd `--config` för en principmotiverad variant under `config/variants/` utan att ändra baseline:

```bash
uv run python -m fibengine.experiment --config config/variants/<variant>.yaml
uv run python -m fibengine.experiment --config config/variants/<profil>.yaml
uv run python -m fibengine.backtest.runner --config config/variants/<profil>.yaml
```

> Obs: automatisk vikt-optimering (Optuna) togs medvetet bort — den optimerade mot
> de manuella labelsen, vilket bryter mot filosofin (labels = referens, inte domare)
> och överanpassade ett för litet labelset. Se `premortem/reflections/`. Vikter
> sätts på principgrund; arkiverade Optuna-artefakter finns under `archive/`.
> de manuella labelsen, vilket bryter mot filosofin (labels = referens, inte domare).
> Se `premortem/reflections/2026-05-28-remove-optuna.md`. Vikter sätts på principgrund.
> Arkiverade Optuna-artefakter finns kvar under `archive/` som historik.

## Pipeline (Lager A)

Expand Down Expand Up @@ -120,3 +123,15 @@ leg än en ritning är det en signal att undersöka, inte automatiskt ett fel.

1. Labela dina setups med `labeling/tool.py` → exakta tid+pris sparas som JSON.
2. Arkivera TradingView-screenshots i `data/screenshots/` som visuell referens.

### Maskin-labeling (kandidater, inte facit)

`labeling/autolabel.py` kan generera **provisoriska** swing-kandidater
(`source="machine"`) från motorns eget urval, så att du slipper börja från ett
tomt chart. Tre hårda regler skyddar facit-integriteten:

- Maskin-labels **exkluderas** från recall/agreement (`pivot_recall`, `experiment`)
och räknas **inte** mot 20–30-målet — annars mäter vi motorn mot sin egen output.
- En befintlig **mänsklig** label skrivs aldrig över.
- Öppna kandidaten i `labeling.tool`, granska/justera och tryck `s` → den sparas som
`source="human"` (befordran). Rubrikstämpla aldrig en ogranskad kandidat som facit.
16 changes: 5 additions & 11 deletions REPO_POLICY.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,7 @@ som Research tills Validate-kriterier uppfyllts.
### Spårkoppling till repo-ytor

- **Research / Experiment**
- `config/variants/`
- `src/fibengine/tuning/`
- `experiments/runs/optuna/`
- `config/variants/` (principmotiverade profiler — inte label-auto-tuning)
- `experiments/label_review/`
- `premortem/reflections/`

Expand Down Expand Up @@ -81,7 +79,6 @@ Varje modul ska ha ett tydligt ansvar. Inga “utils.py” utan kategori.
| `labeling/` | Label-verktyg + lagring + batch |
| `backtest/` | Walk-forward stabilitet + trade-backtest |
| `sizing/` | Solros sizing (Lager B) |
| `tuning/` | Experimentell parameteroptimering (Optuna m.m.) |
| `viz/` | Plot-funktioner |
| `experiment.py` | Standardrunner som loggar till `experiments/runs/` |
| `core/logging_conf.py` | Loguru-setup |
Expand All @@ -107,7 +104,7 @@ Detta är **obligatoriskt** för att repot ska räknas som organiserat:
`data/screenshots/{source}/{symbol}/{timeframe}/{filename}.png`
3. **`experiments/runs/` MÅSTE** använda:
`experiments/runs/{kind}/{YYYY-MM-DD}/{run_id}/`
där `kind ∈ {experiment, stability, optuna, archive}`.
där `kind ∈ {experiment, stability}`.
4. **Indexfiler MÅSTE finnas och hållas uppdaterade**:
- `data/raw/INDEX.md`
- `data/screenshots/INDEX.md`
Expand All @@ -118,8 +115,8 @@ Detta är **obligatoriskt** för att repot ska räknas som organiserat:
- `data/raw/`, `data/screenshots/`, `experiments/runs/`,
`experiments/label_review/`, `data/labels/`
6. **`config/settings.yaml` är baseline (MÅSTE)**:
- ska inte överlagras av tuning-runs.
- nya kandidater sparas i `config/variants/*.yaml`.
- vikter sätts på **principer**, inte genom auto-optimering mot manuella ritningar.
- nya kandidater sparas i `config/variants/*.yaml` med premortem-motivering.
- `config/variants/INDEX.md` ska uppdateras när en ny variant läggs till.

## 4. Tester
Expand Down Expand Up @@ -147,7 +144,6 @@ experiments/
runs/ ← audit-mappar per körtyp/datum + INDEX
experiment/YYYY-MM-DD/run_...
stability/YYYY-MM-DD/bt_...
optuna/YYYY-MM-DD/optuna_...
label_review/ ← versionerade label-checkpoints
```

Expand All @@ -160,8 +156,6 @@ experiments/
- `backtest_matrix.jsonl` — sweep över symbol/timeframe för stabilitet
- `trade_matrix.jsonl` — sweep över symbol/timeframe för trade-ekonomi
- `leaderboard.jsonl` — sammanfattning av `python -m fibengine.experiment`-körningar
- `optuna_trials.jsonl` — trial-utfall från `python -m fibengine.tuning.optuna_runner`
- `optuna_best.json` — senaste bästa Optuna-resultat (överskrivs med senaste körning)

**`experiments/label_review/batches/<batch_id>/`** — där `batch_id` följer §3:
- `metadata.json`
Expand Down Expand Up @@ -281,7 +275,7 @@ struktur eller arbetsflöde: uppdatera först, sen flytta filerna. Aldrig tvärt

Något får bara klassas som **trusted engine behavior** när alla punkter är uppfyllda:

1. Ursprunglig kandidat finns i Research-spåret (t.ex. `config/variants/` eller tuning-run).
1. Ursprunglig kandidat finns i Research-spåret (t.ex. principmotiverad `config/variants/`).
2. Validate-evidens finns (relevanta körningar i `experiments/results/`/`experiments/runs/stability/`).
3. `uv run pytest` är grönt.
4. Kort reflektion i `premortem/reflections/` dokumenterar beslutet.
Expand Down
1 change: 1 addition & 0 deletions archive/INDEX.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@
| 2026-05-28 | `experiments/ledgers/2026-05-28-pre-results-migration/` | `experiments/*.jsonl` (rot) | Flyttad till `experiments/results/`; gamla kopior behålls |
| 2026-05-28 | `experiments/label_review/*` (se undermappar) | `experiments/label_review/` (rot-dubletter) | Canonical källa: `experiments/label_review/batches/` |
| 2026-05-28 | — | `FIB_BACKTEST_PLAN.md` (repo-rot) | Raderad stub; canonical: `docs/FIB_BACKTEST_PLAN.md` |
| 2026-05-28 | `experiments/optuna/`, `config_variants/optuna_2026-05-28_trial31.yaml` | Optuna (kod ur `src/fibengine/tuning/`, variant, ledgers) | Koden borttagen ur drift (strider mot principen labels=referens, inte optimeringsmål); artefakterna behålls här som historik |
2 changes: 1 addition & 1 deletion config/variants/INDEX.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

| file | source | purpose | notes |
|---|---|---|---|
| _(inga aktiva varianter)_ | — | — | Optuna-kandidaten drogs tillbaka (optimerade mot labels) och arkiverades under `archive/config_variants/`. |
| *(inga aktiva varianter)* | — | — | Lägg manuella, principmotiverade YAML här vid behov |
19 changes: 4 additions & 15 deletions config/variants/README.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,7 @@
# config/variants

Alternativa settings-profiler för experiment (manuellt satta på principgrund).
Alternativa settings-profiler för **Research** — principmotiverade, dokumenterade i `INDEX.md`.

## Princip

- `config/settings.yaml` är baseline.
- Nya kandidater sparas här som separata filer.
- Filnamn ska vara beskrivande och gärna datumsatta.
- Vikter sätts på principgrund — inte genom optimering mot labels.

## Namnexempel

- `manual_2026-05-29_round2.yaml`

## Index

- `INDEX.md` listar alla varianter, ursprung och syfte.
- Baseline (Promotion): `config/settings.yaml`
- Ändra vikter här med premortem-motivering; optimera **inte** mot `agreement` mot labels.
- Validate med stabilitet (`backtest.matrix`) och pivot recall — labels endast som referens-check.
7 changes: 7 additions & 0 deletions data/labels/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,11 @@ Kör `uv run python -m fibengine.labeling.worklist` för att se täckning mot
20–30-setup-målet (PREMORTEM.md) och få färdiga `labeling.tool`-kommandon för de
symbol/timeframe-kombinationer som ännu saknar facit.

Varje label har ett `source`-fält:

- `source: "human"` (default) — manuellt facit, golden set.
- `source: "machine"` — provisorisk kandidat från `labeling.autolabel`. Exkluderas
från recall/agreement och räknas inte mot 20–30-målet. Granska i `labeling.tool`
och spara → blir `human`.

Legacy platt filnamn (`binance_BTC-USDT_1h.json` på rot) stöds fortfarande vid läsning men nya sparas i kategoriserad struktur.
26 changes: 4 additions & 22 deletions docs/FIB_BACKTEST_PLAN.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@ Premortem: record surprises in `premortem/reflections/` (short, not essays).
| 3 Manual label recall | Validate | **in progress** | `experiments/results/pivot_recall.jsonl` |
| 4 Layer B trade simulation | Validate | **smoke done** | `experiments/results/trade_*.jsonl` |
| 5 Iteration discipline | All | **active** | Policy + reflections |
| 6 ~~Optuna / variants~~ | — | **withdrawn** | Archived under `archive/` (optimerade mot labels) |
| 7 Promotion gate | Promotion | **next** | Merge into `config/settings.yaml` |
| 6 Promotion gate | Promotion | **next** | Merge into `config/settings.yaml` |

---

Expand All @@ -48,7 +47,7 @@ uv run python -m fibengine.backtest.matrix

**Success:** symbol, timeframe, limit, config hash, run id, metrics; failures as rows; comparable without opening every run folder.

**Later:** re-run matrix with expanded labels/timeframes (`30m`, `1d`, `1w`, `1M`) when label coverage is ready — still Validate, not Research tuning.
**Later:** re-run matrix with expanded labels/timeframes (`30m`, `1d`, `1w`, `1M`) when label coverage is ready.

---

Expand Down Expand Up @@ -116,22 +115,7 @@ uv run python -m fibengine.backtest.trade_matrix

---

## Phase 6 — ~~Optuna / config variants~~ (WITHDRAWN)

**Status:** **withdrawn.** Automatisk vikt-optimering togs bort. Objektivet
maximerade `agreement`/`fib_err` mot de manuella labelsen — vilket bryter mot
filosofin (labels = referens, inte domare) och överanpassade ett för litet
labelset (best agreement ≈ 0.025, principvidriga negativa vikter). Se
`premortem/reflections/2026-05-28-optuna-rollback.md`. Artefakter arkiverade
under `archive/experiments/optuna/` och `archive/config_variants/`.

**Ersättning:** vikter sätts manuellt på principgrund och sparas som
`config/variants/<beskrivning>.yaml`, validerade enligt Phase 7 mot stabilitet/
recall — inte mot en label-agreement-objektivfunktion.

---

## Phase 7 — Promotion gate (Validate → Promotion)
## Phase 6 — Promotion gate (Validate → Promotion)

**Status:** next after variant beats baseline on Validate checks.

Expand All @@ -145,9 +129,7 @@ recall — inte mot en label-agreement-objektivfunktion.
4. Short reflection: what changed, why promoted, what was rejected.
5. Update `config/settings.yaml` only after the above; archive variant rationale in `config/variants/INDEX.md`.

**Do not promote** from a label-agreement objective alone — Validate against
stability/recall first, then Promotion. (Automatic optimization against labels
is disallowed; see Phase 6.)
**Do not promote** from label agreement alone — Validate (stabilitet + recall) first, then Promotion. Viktändringar motiveras av principer (premortem), inte auto-tuning mot ritningar.

---

Expand Down
9 changes: 4 additions & 5 deletions docs/TRACKS.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,15 @@ Syftet är att separera discovery från verifiering och från trusted behavior.
- fri experimentation
- snabb iteration
- AI/reflection/premortem (obligatoriskt enligt policy)
- utforskande metoder
- manuella, principmotiverade profiler i `config/variants/` (inte auto-tuning mot labels)

> Notera: automatisk vikt-optimering *mot labels* (t.ex. Optuna) är **inte** tillåten
> — labels är referens, inte domare. Vikter sätts på principgrund. Se
> `premortem/reflections/` för varför detta drogs tillbaka.
**Inte tillåtet:**
- automatisk vikt-optimering mot `agreement` / manuella ritningar

**Inte krav:** full correctness eller production-grade stabilitet.

**Primära ytor:**
- `config/variants/*.yaml`
- `config/variants/*.yaml` (principprofiler, dokumenterade)
- `experiments/label_review/`
- `premortem/reflections/`

Expand Down
2 changes: 1 addition & 1 deletion experiments/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@ Se även `REPO_POLICY.md` §5 och §10 för vad som ska sparas/städas.

## Koppling till 3 spår

- **Research / Experiment:** `runs/optuna/`, `label_review/`, tuning-ledgers i `results/`.
- **Research / Experiment:** `label_review/`, principmotiverade `config/variants/`.
- **Validate:** `runs/stability/`, `pivot_recall/backtests/backtest_matrix` i `results/`.
- **Promotion:** inga direkta ändringar här; promotion sker först efter validate-gate enligt `docs/TRACKS.md`.
2 changes: 0 additions & 2 deletions experiments/results/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,3 @@ Append-only resultatfiler (`*.jsonl`) från körningar.
- `backtest_matrix.jsonl` stabilitet över symbol/timeframe-matris.
- `trade_matrix.jsonl` trade-matris över symbol/timeframe.
- `leaderboard.jsonl` sammanfattning av experimentkörningar.
- `optuna_trials.jsonl` trial-resultat från Optuna tuning.
- `optuna_best.json` senaste bästa Optuna-resultat.
29 changes: 29 additions & 0 deletions premortem/reflections/2026-05-28-remove-optuna.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# 2026-05-28 Ta bort Optuna (slutstädning)

Uppföljning på `2026-05-28-optuna-rollback.md` (som drog tillbaka själva runnern).
Den här noten städar de sista spåren så repot inte längre låtsas att Optuna finns.

Hypotes:
- Optuna har ingen legitim roll om vikter sätts på principer och labels endast är
referens. Kvarvarande referenser i kod/docs skapar förvirring och frestelse.

Scope:
- Delsystem: dokumentation + repo-bokföring (ingen körning).
- Ytor: `README.md`, `docs/TRACKS.md`, `REPO_POLICY.md`, `docs/FIB_BACKTEST_PLAN.md`,
`archive/INDEX.md`, `config/variants/`.

Observationer:
- `src/fibengine/tuning/` och `optuna`-dependencyn var redan borttagna (rollback);
det som återstod var doc-referenser och arkiv-bokföring.
- Optuna-artefakterna behålls i `archive/` som historik (raderas inte) — `archive/`
finns till för ersatt/legacy-material (REPO_POLICY §1).
- `config/variants/` ramas om till principmotiverade profiler (ingen auto-tuning).

Beslut:
- Ta bort kvarvarande Optuna-referenser i README/TRACKS/REPO_POLICY/FIB_BACKTEST_PLAN.
- Behåll arkiverade artefakter; håll `archive/INDEX.md` ärlig om vad som finns kvar.
- Vikter sätts manuellt på principgrund; ingen optimering mot `agreement`/labels.

Nästa steg:
- Validate via stabilitetsmatris + pivot recall; manuella viktändringar motiveras i
premortem, aldrig auto-tunade mot ritningar.
38 changes: 38 additions & 0 deletions premortem/reflections/2026-05-29-machine-labeling.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# 2026-05-29 Maskin-labeling (kandidater, inte facit)

Uppföljning: jag avböjde att generera facit (cirkulärt — maskinen skulle valideras
mot sin egen output). Kompromissen blev maskin-labeling med tydlig `source`-stämpel
och hårda integritetsregler, så kandidater kan sänka tröskeln utan att bli domare.

Hypotes:
- Provisoriska maskin-kandidater gör det billigare för en människa att fylla
facit-gapen — UTAN att korrumpera golden set — om de (a) är tydligt märkta,
(b) exkluderas från all label-baserad evaluering, och (c) aldrig skriver över
mänskligt facit.

Scope:
- Delsystem: `labeling/` (ny `autolabel.py`, `source` i `store.py`, worklist-split),
`evaluation/pivot_recall.py` + `experiment.py` (exkludering).
- Ingen nät/GUI i tester (syntetiska data + mockad `select_swing`/`load_candles`).

Observationer:
- `SwingLabel.source` ("human"/"machine"), default "human" → befintliga JSON-labels
förblir human. `list_labels(source=...)` filtrerar.
- `pivot_recall` och `experiment` evaluerar nu **bara** `source="human"`; antal
hoppade maskin-labels loggas. Test låser exkluderingen.
- `autolabel.py` bygger kandidat från motorns `select_swing`, märker `source="machine"`
+ not, och **vägrar** skriva över en mänsklig label (`status="skipped_human"`).
- `worklist`: bara human räknas mot målet; maskin-kandidater listas separat som
"att granska". Nuläge oförändrat: 15/25 human, 6 helt olabelade.
- Befordran: öppnas kandidaten i `labeling.tool` och sparas → `source="human"`
(verktygets save bygger en label utan source = default human).
- Tester: 78 → 85 gröna; coverage ~76%; lint rent.

Beslut:
- Maskin-labels är scaffolding/Research, aldrig facit eller optimeringsmål. Den
uttalade filosofin ("labels = referens, inte domare") står kvar oförändrad.

Nästa steg (kräver nät/människa):
- Kör `autolabel` på de 6 saknade kombinationerna när nät finns; granska var och en
i `labeling.tool` och befordra de rimliga till human.
- Kör därefter `pivot_recall` + `matrix` och kalibrera `gate_*`.
7 changes: 6 additions & 1 deletion src/fibengine/evaluation/pivot_recall.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,12 @@ def run_pivot_recall(settings: Settings | None = None) -> list[dict]:
rows: list[dict] = []
run_id = datetime.now(UTC).strftime("pivot_recall_%Y%m%dT%H%M%SZ")
log = setup_logging(run_id, settings.config_hash())
labels = list_labels()
# Endast mänskligt facit får vara ground truth. Maskin-labels är kandidater
# och EXKLUDERAS — annars mäter vi motorn mot sig själv (cirkulärt).
labels = list_labels(source="human")
n_machine = len(list_labels(source="machine"))
if n_machine:
Comment on lines +123 to +125
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (performance): Att ladda labels två gånger träffar label-storen två gånger; överväg att partitionera en enda laddning för bättre effektivitet.

Detta triggar nu två fullständiga katalogskanningar/JSON-laddningar (source="human" och source="machine"). När mängden labels växer kan den extra I/O:n bli märkbar. Överväg att ladda en gång (t.ex. all_labels = list_labels()) och sedan partitionera till human vs. machine i minnet för att behålla samma loggning men undvika upprepad I/O.

Original comment in English

suggestion (performance): Loading labels twice hits the label store twice; consider partitioning a single load for better efficiency.

This now triggers two full directory scans/JSON loads (source="human" and source="machine"). As the label set grows this extra I/O can add up. Consider loading once (e.g. all_labels = list_labels()) and then partitioning into human vs machine in memory to keep the same logging while avoiding repeated I/O.

log.info("Hoppar över {} maskin-labels (ej ground truth för recall)", n_machine)

for label in labels:
row = {
Expand Down
7 changes: 6 additions & 1 deletion src/fibengine/experiment.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,12 @@ def run_experiment(settings: Settings | None = None) -> Path:
(run_dir / "config.json").write_text(json.dumps(settings.model_dump(), indent=2))
log.info("Startar experiment {} (cfg {})", run_id, config_hash)

labels = list_labels()
# Agreement mäts bara mot mänskligt facit; maskin-labels exkluderas (kandidater,
# inte domare) så vi inte råkar mäta motorn mot sin egen output.
labels = list_labels(source="human")
n_machine = len(list_labels(source="machine"))
if n_machine:
Comment on lines +130 to +132
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (performance): Samma dubbel-laddningsmönster som i pivot_recall; du kan återanvända ett enda anrop till list_labels() och partitionera i minnet.

För att undvika upprepad I/O och hålla detta konsekvent med pivot_recall, överväg att anropa list_labels() en gång och dela upp resultatet i human- respektive machine-labels i minnet, särskilt eftersom experiment kan köras ofta mot en växande label-mängd.

Suggested implementation:

    # Agreement mäts bara mot mänskligt facit; maskin-labels exkluderas (kandidater,
    # inte domare) så vi inte råkar mäta motorn mot sin egen output.
    all_labels = list_labels()
    labels = [lbl for lbl in all_labels if getattr(lbl, "source", None) == "human"]
    n_machine = sum(1 for lbl in all_labels if getattr(lbl, "source", None) == "machine")
    if n_machine:
        log.info("Hoppar över {} maskin-labels i agreement (ej ground truth)", n_machine)
    results: list[dict] = []
    if not labels:
        log.warning("Inga labels i data/labels/ — kör enbart prediktion på konfig-symbolen.")

Om list_labels() redan returnerar separata strukturer eller tupler (t.ex. (human_labels, machine_labels)), eller om label-objekten exponerar källan under ett annat attribut eller nyckel än .source, justera getattr(lbl, "source", None)-kontrollerna därefter för att matcha det faktiska API:et (till exempel lbl["source"] eller lbl.meta.source). Det viktiga är: behåll ett enda anrop till list_labels() och härled labels (human) och n_machine (antal machine) från det i minnet.

Original comment in English

suggestion (performance): Same double-load pattern as in pivot_recall; you can reuse a single list_labels() call and partition in memory.

To avoid repeated I/O and keep this consistent with pivot_recall, consider calling list_labels() once and splitting the result into human vs. machine labels in memory, especially since experiments may run often over an increasing label set.

Suggested implementation:

    # Agreement mäts bara mot mänskligt facit; maskin-labels exkluderas (kandidater,
    # inte domare) så vi inte råkar mäta motorn mot sin egen output.
    all_labels = list_labels()
    labels = [lbl for lbl in all_labels if getattr(lbl, "source", None) == "human"]
    n_machine = sum(1 for lbl in all_labels if getattr(lbl, "source", None) == "machine")
    if n_machine:
        log.info("Hoppar över {} maskin-labels i agreement (ej ground truth)", n_machine)
    results: list[dict] = []
    if not labels:
        log.warning("Inga labels i data/labels/ — kör enbart prediktion på konfig-symbolen.")

If list_labels() already returns separate structures or tuples (e.g. (human_labels, machine_labels)), or if the label objects expose the source under a different attribute or key than .source, adjust the getattr(lbl, "source", None) checks accordingly to match the actual API (for example lbl["source"] or lbl.meta.source). The important part is: keep a single list_labels() call and derive labels (human) and n_machine (machine count) from that in memory.

log.info("Hoppar över {} maskin-labels i agreement (ej ground truth)", n_machine)
results: list[dict] = []
if not labels:
log.warning("Inga labels i data/labels/ — kör enbart prediktion på konfig-symbolen.")
Expand Down
Loading
Loading