#!/usr/bin/env python3 """Aceeași candelă, două contexte: hammer (după scădere) vs. hanging man (după urcare). Două panouri alăturate, aceeași scară px/unitate. Bara 9 e IDENTICĂ în ambele (o 63.05, h = c 63.30, l 62.10) — verificat prin assert; ce diferă e ce s-a întâmplat înaintea ei. Panourile nu împart axa de preț: seriile trăiesc în zone de preț diferite, iar comparația cerută aici e de context, nu de nivel. Rulare: python3 gen/strategii/hammer_mbt10_bh_trend.py """ import re import sys; sys.path.insert(0, "/workspace/atm-curs-dl") from pathlib import Path from svg_candles import Arrow, Chart, Zone, from_closes OUT = Path(__file__).with_suffix(".svg") GREEN, RED, BLUE, ORANGE, GREY = "#188a3e", "#c00", "#1a5fb4", "#b06000", "#555" HAM = (63.05, 63.30, 62.10, 63.30) # o, h, l, c — bara 9, în ambele panouri JOS = [68.00, 67.20, 66.50, 66.80, 65.60, 64.90, 65.10, 64.20, 63.05, 63.30, 63.35, 63.80] SUS = [58.00, 58.70, 59.40, 59.20, 60.30, 61.00, 61.80, 62.40, 63.05, 63.30, 62.00, 61.40] def serie(closes): w = [(0.15, 0.15)] * len(closes) w[9] = (0.00, 0.95) # bara-hammer: high = close, fitil jos 0.95 return from_closes(closes, wicks=w, start=closes[0] + (0.4 if closes[0] > 60 else -0.4)) L, R = serie(JOS), serie(SUS) # --- verificări ------------------------------------------------------------- for s, nume in ((L, "stânga"), (R, "dreapta")): for i in range(1, len(s)): assert abs(s[i].o - s[i - 1].c) < 1e-9, f"{nume}: open[{i}] != close[{i-1}]" b = s[9] assert (round(b.o, 2), round(b.h, 2), round(b.l, 2), round(b.c, 2)) == HAM, (nume, b) assert (L[9].o, L[9].h, L[9].l, L[9].c) == (R[9].o, R[9].h, R[9].l, R[9].c), \ "bara 9 trebuie să fie identică în ambele panouri" corp, jos = HAM[3] - HAM[0], HAM[0] - HAM[2] assert jos >= 2 * corp, "bara 9 nu trece regula de formă" assert L[8].c < L[0].c - 4, "stânga: scăderea nu se vede" assert R[8].c > R[0].c + 4, "dreapta: urcarea nu se vede" assert L[10].c > L[9].h, "stânga: bara 10 nu confirmă peste high-ul hammer-ului" assert R[10].c < R[9].l, "dreapta: bara 10 nu închide sub low-ul candelei" # --- desen ------------------------------------------------------------------ W, PW = 780, 358 PX = [24, 24 + PW + 20] SCALE, TOP, SHIFT = 26.0, 104, 60 panels, inalt = [], [] for px, cds, (zt, zc), arr in ( (PX[0], L, ("scădere de 9 candele", RED), [Arrow(9, "hammer 63.30 / 62.10: prețul a fost dus la 62.10\nși readus sus, la 63.30", where="below", color=ORANGE, dx=-70, dy=34), Arrow(10, "close 63.35, peste high-ul hammer-ului:\nsemnalul e valid, aici intri", where="above", color=GREEN, dx=-96, dy=-24)]), (PX[1], R, ("urcare de 9 candele", GREEN), [Arrow(9, "aceeași candelă 63.30 / 62.10, dar după o urcare:\nse numește hanging man și avertizează de scădere", where="below", color=RED, dx=-250, dy=98), Arrow(10, "close 62.00, sub low-ul ei: scăderea\nîncepe — nu era semnal de cumpărare", where="above", color=RED, dx=-70, dy=-18)]), ): ch = Chart(candles=cds, arrows=arr, zones=[Zone(0, 8, zt, zc)], scale=SCALE, gap=24, body_w=12, left=px + 46, width=px + PW, top=TOP) body = ch._render() assert f'viewBox="0 0 {px + PW} ' in body, f"panoul {px}: ceva iese din cadru" assert ch.scale == SCALE corp_panou = body.split(">", 1)[1].rsplit("", 1)[0].strip() panels.append(f'{corp_panou}') inalt.append(float(re.search(r'viewBox="0 0 [\d.]+ ([\d.]+)"', body).group(1))) H = int(max(inalt)) + SHIFT + 46 parts = [ f'', '' 'Aceeași candelă, două contexte — daily, exemplu construit', f'' 'DA — după o scădere: hammer', f'' 'NU — după o urcare: hanging man', f'', *panels, f'Forma nu spune nimic singură: hammer-ul ' 'e pattern de întoarcere doar după o scădere. Aceeași bară după o urcare', f'e hanging man și are sensul opus. ' 'Prețurile sunt construite; regula de context e a cursului.', "", ] svg = "\n ".join(parts).replace("\n ", "\n") 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})")