Cea mai grava, si cea care a cerut refacerea seriei: exemplul central de MBT-10 era luat de pe 60 de minute si bagat in procedura de daily, cu barele numite "zile", desi sursa spune explicit de ce nu merge pe daily. Pe langa asta, suportul fusese schimbat din 88.00 (testat de trei ori, cu compresie, cum e in sursa) in 87.50 cu un double bottom si o divergenta de volum imprumutate din alt exemplu. Seria e refacuta pe exemplul materialului, cu assert pe cele trei atingeri ale lui 88.00 si pe compresia varfurilor. Adaosurile au fost scoase, nu doar marcate: cu ele in desen, suportul din sursa n-ar fi avut sens. Aritmetica a supravietuit neatinsa. Restul: stopul de 60.40 sta acum sub o structura reala; pivotul daily nu mai e o linie fixa peste tot graficul, ci un segment peste ziua intrarii; SL-ul de pe LABU respecta regula proprie de 5 centi; citatul de la A2 nu mai e dat ca al autorului; pragul de 1-2% isi spune originea (cursul da 0,5%, pe 60 min); o singura conventie de distanta, impartirea la nivel; swing low definit la fel in pas si in glosar. eticheta_libera a prins 7 suprapuneri reale. La bh_aplus a trebuit rulat pe fiecare panou separat: wrapper-ul le muta cu <g transform>, pe care unealta nu-l citeste - de notat pentru data viitoare. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ThN7ixZrowca8aTGrK1MUJ
77 lines
3.8 KiB
Python
77 lines
3.8 KiB
Python
#!/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 (60 de minute)",
|
|
)
|
|
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 de 60 de minute. Cifrele "
|
|
"trade-ului sunt din exemplul 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("</svg>", "".join(
|
|
f'<text x="24" y="{H + 10 + 16 * i}" fill="{c}">{t}</text>'
|
|
for i, (t, c) in enumerate(linii)) + "</svg>")
|
|
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")
|