"""MP² — cei doi pivoți și condiția M (Pasul 2 din `02_mp2.md`). Aceeași serie ca tot capitolul. Aici nu e niciun trade: doar cele două linii de pivot și granița dintre „nu ai voie long" și „ai voie să cauți trigger". Dedesubt, aritmetica: pivotul mic al zilei 4 iese din OHLC-ul zilei 3, cu formula cursului. Cifrele nu sunt scrise de mână — ies din serie. Rulare: python3 gen/strategii/mp2_pivoti.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, Zone # noqa: E402 import mp2_serie as S # noqa: E402 OUT = Path(__file__).with_suffix(".svg") RED, BLUE, GRAY, GREEN = "#c00", "#1a5fb4", "#777", "#188a3e" W = 720 zi = S.zilnice(S.CDS) z3 = zi[S.ZI4 - 1] # ziua 3, cea din care iese pivotul zilei 4 assert S.pp(z3.h, z3.l, z3.c) == S.PPD[S.ZI4] assert S.pp(*S.PPW_OHLC) == S.PPW hot = S.ZI4 * S.BARE_ZI # prima bară a zilei 4 ch = Chart( candles=S.CDS, levels=[Level(S.PPW, f"pivot weekly (mare) {S.PPW:.2f} — nu se mișcă toată săptămâna", GRAY, "8 4", "right")], zones=[Zone(0, hot - 1, "pivotul mic e SUB cel mare: M neîndeplinit, nu cauți long", RED), Zone(hot, len(S.CDS) - 1, "pivotul mic e PESTE cel mare: M îndeplinit", GREEN)], scale=15.0, gap=15, body_w=9, left=52, width=W, top=40, title="Pasul 2 — cei doi pivoți: unde stă cel mic față de cel mare") svg = ch.render() off = S.offset(svg, ch) inject = [ f'', ] # doar cele două valori care contează: ultima de sub pivotul mare și prima de peste for d, dy_, b in ((S.ZI4 - 1, 14, 3), (S.ZI4, -7, 6)): inject.append( f'{S.PPD[d]:.2f}') svg = S.injecteaza(svg, inject) # --- aritmetica, sub grafic --------------------------------------------------- h = float(re.search(r'viewBox="0 0 [\d.]+ ([\d.]+)"', svg).group(1)) linii = [ ("Linia albastră în trepte e pivotul daily (mic), recalculat în fiecare ședință; " "linia gri e pivotul weekly (mare).", "#333"), ("Pivotul mare, al săptămânii încheiate: PP = (High + Low + Close) / 3 = " f"({S.PPW_OHLC[0]:.2f} + {S.PPW_OHLC[1]:.2f} + {S.PPW_OHLC[2]:.2f}) / 3 = " f"{S.PPW:.2f}", GRAY), ("Pivotul mic al zilei a 4-a, din ziua a 3-a încheiată: " f"({z3.h:.2f} + {z3.l:.2f} + {z3.c:.2f}) / 3 = {S.PPD[S.ZI4]:.2f}", BLUE), (f"{S.PPD[S.ZI4]:.2f} este peste {S.PPW:.2f}, iar în ziua a 3-a era " f"{S.PPD[S.ZI4 - 1]:.2f}, adică dedesubt: M îndeplinit, printr-un crossing proaspăt.", GREEN), ] blocs = [f'{t}' for i, (t, c) in enumerate(linii)] H = h + 6 + 19 * len(linii) svg = svg.replace(f'viewBox="0 0 {W} {h:.0f}"', f'viewBox="0 0 {W} {H:.0f}"', 1) if f'viewBox="0 0 {W} {H:.0f}"' not in svg: # lățimea a fost lărgită vb = re.search(r'viewBox="0 0 ([\d.]+) ([\d.]+)"', svg) svg = svg.replace(vb.group(0), f'viewBox="0 0 {vb.group(1)} {H:.0f}"', 1) svg = svg.replace("", " " + "\n ".join(blocs) + "\n") w = float(re.search(r'viewBox="0 0 ([\d.]+)', svg).group(1)) assert max(len(t) for t, _ in linii) * 5.7 + 24 < w, "linia de aritmetică iese din pânză" S.scrie(OUT, svg, w, H)