#!/usr/bin/env python3
"""MBT-10 — singura bucată reconstituibilă: close peste pivotul daily.
Aceleași bare ca la pasul „unde" (importate din `hammer_mbt10_mbt_confluente`),
tăiate în jurul trigger-ului. Exemplul e pe 60 de minute, ca în material: bara
18 atinge pivotul 89.60 în timpul zilei, dar se închide sub el (nu e semnal),
iar bara 19 se închide la 89.90, peste pivot — aici intri.
Pivotul daily NU e un nivel fix pe grafic: se recalculează în fiecare zi. Pe
60 de minute el e același pentru toate barele unei zile, așa că aici e desenat
doar peste barele zilei de intrare, între două linii de separare de zi. În
ziua dinainte era alt număr, pe care materialul nu-l dă — de aceea nu-l
inventăm, doar spunem că era altul.
Rulare: python3 gen/strategii/hammer_mbt10_mbt_ppd.py
"""
import re
import sys; sys.path.insert(0, "/workspace/atm-curs-dl")
sys.path.insert(0, "/workspace/atm-curs-dl/gen")
sys.path.insert(0, "/workspace/atm-curs-dl/gen/strategii")
from pathlib import Path
from eticheta_libera import eticheta_libera
from hammer_mbt10_mbt_confluente import (CLOSE_I, INTRARE, PPD, SUP_W,
ZI_INTRARE, 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"
ET_PIVOT = ("pivotul daily al zilei de", "intrare: 89.60 (ieri, altul) →")
cds = serie()
I0, I1 = 9, 22
w = cds[I0:I1 + 1]
sh = lambda i: i - I0 # noqa: E731
NU, DA = CLOSE_I - 1, CLOSE_I
assert cds[NU].h > PPD > cds[NU].c, "bara 18 nu mai e contraexemplul așteptat"
assert cds[DA].c > PPD and round(cds[DA].c, 2) == INTRARE
assert 0 <= sh(NU) < len(w) and sh(DA) < len(w), "fereastra nu prinde cele două bare"
assert max(c.c for c in cds[I0:DA]) < PPD, "o bară din fereastră închide deja peste pivot"
assert I0 < ZI_INTRARE[0] and ZI_INTRARE[1] <= I1, \
"ziua intrării trebuie să se vadă întreagă, cu bare de altă zi de o parte și de alta"
ch = Chart(
candles=w,
levels=[Level(SUP_W, "suport weekly 88.00", GREY, label_at="right")],
zones=[Zone(sh(NU), sh(DA), "", ORANGE, p_top=90.4)],
arrows=[
Arrow(sh(NU), "a atins 89.70 în timpul barei,\ndar s-a închis la 89.40, sub pivot:\nnu e semnal",
where="below", color=RED, dx=-190, dy=40),
Arrow(sh(DA), "s-a închis la 89.90, peste pivot:\naici intri, la close-ul barei",
where="above", color=GREEN, dx=-70, dy=-20),
],
scale=44.0, gap=26, body_w=13, left=64, width=680, top=58, vol_h=60, vol_label="volum",
title="MBT-10 — condiția de preț: close peste pivotul daily (60 de minute)",
)
svg = ch.render()
# --- pivotul daily: un segment peste ziua de intrare, nu o linie fixă -------
# aceeași corecție de offset ca în `_mbt_stop`: `_render` mută `top` ca să facă
# loc titlului și săgeților, deci `_y` singur nu nimerește coordonatele finale.
OFF = float(re.search(r''
f''
f''
+ "".join(
f'{t}' for i, t in enumerate(ET_PIVOT))
)
svg = svg.replace("", pivot + "")
m = re.search(r'viewBox="0 0 (\d+) (\d+)"', svg)
W, H = int(m.group(1)), int(m.group(2))
linii = [
("Pivotul daily se recalculează în fiecare zi din maximul, minimul și închiderea zilei "
"precedente.", "#333"),
("Pe 60 de minute e același nivel pentru toate barele unei zile, așa că e desenat doar "
"între cele două", "#333"),
("linii subțiri care taie ziua intrării — nu peste tot graficul.", "#333"),
("Asta e tot ce se poate verifica din MBT-10 fără indicatorul proprietar — „prima "
"componentă\" din el,", GREY),
("cum îi spune materialul; restul formulei nu e publicat nicăieri.", 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)) + "")
eticheta_libera(svg, "mbt_ppd",
{ET_PIVOT}, rects=True)
assert "\n\n" not in svg, "linie goală în SVG"
OUT.write_text(svg, encoding="utf-8")
print(f"scris {OUT.name} ({W}x{H + add})")