"""MDSRT, Pasul 6 — ieșirea: TP1 la 1:1, breakeven, restul pe trail. Aceeași serie canonică (importată din `mdsrt_ansamblu`), de la intrare încolo: prima parte a poziției iese la ținta simetrică 1:1 (591.00), stopul se mută la breakeven după ce prețul a trecut de jumătatea drumului până la țintă, iar restul merge pe linia de trail — ultimul swing low — până la prima închidere sub ea. Din curs: ținta stabilită împreună cu stopul, simetric; trail pe Bull Trail sau pe swing low, la alegerea traderului; trail-ul se evaluează pe candelă închisă, nu în timpul barei. Numărul de tranșe NU e dat de curs — transcrierea se întrerupe exact acolo. Rulează: python3 gen/strategii/mdsrt_iesire.py """ import re import sys from pathlib import Path sys.path.insert(0, "/workspace/atm-curs-dl") sys.path.insert(0, str(Path(__file__).parent)) from svg_candles import Chart, Level, Mark, Arrow, Zone # noqa: E402 from mdsrt_ansamblu import (serie, CONF, ENTRY, SL, R, TP1, EXIT_I, TRAIL, # noqa: E402 bull_trail) OUT = Path(__file__).with_suffix(".svg") GREEN, RED, BLUE, GRAY, ORANGE = "#188a3e", "#c00", "#1a5fb4", "#555", "#b06000" W = 720 S = 14 cds = serie()[S:EXIT_I + 1] cf, tp_i, ex_i = CONF - S, 22 - S, EXIT_I - S BE = ENTRY # stopul mutat la prețul de intrare half = round(ENTRY + R / 2, 2) # jumătatea drumului până la țintă be_i = next(i for i in range(cf + 1, len(cds)) if cds[i].c > half) # ----------------------------------------------------------------- assert-uri assert cds[cf].c == ENTRY and round(ENTRY - SL, 2) == R assert round(TP1 - ENTRY, 2) == R, "ținta nu e simetrică cu stopul" assert cds[tp_i].h >= TP1 and max(c.h for c in cds[cf + 1:tp_i]) < TP1, "TP1 atins altundeva" assert cds[be_i].c > half and all(c.c <= half for c in cds[cf + 1:be_i]), "breakeven greșit" assert be_i < tp_i, "breakeven-ul ar veni după țintă" # trail: ultimul swing low înaintea întoarcerii; ieșirea e prima închidere sub el assert cds[ex_i].c < TRAIL and all(c.c > TRAIL for c in cds[ex_i - 2:ex_i]) r_exit = round((cds[ex_i].c - ENTRY) / R, 2) assert r_exit == 2.75, r_exit # scara: distanța intrare→TP1 e egală cu distanța intrare→SL, și în preț, și în px print(f"ieșire: TP1 {TP1:.2f} la bara {tp_i + S}, breakeven de la bara {be_i + S} " f"(peste {half:.2f}), trail {TRAIL:.2f}, ieșire {cds[ex_i].c:.2f} = {r_exit:.2f}R") ch = Chart( candles=cds, levels=[ Level(TP1, f"TP1 {TP1:.2f} = 1:1", GREEN, "2 2", label_at="left"), Level(ENTRY, f"intrare {ENTRY:.2f} = breakeven", GRAY, "4 3", label_at="left"), Level(SL, f"SL inițial {SL:.2f} (risc {R:.2f} = 1R)", RED, "4 3", label_at="left"), ], marks=[Mark(ex_i, f"ieșire {cds[ex_i].c:.2f} = {r_exit:.2f}R", GREEN, "above")], zones=[Zone(be_i, tp_i, "de aici stopul stă la breakeven", ORANGE)], arrows=[ Arrow(be_i, f"prețul a trecut de jumătatea drumului ({half:.2f}):\n" f"muți stopul la {BE:.2f} — trade-ul nu mai poate pierde", where="below", price=SL, color=ORANGE, dx=-40, dy=44), Arrow(tp_i, f"ținta 1:1 atinsă: {TP1:.2f}\nrestul poziției rămâne pe trail", where="above", color=GREEN, dx=90, dy=-30), Arrow(ex_i, f"prima închidere sub linia de trail ({TRAIL:.2f}):\n" f"ieși cu restul — se citește pe candelă închisă,\nnu în timpul barei", where="below", price=cds[ex_i].c, color=BLUE, dx=-30, dy=64), ], scale=56.0, gap=24, body_w=12, left=200, width=W, top=44, title="Pasul 6 — ieșirea: ținta 1:1, breakeven, restul pe trail (SPY 5 min, construit)", caption="Câte tranșe faci nu e dat de curs: acolo se întrerupe transcrierea.", ) svg = ch.render() # linia de trail: ultimul swing low de la fiecare pas, desenată ca scară trail_pts = bull_trail(cds, cf) assert trail_pts[-1][1] == TRAIL, (trail_pts[-1], TRAIL) assert len(trail_pts) > 5, trail_pts d = [] for k, (i, p) in enumerate(trail_pts): x0, x1 = ch._cx(i) - ch.gap / 2, ch._cx(i) + ch.gap / 2 d.append(("M" if k == 0 else "L") + f"{x0:.1f},{ch._y(p):.1f}") d.append(f"L{x1:.1f},{ch._y(p):.1f}") trail_svg = (f'') i = svg.rindex("") svg = svg[:i] + " " + trail_svg + "\n" + svg[i:] assert "\n\n" not in svg, "linie goală în SVG" H = float(re.search(r'viewBox="0 0 [\d.]+ ([\d.]+)"', svg).group(1)) for x, y in re.findall(r'