Files
atm-backtesting/.claude/commands/m2d-log.md

143 lines
5.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
description: Adaugă rapid un trade în jurnal.csv. 6 câmpuri minim, restul derivate auto. Manual entry rapidă pentru backtest/forward paper.
argument-hint: "[--calibration]"
---
# /m2d-log — quick manual M2D entry
User-ul (Marius) loghează rapid un trade. 6 câmpuri esențiale obligatorii, restul derivate automat de `scripts/manual_log.py`.
## Workflow
1. **Parse `$ARGUMENTS`** — flag `--calibration` produce `source=manual_calibration`; altfel `source=manual`.
2. **Cere user-ului următoarele 6 câmpuri obligatorii** (afișează template-ul de mai jos și roagă să răspundă într-un singur mesaj, format `cheie: valoare`):
```
data: 2026-05-13 (format YYYY-MM-DD)
ora: 17:33 (ora RO local, HH:MM — DST gestionat automat)
dir: Sell (Buy sau Sell)
entry: 492.47 (prețul de intrare = close trigger candle)
sl: 492.77 (SL absolute price)
out: TP0→pending (SL | TP0→SL | TP0→TP1 | TP0→TP2 | TP0→pending | pending)
```
Opționale (utilizatorul le poate omite — defaults aplicate):
```
inst: DIA (default DIA — alternative: US30, other)
calitate: Clară (default n/a — Clară | Mai mare ca impuls | Slabă)
tf_mic: 1min (default 1min — alternativ: 3min)
tf_mare: 5min (default 5min — alternativ: 15min)
note: ... (default empty)
```
3. **Parsează răspunsul user-ului**. Tolerant la spații în jurul valorilor. Dacă lipsește un câmp obligatoriu → afișează ce lipsește și ceri din nou.
4. **Construiește dict-ul** apelând helper-ul Python (printr-un singur `python -c`):
```bash
python -c "
import json
from scripts.manual_log import build_extraction
d = build_extraction(
data='<data>',
ora_ro='<ora>',
directie='<dir>',
entry=<entry>,
sl=<sl>,
outcome_path='<out>',
instrument='<inst_or_DIA>',
tf_mare='<tf_mare_or_5min>',
tf_mic='<tf_mic_or_1min>',
calitate='<calitate_or_n/a>',
note='<note_or_empty>',
)
import pathlib
basename_no_ext = d['screenshot_file'].rsplit('.', 1)[0]
p = pathlib.Path(f'data/extractions/{basename_no_ext}.manual.json')
p.parent.mkdir(parents=True, exist_ok=True)
p.write_text(json.dumps(d, ensure_ascii=False, indent=2), encoding='utf-8')
print(json.dumps({'json_path': str(p), 'screenshot_file': d['screenshot_file']}, default=str))
"
```
Helper-ul calculează automat:
- `ora_utc` din `ora_ro` (DST-aware Europe/Bucharest)
- `tp0` = entry ± 0.4·|entrysl| (sign în funcție de directie)
- `tp1` = entry ± 0.6·|entrysl|
- `tp2` = entry ± |entrysl| (simetric SL)
- `risc_pct` = 100·|entrysl|/entry
- `max_reached` din `outcome_path` (SL→SL_first, TP0→SL→TP0, TP0→TP1→TP1, ...)
- `be_moved` din `outcome_path` (False pentru SL/pending, True pentru orice TP0→...)
- `screenshot_file` generat dacă nu e prezent: `<data>-<inst>-<ora_compactă>.png`
- Cross-field ordering validat (Buy: sl<entry<tp0<tp1<tp2; Sell invers)
5. **Append la CSV**:
```bash
python -c "
from pathlib import Path
from scripts.append_row import append_extraction
import json
r = append_extraction(Path('<json_path>'), source='<source>')
print(json.dumps(r, default=str))
"
```
6. **Dacă `status == "ok"`**:
```bash
python -m scripts.regenerate_md
```
Apoi afișează concis:
```
✅ Trade #<id> adăugat — set=<set>, outcome=<outcome_path>, pl_marius=<pl>, pl_theoretical=<pl_t>
```
7. **Dacă `status == "rejected"`**:
```
❌ Respins: <reason>
```
Dacă `reason` conține "duplicate" → trade-ul cu acel `(screenshot_file, source)` există deja. Dacă vrei să-l suprascrii, șterge linia din `data/jurnal.csv` și re-rulează (sau cere user-ului să specifice `note: <diferit>` ca să forțeze basename diferit).
Dacă `reason` conține "validation" → câmpurile au violat constraint-urile pydantic; reîntrebezi user-ul ce să corecteze.
8. **Errori în parsing user**: dacă user-ul răspunde ambiguu (ex: lipsește `dir`, sau `entry` nu e număr), afișează ce trebuie corectat și revii la step 2 cu valorile parțiale păstrate.
## Reguli
- NU edita CSV direct.
- NU regenera MD pe rejection.
- Helper-ul `build_extraction` ridică `ValueError` dacă: `entry == sl`, `Buy` cu `sl >= entry`, `Sell` cu `sl <= entry`. Propaga eroarea către user cu mesaj clar.
## Exemple
**Cel mai scurt input valid**:
```
data: 2026-05-13
ora: 17:33
dir: Sell
entry: 492.47
sl: 492.77
out: TP0→pending
```
→ generează screenshot_file=`2026-05-13-dia-1733.png`, calculează ora_utc=14:33, tp0=492.35, tp1=492.29, tp2=492.17, risc_pct=0.0609, max_reached=TP0, be_moved=True, set=A2 (Mie 17:33).
**Cu calitate și note**:
```
data: 2026-05-13
ora: 17:33
dir: Sell
entry: 492.47
sl: 492.77
out: TP0→TP1
calitate: Clară
note: bună retragere dimineața, news risc zero
```
**Calibrare**: `/m2d-log --calibration` → source=manual_calibration. Folosit cu `/backtest --calibration <screenshot>` pe același screenshot pentru P4 mismatch report.