"""Diagrama din `gen/strategii/intrarea_retest_ratat.spec.txt` (TIP: PRET). Pereche pentru `intrarea_doua_variante`: aceeași serie până la candela de semnal inclusiv (0-15), apoi prețul nu mai coboară în corpul ei. Ordinele de la 1/2 și 1/3 rămân neumplute, varianta A merge la +1.7R, varianta B n-are poziție. Seria e construită (fără ticker), nu un trade din curs. """ import re import sys from pathlib import Path sys.path.insert(0, "/workspace/atm-curs-dl") from svg_candles import Chart, Level, Mark, from_closes # noqa: E402 OUT = Path(__file__).resolve().parent / "intrarea_retest_ratat.svg" GREEN, RED, ORANGE, GREY = "#188a3e", "#c00", "#b06000", "#777" # ── 0-15: copiate din intrarea_doua_variante.spec.txt (aceeași serie) ─────── CLOSES_0_15 = [103.60, 103.35, 103.45, 103.10, 102.80, 102.90, 102.50, 102.20, 101.85, 101.95, 101.50, 101.10, # downtrend spre suport 100.60, 100.40, 100.35, # la suport 102.15] # candela de semnal WICKS_0_15 = [(0.15, 0.15)] * 16 # 12-14 la suport: aceleași fitiluri ca în intrarea_doua_variante.py WICKS_0_15[12] = (0.10, 0.15) WICKS_0_15[13] = (0.10, 0.50) # low 99.90 (wick sub suportul de 100.00) WICKS_0_15[14] = (0.10, 0.15) WICKS_0_15[15] = (0.15, 0.10) # semnal: high 102.30, low 100.25 START = 103.80 # open-ul candelei 0 # ── 16-31: plecare fără pullback adânc ────────────────────────────────────── CLOSES_16_31 = [102.40, 102.70, 102.55, 102.95, 103.30, 103.20, 103.60, 104.00, 103.85, 104.30, 104.70, 104.60, 105.10, 105.40, 105.30, 106.00] WICKS_16_31 = [(0.15, 0.15)] * 16 WICKS_16_31[0] = (0.15, 0.25) # low-ul candelei 16 = 101.90 cds = from_closes(CLOSES_0_15 + CLOSES_16_31, wicks=WICKS_0_15 + WICKS_16_31, start=START) SL, SIG = 99.90, 15 sig = cds[SIG] half = (sig.o + sig.c) / 2 third = sig.c - (sig.c - sig.o) / 3 entry_a = sig.c low_after = min(c.l for c in cds[SIG + 1:]) r_a = (cds[31].c - entry_a) / (entry_a - SL) # ── assert-urile din specificație ─────────────────────────────────────────── assert len(cds) == 32 # 1. open == close-ul barei anterioare assert all(abs(cds[i].o - cds[i - 1].c) < 1e-9 for i in range(1, len(cds))) # 2. 0-15 identice cu intrarea_doua_variante (lista e copiată din spec-ul ei) assert abs(sig.o - 100.35) < 1e-9 and abs(sig.c - 102.15) < 1e-9 assert abs(sig.h - 102.30) < 1e-9 and abs(sig.l - 100.25) < 1e-9 assert abs(cds[13].l - 99.90) < 1e-9 assert abs(min(c.l for c in cds[11:15]) - SL) < 1e-9 and sig.l > SL assert all(c.l > SL for i, c in enumerate(cds[11:15], 11) if i != 13) assert abs(half - 101.25) < 1e-9 and abs(third - 101.55) < 1e-9 # 3. niciun ordin nu se umple assert low_after > 101.55, low_after assert abs(cds[16].l - 101.90) < 1e-9 and low_after >= 101.80 assert abs(low_after - 101.90) < 1e-9 # „cel mai jos după semnal" e chiar candela 16 # 4. finalul și R-ul assert abs(cds[31].c - 106.00) < 1e-9 assert round(r_a, 2) == 1.71, r_a R_TEXT = f"+{r_a:.1f}R" assert R_TEXT == "+1.7R" # 5. candela 23 și niciun „suport" inventat în 17-23 assert abs(cds[23].c - 104.00) < 1e-9 MARKED = [SL, half, third, entry_a] assert not any(abs(c.l - p) < 1e-6 for c in cds[17:24] for p in MARKED) levels = [ Level(SL, "SL 99.90", RED, dash=""), Level(third, f"ordin 1/3 {third:.2f} — neumplut", ORANGE), Level(half, f"ordin 1/2 {half:.2f} — neumplut", ORANGE), Level(entry_a, f"A: close {entry_a:.2f}", GREEN), ] marks = [ Mark(SIG, "semnal", GREEN, "above"), # dy=-16: textul stă chiar la înălțimea low-ului, între eticheta 1/3 și linia A Mark(16, f"cel mai jos după semnal: {low_after:.2f}", GREY, "below", dy=-16), Mark(23, "NU muți ordinul aici: sub 104.00 nu e niciun nivel", RED, "above"), Mark(31, f"A: {R_TEXT} · B: 0 (fără poziție)", GREY, "above"), ] CAPTION = ["Exemplu construit, fără ticker. «Poate să nu mai facă, poate nu mai face niciodată.»", "Ai ratat trade-ul; aștepți următoarea structură."] ch = Chart( candles=cds, levels=levels, marks=marks, scale=80.0, width=660, gap=16, body_w=9, left=40, title="Exemplu construit (fără ticker) — 15 min", caption=CAPTION[0], ) svg = ch.render() def reanchor(svg, text, anchor, dx): """Mark-urile ies centrate; unele trebuie să curgă într-o parte, unde e loc liber (stânga lui 15: candelele 13-14 sunt jos; dreapta lui 16: toate low-urile >= 102.25; stânga lui 23: toate high-urile < 104.00).""" pat = re.compile(r'' + re.escape(text) + ')') svg, n = pat.subn(lambda m: f'' + re.escape(CAPTION[0]) + '', svg) assert m y2 = float(m[1]) + 17 svg = svg.replace(m[0], m[0] + f'\n {CAPTION[1]}') vb = re.search(r'viewBox="0 0 660 ([\d.]+)"', svg) assert vb svg = svg.replace(vb[0], f'viewBox="0 0 660 {float(vb[1]) + 17:.0f}"') assert svg.count("\n\n") == 0, "linie goală în SVG — rupe markdown-ul" OUT.write_text(svg) print(f"low după semnal {low_after:.2f} | A {R_TEXT} ({r_a:.4f}) | scris {OUT}")