#!/usr/bin/env python3 """MBT-10 — ieșirea: ținta e o structură din stânga, nu un procent. Toată seria pasului „unde" (importată), de la vârful din care a pornit coborârea până la atingerea lui înapoi. Ținta 95.20 nu e aleasă: e high-ul ultimului maxim dinaintea coborârii, verificat prin assert. Fișierul principal nu fixează nicio regulă proprie de take-profit — de aceea ținta e numită pe desen ca structură, nu ca regulă. Rulare: python3 gen/strategii/hammer_mbt10_mbt_iesire.py """ import re import sys; sys.path.insert(0, "/workspace/atm-curs-dl") sys.path.insert(0, "/workspace/atm-curs-dl/gen/strategii") from pathlib import Path from hammer_mbt10_mbt_confluente import CLOSE_I, INTRARE, SL, TP, VARF, serie from svg_candles import Arrow, Chart, Level, Zone OUT = Path(__file__).with_suffix(".svg") GREEN, RED, BLUE, ORANGE, GREY = "#188a3e", "#c00", "#1a5fb4", "#b06000", "#555" cds = serie() RISC = round(INTRARE - SL, 2) R_TINTA = round((TP - INTRARE) / RISC, 2) prim_tp = next(i for i in range(CLOSE_I + 1, len(cds)) if cds[i].h >= TP) # --- verificări ------------------------------------------------------------- assert round(cds[VARF].h, 2) == TP, "ținta nu e high-ul vârfului" assert max(c.h for c in cds[VARF + 1:prim_tp]) < TP, "structura e depășită înainte de țintă" # cifra din material/fișă e 2,0R (summaries/08_ANALIZA_ZILNICA/02_mbt10.md:451): # raportul exact e 2.038, dar se rotunjește la o zecimală la 2.0 — verificăm # exact ce se afișează pe desen, nu valoarea brută. assert prim_tp == 26 and round(R_TINTA, 1) == 2.0, (prim_tp, R_TINTA) assert min(c.l for c in cds[CLOSE_I:]) > SL, "stopul ar fi fost atins înainte de țintă" assert cds[VARF].h > cds[CLOSE_I].c > SL, "ordinea vârf / intrare / stop e greșită" zile = prim_tp - CLOSE_I assert zile == 7, zile ch = Chart( candles=cds, levels=[Level(TP, "ținta 95.20 = ultimul maxim dinaintea coborârii", BLUE), Level(INTRARE, "intrare 89.90", GREEN, label_at="left"), Level(SL, "SL 87.30", RED, label_at="left")], zones=[Zone(VARF, VARF, "de aici a pornit coborârea", ORANGE, p_top=95.9), Zone(CLOSE_I, prim_tp, "drumul până la structură: 7 bare", GREEN)], arrows=[ Arrow(prim_tp, f"ieși la 95.20 (+{R_TINTA:.1f}R):\nprima structură care a oprit\nprețul " "ultima dată", price=TP, where="below", color=BLUE, dx=-200, dy=54), ], scale=26.0, gap=17, body_w=10, left=54, width=700, top=58, vol_h=60, vol_label="volum", title="MBT-10 — ieșirea la prima structură din stânga (exemplu construit)", ) svg = ch.render() m = re.search(r'viewBox="0 0 (\d+) (\d+)"', svg) W, H = int(m.group(1)), int(m.group(2)) linii = [ ("Materialul nu dă o regulă proprie de take-profit la MBT-10. Ce au în comun toate " "exemplele lui e că", "#333"), ("ținta e o structură vizibilă în stânga: un vârf anterior, ultimul maxim mai jos, sau " "închiderea unui gap.", "#333"), (f"Aici: 89.90 → 95.20 = {R_TINTA:.1f}R, în {zile} bare. Cifrele trade-ului sunt din " "exemplul construit al materialului.", GREY), ] add = 16 * len(linii) + 10 svg = svg.replace(f'viewBox="0 0 {W} {H}"', f'viewBox="0 0 {W} {H + add}"') svg = svg.replace("", "".join( f'{t}' for i, (t, c) in enumerate(linii)) + "") assert "\n\n" not in svg, "linie goală în SVG" # ce se vede pe desen: ambele etichete trebuie să spună 2,0R, ca în material assert f"(+{R_TINTA:.1f}R)" in svg and f"= {R_TINTA:.1f}R," in svg, \ "eticheta de ieșire nu afișează 2,0R" assert "2.04R" not in svg, "a rămas eticheta veche cu 2.04R" OUT.write_text(svg, encoding="utf-8") print(f"scris {OUT.name} ({W}x{H + add}); ținta atinsă la bara {prim_tp} = +{R_TINTA:.1f}R")