commands: stats.md + batch.md aligned to canonical spec (Romanian, STOPPING_RULE highlight, _batch summary format)
This commit is contained in:
@@ -1,95 +1,106 @@
|
|||||||
---
|
---
|
||||||
description: Run vision extraction in parallel on multiple screenshots (default screenshots/inbox/), then serial-append the results with partial-failure handling.
|
description: Procesează toate screenshot-urile din screenshots/inbox/ paralel (5 agenți). Append serial cu partial-failure semantics.
|
||||||
argument-hint: "[dir_or_glob] [--limit N] [--calibration]"
|
argument-hint: "[N max_parallel=5]"
|
||||||
---
|
---
|
||||||
|
|
||||||
# /batch — parallel vision extraction over multiple screenshots
|
# /batch — parallel vision extraction over screenshots/inbox/
|
||||||
|
|
||||||
Procesează screenshot-uri multiple. Lansează până la **5 subagenți `m2d-extractor` în paralel** (cap rigid — protejează context window și rate limits). După ce toți revin, append-ezi rezultatele **serial** (`append_row` citește/scrie CSV — paralelism la write = corupție garantată).
|
Procesează screenshot-uri multiple din `screenshots/inbox/`. Lansează până la **5 subagenți `m2d-extractor` în paralel** (cap rigid — context window + rate limits). După ce toți revin, append-ezi rezultatele **serial** (`append_row` citește/scrie CSV — paralelism la write = ID collision garantat).
|
||||||
|
|
||||||
## Arguments
|
|
||||||
|
|
||||||
- `$1` (opțional) — director sau glob. Default `screenshots/inbox/`. Exemplu: `screenshots/inbox/2025-09-*.png`.
|
|
||||||
- `--limit N` (opțional) — procesează doar primele N screenshot-uri (în ordine alfabetică). Default: toate.
|
|
||||||
- `--calibration` (flag) — `source=vision_calibration` în loc de `vision`.
|
|
||||||
|
|
||||||
## Workflow
|
## Workflow
|
||||||
|
|
||||||
### Fază 1 — Colectează lista
|
### Fază 1 — Colectează lista
|
||||||
|
|
||||||
1. Enumeră fișierele PNG/JPG match-uind argumentul. Sortează alfabetic. Aplică `--limit` dacă există.
|
1. Listează `screenshots/inbox/*.png` (sortat alfabetic).
|
||||||
2. Dacă lista e goală → raportezi "Nimic de procesat în <path>" și te oprești.
|
2. Dacă lista e goală → afișează `Inbox gol. Adaugă PNG-uri în screenshots/inbox/.` și oprește.
|
||||||
3. Dacă lista are 1 element → sugerează `/backtest` în loc și continuă cu batch.
|
3. Dacă `$ARGUMENTS` conține un număr `N`, folosește-l ca `max_parallel` în loc de 5 (dar nu depăși niciodată 5 — hard cap).
|
||||||
|
|
||||||
### Fază 2 — Extracție paralelă (max 5 concurent)
|
### Fază 2 — Extracție paralelă (max 5 concurent)
|
||||||
|
|
||||||
Procesezi în **batch-uri de 5**. Pentru fiecare batch:
|
Procesezi în **batch-uri de `max_parallel`**. Pentru fiecare batch:
|
||||||
|
|
||||||
- Lansezi câte un Task tool call cu `subagent_type: "m2d-extractor"` pentru fiecare screenshot, ÎN ACELAȘI MESAJ (tool calls paralele). Prompt-ul per agent:
|
- Lansezi câte un Task tool call cu `subagent_type: "m2d-extractor"` pentru fiecare screenshot, ÎN ACELAȘI MESAJ (tool calls paralele). Prompt per agent:
|
||||||
|
|
||||||
```
|
```
|
||||||
|
Extrage trade din `<absolute_path>`. Scrie JSON la `data/extractions/<basename_no_ext>.json` și log la `data/extractions/<basename_no_ext>.log`.
|
||||||
|
|
||||||
screenshot_path: <absolute_path>
|
screenshot_path: <absolute_path>
|
||||||
screenshot_file: <basename>
|
screenshot_file: <basename>
|
||||||
```
|
```
|
||||||
|
|
||||||
- Aștepți să se întoarcă toți cinci. Pentru fiecare, verifici că `data/extractions/<basename_no_ext>.json` a fost scris.
|
- Aștepți să se întoarcă toți. Treci la următorul batch.
|
||||||
- Treci la următorul batch de 5.
|
|
||||||
|
|
||||||
**De ce 5**: peste 5 sub-agenți paraleli începi să saturezi context window-ul orchestratorului cu output-urile lor și rate limits-urile API-ului. Cap rigid.
|
**De ce max 5**: peste 5 sub-agenți paraleli începi să saturezi context window-ul orchestratorului cu output-urile lor și rate limits-urile API-ului. Cap rigid.
|
||||||
|
|
||||||
### Fază 3 — Append serial cu partial-failure
|
### Fază 3 — Append serial cu partial-failure
|
||||||
|
|
||||||
Pentru fiecare screenshot din lista originală, **în ordine**:
|
Ține trei liste: `ok`, `rejected`, `failed`. Pentru fiecare PNG din lista originală, **în ordine alfabetică**:
|
||||||
|
|
||||||
1. Verifică `data/extractions/<basename_no_ext>.json`:
|
1. **Verifică existența JSON-ului** `data/extractions/<basename_no_ext>.json`:
|
||||||
- Lipsă → log "missing JSON, agent abort", mută screenshot-ul la `screenshots/needs_review/`, continuă cu următorul.
|
- Lipsește sau e corupt → mută PNG la `screenshots/needs_review/<basename>`, adaugă la `failed` cu motiv `missing/invalid JSON`, continuă.
|
||||||
- Citește JSON. Dacă `confidence == "low"` SAU `"image_unreadable" in ambiguities` → mută la `needs_review/`, continuă.
|
|
||||||
|
|
||||||
2. Apelează append:
|
2. **Apelează append** (source = `vision` — `/batch` nu suportă calibration, pentru asta folosește `/backtest --calibration` individual):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python -c "from pathlib import Path; from scripts.append_row import append_extraction; import json; r = append_extraction(Path('data/extractions/<basename_no_ext>.json'), source='<source>'); print(json.dumps(r, default=str))"
|
python -c "from pathlib import Path; from scripts.append_row import append_extraction; import json; r = append_extraction(Path('data/extractions/<basename_no_ext>.json'), source='vision'); print(json.dumps(r, default=str))"
|
||||||
```
|
```
|
||||||
|
|
||||||
`<source>` = `vision_calibration` dacă `--calibration`, altfel `vision`.
|
3. **Reacționezi**:
|
||||||
|
- `status == "ok"` → mută PNG la `screenshots/processed/<basename>`, adaugă la `ok` cu `id`, `set`, `outcome_path`.
|
||||||
|
- `status == "rejected"` → mută PNG la `screenshots/needs_review/<basename>`, mută JSON la `data/extractions/rejected/<basename_no_ext>.json` (creează folderul dacă lipsește), adaugă la `rejected` cu `reason`.
|
||||||
|
|
||||||
3. Reacționezi la rezultat:
|
4. **NU oprești batch-ul la primul fail**. Continuă până la capăt.
|
||||||
- `status == "ok"` → ține minte ID-ul, mută screenshot la `screenshots/processed/<basename>` dacă era în inbox.
|
|
||||||
- `status == "rejected"`, `reason` conține "duplicate" → ține minte ca skip; NU muta screenshot-ul (deja procesat).
|
|
||||||
- `status == "rejected"`, alt reason → log motivul, mută la `needs_review/`.
|
|
||||||
|
|
||||||
4. NU oprești batch-ul la primul fail. Continuă până la capăt.
|
|
||||||
|
|
||||||
### Fază 4 — Regenerează MD o singură dată
|
### Fază 4 — Regenerează MD o singură dată
|
||||||
|
|
||||||
După ce toate append-urile s-au terminat (chiar și parțial), rulezi UNA SINGURĂ DATĂ:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python scripts/regenerate_md.py
|
python -m scripts.regenerate_md
|
||||||
```
|
```
|
||||||
|
|
||||||
(Regenerarea după fiecare append e wasteful; CSV-ul e sursa de adevăr, MD-ul e mirror.)
|
(MD regen după fiecare append e wasteful; CSV-ul e sursa de adevăr.)
|
||||||
|
|
||||||
### Fază 5 — Raport final
|
### Fază 5 — Scrie summary la `data/extractions/_batch_<utc_timestamp>.md`
|
||||||
|
|
||||||
Format:
|
`<utc_timestamp>` format ISO compact (ex: `2026-05-13T15-45-21Z`). Conținut:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
# Batch run <iso_utc_timestamp>
|
||||||
|
|
||||||
|
Total: <N> | OK: <n_ok> | REJECTED: <n_rej> | FAILED: <n_fail>
|
||||||
|
|
||||||
|
## OK
|
||||||
|
- <basename>.png → id=<id>, set=<set>, outcome_path=<outcome_path>
|
||||||
|
- ...
|
||||||
|
|
||||||
|
## REJECTED
|
||||||
|
- <basename>.png — reason: <reason>
|
||||||
|
- ...
|
||||||
|
|
||||||
|
## FAILED
|
||||||
|
- <basename>.png — <motiv: missing/invalid JSON>
|
||||||
|
- ...
|
||||||
|
```
|
||||||
|
|
||||||
|
Secțiuni goale se omit (dacă REJECTED e gol, nu scrii secțiunea).
|
||||||
|
|
||||||
|
### Fază 6 — Afișează summary user-ului
|
||||||
|
|
||||||
|
Format scurt în terminal:
|
||||||
|
|
||||||
```
|
```
|
||||||
/batch terminat. Procesat <total> screenshot-uri.
|
/batch terminat. Total <N> screenshot-uri.
|
||||||
OK: <n_ok> (trade-uri #<id1>, #<id2>, ...)
|
OK: <n_ok> (trade-uri #<id1>, #<id2>, ...)
|
||||||
Duplicate: <n_dup> (skipped — deja în CSV)
|
REJECTED: <n_rej> (mutate la screenshots/needs_review/)
|
||||||
Needs review: <n_nr> (mutate la screenshots/needs_review/)
|
FAILED: <n_fail> (mutate la screenshots/needs_review/, JSON lipsă)
|
||||||
- <basename1>: <motiv>
|
Regenerat data/jurnal.md.
|
||||||
- <basename2>: <motiv>
|
Summary scris la data/extractions/_batch_<utc_timestamp>.md.
|
||||||
Erori: <n_err>
|
|
||||||
- <basename>: <reason>
|
|
||||||
Regenerat data/jurnal.md (<total_rows> rânduri).
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Reguli
|
## Reguli
|
||||||
|
|
||||||
- **Cap concurrency la 5**. Niciodată mai mulți subagenți paraleli — chiar și pentru un batch mare. Procesezi în secvențe de batch-uri de 5.
|
- **Hard cap concurrency la 5**. Chiar dacă `max_parallel` argumentat e mai mare, clamp la 5.
|
||||||
- **Append serial obligatoriu**. `append_extraction` citește CSV-ul, computează `next_id` și scrie atomic; rulat în paralel ar duce la ID-uri duplicat sau pierderi.
|
- **Append serial obligatoriu**. `append_extraction` citește CSV, computează `next_id`, scrie atomic; rulat paralel = ID-uri duplicate sau pierderi.
|
||||||
- **Partial failure = continuă**. Un screenshot prost nu blochează restul batch-ului.
|
- **Partial failure = continuă**. Un screenshot prost nu blochează restul batch-ului.
|
||||||
- **MD regen o singură dată** la final.
|
- **MD regen o singură dată** la final.
|
||||||
- **Path discipline pentru subagent neschimbată**: agentul scrie doar la `data/extractions/`. Tu, ca orchestrator, muți screenshot-uri.
|
- **Path discipline pentru subagent neschimbată**: agentul scrie doar la `data/extractions/`. Tu (orchestrator) muți screenshot-uri și rejected JSON-uri.
|
||||||
|
- `/batch` folosește mereu `source=vision`. Pentru calibration, rulează `/backtest --calibration` individual pe fiecare screenshot.
|
||||||
|
|||||||
@@ -1,42 +1,57 @@
|
|||||||
---
|
---
|
||||||
description: Show backtest statistics for data/jurnal.csv (overall, per-Set, per-calitate, per-instrument with Wilson + bootstrap CIs). --calibration shows P4 mismatch report.
|
description: Afișează statistici WR / expectancy / per Set (din data/jurnal.csv). Cu --calibration arată raport P4.
|
||||||
argument-hint: "[--calibration] [--seed N]"
|
argument-hint: "[--calibration] [--overlay pl_marius|pl_theoretical] [--seed N]"
|
||||||
---
|
---
|
||||||
|
|
||||||
# /stats — backtest statistics
|
# /stats — backtest statistics
|
||||||
|
|
||||||
Rulează `scripts/stats.py` și afișează raportul.
|
Wrapper read-only peste `scripts/stats.py`. Afișează raportul stat ca atare; eventual adăugă highlight la final dacă observi un Set care îndeplinește pragul STOPPING_RULE.
|
||||||
|
|
||||||
## Arguments
|
## Arguments
|
||||||
|
|
||||||
- `--calibration` (flag) — afișează raportul P4 (mismatch field-by-field pe perechi `manual_calibration` ↔ `vision_calibration` join-uite pe `screenshot_file`).
|
- `--calibration` (flag) — afișează raportul P4 (mismatch field-by-field pe perechi `manual_calibration` ↔ `vision_calibration` join-uite pe `screenshot_file`).
|
||||||
- `--seed N` (opțional) — seed pentru bootstrap RNG (default fără seed → output ne-determinist între run-uri). Folosește când vrei reproducibilitate.
|
- `--overlay pl_marius|pl_theoretical` (opțional, default `pl_marius`) — care P/L overlay folosește.
|
||||||
|
- `--seed N` (opțional) — seed pentru bootstrap RNG. Folosește pentru reproducibilitate.
|
||||||
|
|
||||||
Default (fără flag-uri): backtest stats — overall + per-Set + per-calitate + per-instrument WR, expectancy, Wilson 95% CI pe WR, bootstrap 95% CI pe expectancy.
|
Default (fără flag-uri): backtest stats — overall + per-Set + per-calitate + per-instrument WR, expectancy, Wilson 95% CI pe WR, bootstrap 95% CI pe expectancy, pe overlay `pl_marius`.
|
||||||
|
|
||||||
## Workflow
|
## Workflow
|
||||||
|
|
||||||
1. Construiește comanda:
|
1. **Parse `$ARGUMENTS`** și pasează-le direct prin:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python scripts/stats.py [--calibration] [--seed N]
|
python -m scripts.stats $ARGUMENTS
|
||||||
```
|
```
|
||||||
|
|
||||||
`--csv data/jurnal.csv` e default-ul scriptului — nu îl pasezi.
|
`--csv data/jurnal.csv` e default-ul scriptului; nu îl pasezi.
|
||||||
|
|
||||||
2. Rulează prin Bash tool. Output-ul vine pe stdout în UTF-8.
|
2. Rulează prin Bash. Output-ul vine pe stdout în UTF-8.
|
||||||
|
|
||||||
3. Afișează output-ul **as-is** către user. Nu reformata, nu re-rezuma, nu interpreta. Scriptul are deja format ales (tabel + secțiuni text).
|
3. **Afișează output-ul as-is** către user. NU reformata, NU re-rezuma, NU inventa numere. Scriptul are deja format ales (tabele + secțiuni text).
|
||||||
|
|
||||||
4. **Interpretare** scurtă (max 3 propoziții) DACĂ user-ul cere explicit sau dacă observi ceva ce merită menționat:
|
4. **Highlight STOPPING_RULE** la final, DOAR dacă observi în output un Set care îndeplinește toate cele 3 thresholds din `STOPPING_RULE.md`:
|
||||||
- În modul backtest: Set-uri cu N ≥ 40 și Wilson lower bound > 50% → candidat pentru GO LIVE (vezi `STOPPING_RULE.md`).
|
- `N ≥ 40` trade-uri non-pending pe acel Set
|
||||||
- În modul `--calibration`: dacă există ≥10 perechi și mismatch rate > 10% pe câmpuri core (`entry/sl/tp0/1/2/outcome_path/max_reached/directie`) → P4 FAIL, vision agent are nevoie de fix (`.claude/agents/m2d-extractor.md`).
|
- `WR ≥ 55%` cu Wilson 95% CI lower bound ≥ 45%
|
||||||
|
- `Expectancy ≥ +0.20R` pe overlay `pl_marius`
|
||||||
|
|
||||||
5. NU edita CSV. NU regenera MD (citire pură).
|
Dacă DA pe vreun Set:
|
||||||
|
|
||||||
|
```
|
||||||
|
🚀 STOPPING RULE: Set <X> îndeplinește pragurile (N=<n>, WR=<wr>, Wilson_LB=<lb>, E=<exp>R). Discută cu user dacă pornește forward paper trading la 0.25R per trade pe acest Set.
|
||||||
|
```
|
||||||
|
|
||||||
|
Dacă **niciun Set** nu îndeplinește toate: nu adăuga highlight. Lasă raportul scriptului să vorbească.
|
||||||
|
|
||||||
|
5. **Highlight calibration P4** (în modul `--calibration`):
|
||||||
|
- Dacă perechi `(manual_calibration, vision_calibration)` < 10 → adăugă: `Insuficient pentru P4 — continuă să acumulezi calibrare (minim 10 perechi).`
|
||||||
|
- Dacă ≥ 10 perechi și mismatch rate > 10% pe câmpuri core (`entry/sl/tp0/tp1/tp2/outcome_path/max_reached/directie`) → adăugă: `⚠️ P4 FAIL: mismatch > 10% pe câmpuri core. Fix promptul vision agent (.claude/agents/m2d-extractor.md) și re-rulează calibrarea.`
|
||||||
|
- Dacă ≥ 10 perechi și mismatch ≤ 10% → adăugă: `✅ P4 PASS: mismatch ≤ 10% pe câmpuri core.`
|
||||||
|
|
||||||
|
6. NU edita CSV. NU regenera MD. Citire pură.
|
||||||
|
|
||||||
## Reguli
|
## Reguli
|
||||||
|
|
||||||
- Read-only. Această comandă nu scrie nimic.
|
- Read-only. Această comandă nu scrie nimic.
|
||||||
- Output-ul scriptului e ground truth — nu inventezi numere.
|
- Output-ul scriptului e ground truth — nu inventezi numere; doar le citești și aplici regulile STOPPING_RULE.
|
||||||
- `calitate` e descriptor biased (post-outcome) — vezi `STOPPING_RULE.md` §3 — raportul îl afișează informational only. NU sugerezi user-ului să folosească `calitate` ca filtru pentru GO LIVE.
|
- `calitate` e descriptor biased post-outcome (vezi `STOPPING_RULE.md` §3) — raportul îl afișează informational only. NU sugera user-ului să folosească `calitate` ca filtru pentru GO LIVE.
|
||||||
- Pentru calibration P4: minimum 10 perechi pentru ca verdictul să aibă sens. Sub 10 perechi → raportezi "insuficient pentru P4 — continuă să acumulezi calibrare".
|
- Highlight-ul `🚀 STOPPING RULE` e doar trigger pentru discuție; decizia GO LIVE rămâne a user-ului, cu caveats-urile semnate în `STOPPING_RULE.md`.
|
||||||
|
|||||||
Reference in New Issue
Block a user