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

5.1 KiB
Raw Blame History

description, argument-hint
description argument-hint
Adaugă rapid un trade în jurnal.csv. 6 câmpuri minim, restul derivate auto. Manual entry rapidă pentru backtest/forward paper. [--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):

    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:

    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":

    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.