"""Diagrama din `gen/strategii/atmi_exemplu.spec.txt` (TIP: PRET). Exemplul real din curs (ATMI / SPY weekly): corecție de context ≥4 %, intrare pe 27.01.2005 la 117.43 după BIM + candelă verde, fără stop-loss standard, urcare lentă până la TP1 +10 % = 129.17, atins ~1 an mai târziu (data exactă nesigură în ASR). Serie continuă de 38 de candele weekly (from_closes), panou de volum, niveluri reale (intrare / TP1) și marcaje ancorate. Toate cifrele vin din `summaries/04_MODUL_3/03_strategia_2_atmi.md` (liniile citate în spec); singurul număr construit de mine e swing high-ul ~123.00, care trebuie să conțină corecția de context. """ import sys from pathlib import Path sys.path.insert(0, "/workspace/atm-curs-dl") from svg_candles import Chart, Level, Mark, MA, from_closes # noqa: E402 OUT = Path(__file__).resolve().parent / "atmi_exemplu.svg" # ── cifrele din material ──────────────────────────────────────────────────── ENTRY = 117.43 # 04_MODUL_3/03_strategia_2_atmi.md:358-363 TP = 129.17 # TP1 = +10 % pe 117.43 → 129.17 (":170-171, 358-363") SWING_HIGH = 123.00 # construit de mine ca să conțină corecția ≥4 % ENTRY_I = 17 # candela de intrare (verde, precedată de BIM) TP_I = 37 # ultima candelă: TP1 atins BIM_I = ENTRY_I - 1 # BIM (bară de inversare bearish) înaintea candelei verzi # ── structura seriei: 12 sus → 6 corecție → intrare → 20 spre TP ─────────── closes = [ # ~12 candele de urcare spre swing high ~123.00 115.80, 116.50, 117.20, 117.90, 117.60, 118.30, 119.00, 119.70, 120.40, 121.00, 121.70, 122.70, # ~6 candele de corecție, de la 123.00 în zona de intrare 122.00, 121.10, 120.10, 119.00, 117.00, 117.43, # candela de intrare (verde) # ~20 candele de urcare de la 117.43 spre 129.17 118.00, 118.55, 119.05, 119.50, 119.95, 120.40, 120.85, 121.25, 121.65, 122.10, 122.50, 122.95, 123.40, 123.85, 124.30, 125.00, 126.00, 127.10, 128.40, 129.17, ] assert len(closes) == 38, len(closes) wicks = [(0.25, 0.30)] * len(closes) wicks[0] = (0.35, 0.35) wicks[11] = (0.30, 0.25) # high = 122.70 + 0.30 = 123.00 (swing high exact) wicks[BIM_I] = (0.15, 0.45) wicks[ENTRY_I] = (0.20, 0.40) wicks[TP_I] = (0.00, 0.30) # high = 129.17 exact, ca TP să fie max(high) vols = [42, 40, 44, 47, 39, 45, 48, 52, 50, 55, 58, 62, 57, 61, 66, 72, 84, 70, 58, 55, 53, 57, 54, 56, 59, 55, 57, 60, 58, 61, 63, 60, 64, 66, 68, 72, 76, 88] cds = from_closes(closes, wicks=wicks, vols=vols, start=115.30) # ── assert-urile din specificație ─────────────────────────────────────────── entry = cds[ENTRY_I].c tp = cds[TP_I].c swing_high = max(c.h for c in cds[:ENTRY_I]) assert abs(entry - 117.43) < 0.05, entry assert abs(tp - 129.17) < 0.05, tp assert abs(tp / entry - 1.10) < 0.005, tp / entry assert (swing_high - entry) / swing_high >= 0.04, (swing_high, entry) assert abs(entry - cds[ENTRY_I].c) < 0.05 assert abs(max(c.h for c in cds[-10:]) - tp) < 0.05, max(c.h for c in cds[-10:]) # structura care susține afirmațiile din text assert abs(swing_high - SWING_HIGH) < 0.05, swing_high assert cds[ENTRY_I].c > cds[ENTRY_I].o, "candela de intrare trebuie să fie verde" assert cds[BIM_I].c < cds[BIM_I].o, "BIM-ul dinaintea intrării trebuie să fie bearish" assert any(c.vol is not None for c in cds), "lipsește panoul de volum" n_entry_to_tp = TP_I - ENTRY_I + 1 assert 18 <= n_entry_to_tp <= 23, n_entry_to_tp TP_LABEL = "TP1 atins ~1 an mai târziu (data exactă neclară în transcriere — ASR)" assert "~1 an" in TP_LABEL levels = [ Level(ENTRY, "intrare 117.43", "#188a3e", label_at="left"), Level(TP, "TP1 129.17 (+10 %)", "#1a5fb4"), ] marks = [ Mark(11, f"swing high ~{SWING_HIGH:.2f}", "#c00", "above"), Mark(BIM_I, "BIM", "#777", "above"), Mark(ENTRY_I, "27.01.2005", "#188a3e", "below"), Mark(TP_I, "TP1", "#1a5fb4", "below"), ] # nu există nicio linie de stop-loss în desen assert not any("stop" in t.lower() for t in [lv.text for lv in levels] + [mk.text for mk in marks]) assert len(levels) == 2, "doar intrare și TP; strategic nu există stop standard" # etichetele lungi merg ca linii de text sub grafic, ca să nu se bată cu # candelele din dreapta-sus (unde urcarea spre TP nu lasă loc liber) cds[TP_I - 1].note = "după TP: capital + profit → cash până la următorul trigger valid" cds[TP_I].note = TP_LABEL ch = Chart( candles=cds, levels=levels, marks=marks, mas=[MA(20, "#b06000", dash="4 3")], scale=9.5, width=660, gap=15, body_w=9, left=40, vol_h=70, vol_label="volum", title="SPY — weekly: intrare 117.43 (27.01.2005) → TP +10 % = 129.17", caption="Swing high ~123.00 construit de mine; cifrele de intrare/TP sunt din material.", ) svg = ch.render() assert svg.count("\n\n") == 0, "linie goală în SVG — rupe markdown-ul" OUT.write_text(svg) print(f"serie {len(cds)} candele | entry {entry:.2f} @ {ENTRY_I} | " f"tp {tp:.2f} @ {TP_I} | swing high {swing_high:.2f} " f"(corecție {(swing_high - entry) / swing_high * 100:.2f} %) | " f"entry→TP {n_entry_to_tp} candele (~1 an)") print(f"scris {OUT}")