"""ATMI — Pasul 1: PPQ și SQ, calculați din trimestrul precedent. Un singur grafic daily care acoperă sfârșitul trimestrului precedent (zona gri) și începutul celui nou. Din H/L/C-ul trimestrului precedent ies, prin formula standard de pivot point, cele două niveluri pe care ATMI cumpără: PPQ (pivotul trimestrial) și SQ (suportul trimestrial, S1). Liniile se prelungesc peste trimestrul nou — acolo le folosești. Cifrele PPQ/SQ sunt COMPLETARE PROPRIE: cursul spune explicit că nu dă valorile lor. Formula e cea confirmată „1 la 1" în material. Aici sunt calculate în cod din seria desenată, nu scrise de mână. Rulează: python3 gen/strategii/atmi_pivoti.py """ import sys from pathlib import Path sys.path.insert(0, "/workspace/atm-curs-dl") from svg_candles import Chart, Level, Mark, Zone, Arrow, from_closes # noqa: E402 OUT = Path(__file__).resolve().parent / "atmi_pivoti.svg" GRAY, RED, GREEN, BLUE, ORANGE, INK = "#777", "#c00", "#188a3e", "#1a5fb4", "#b06000", "#333" PURPLE = "#7b2fbf" # --- seria: 22 de bare din trimestrul precedent + 12 din cel nou ----------- # Trimestrul precedent trebuie să aibă H = 100.80, L = 90.40, C = 96.20. Q_PREV = [95.40, 94.10, 93.00, 92.10, 90.90, 90.70, 92.20, 93.60, 95.00, 96.40, 97.90, 99.20, 100.40, 99.80, 98.60, 97.40, 96.20, 95.10, 95.90, 96.80, 97.30, 96.20] Q_NOU = [97.00, 97.70, 98.40, 99.00, 99.60, 100.00, 99.20, 98.30, 97.40, 96.90, 96.50, 96.20] CLOSES = Q_PREV + Q_NOU NP = len(Q_PREV) assert len(CLOSES) == 34 wicks = [(0.25, 0.25)] * len(CLOSES) wicks[4] = (0.20, 0.50) # minimul trimestrului precedent: 90.90 - 0.50 = 90.40 wicks[12] = (0.40, 0.20) # maximul trimestrului precedent: 100.40 + 0.40 = 100.80 wicks[NP - 1] = (0.20, 0.20) wicks[NP] = (0.25, 0.00) # prima bară a trimestrului nou pleacă de pe close-ul C wicks[NP + 5] = (0.00, 0.25) # swing high-ul trimestrului nou: exact 100.00 wicks[NP + 6] = (0.00, 0.25) # nicio bară de după nu depășește swing high-ul wicks[-3] = (0.20, 0.00) wicks[-2] = (0.20, 0.00) wicks[-1] = (0.15, 0.20) # low-ul ultimei bare: 96.20 - 0.20 = 96.00 cds = from_closes(CLOSES, wicks=wicks, vols=[40 + (i * 7) % 33 for i in range(len(CLOSES))], start=96.00) # --- pivoții, calculați din seria desenată --------------------------------- H = round(max(c.h for c in cds[:NP]), 2) L = round(min(c.l for c in cds[:NP]), 2) C = round(cds[NP - 1].c, 2) PP = round((H + L + C) / 3, 2) S1 = round(2 * PP - H, 2) R1 = round(2 * PP - L, 2) assert (H, L, C) == (100.80, 90.40, 96.20), (H, L, C) assert PP == 95.80, PP assert S1 == 90.80, S1 assert R1 == 101.20, R1 assert S1 < PP < R1 assert abs(S1 - L) > 0.3, "S1 a ieșit chiar pe low — ar părea o coincidență, nu un calcul" # ce afirmă textul capitolului despre trimestrul NOU SWING = round(max(c.h for c in cds[NP:]), 2) FUND = round(min(c.l for c in cds[NP:]), 2) assert abs(SWING - 100.00) < 1e-9, SWING ZONA = (PP - 0.30, PP + 0.30) # banda de cumpărare din jurul pivotului assert abs(FUND - 96.00) < 1e-9, FUND assert ZONA[0] <= FUND <= ZONA[1], (FUND, ZONA) # ultima bară intră în zona PPQ assert abs((SWING - 96.00) / SWING * 100 - 4.0) < 0.05 # corecție de exact 4,0 % assert all(c.l > S1 for c in cds[NP:]), "trimestrul nou nu trebuie să atingă SQ" levels = [ Level(PP, f"PPQ {PP:.2f} — zona 1", PURPLE), Level(S1, f"SQ {S1:.2f} — zona 2", GREEN), ] marks = [ Mark(12, f"H {H:.2f}", INK, "above"), Mark(4, f"L {L:.2f}", INK, "below"), Mark(NP - 1, f"C {C:.2f}", INK, "above", dy=-16), Mark(NP + 5, f"swing high {SWING:.2f}", RED, "above"), Mark(len(cds) - 4, "corecție 4,0 % — prețul intră în zona PPQ: treci la pasul 2", PURPLE, "below", dy=34), ] arrows = [] zones = [Zone(0, NP - 1, "", GRAY), Zone(NP, len(cds) - 1, "", BLUE)] ch = Chart(candles=cds, levels=levels, marks=marks, zones=zones, arrows=arrows, scale=13.0, gap=16, body_w=9, left=52, width=720, vol_h=60, top=124, label_gap=54, caption="Cifrele PPQ/SQ sunt completarea mea: cursul dă regula, nu valorile. " "Formula e cea standard, confirmată în material pentru pivoți.") svg = ch.render() # formula, scrisă cu cifrele desenului, ca să nu rămână o regulă abstractă form = [f"PP = (H + L + C) / 3 = ({H:.2f} + {L:.2f} + {C:.2f}) / 3 = {PP:.2f} → PPQ", f"S1 = 2 x PP - H = 2 x {PP:.2f} - {H:.2f} = {S1:.2f} → SQ", f"R1 = 2 x PP - L = 2 x {PP:.2f} - {L:.2f} = {R1:.2f}"] box = [f'' f'SPY — daily: pivoții trimestrului nou, calculați din trimestrul precedent', f'', f'' f'trimestrul precedent', f'' f'trimestrul nou: aici tranzacționezi'] for i, s in enumerate(form): box.append(f'{s}') i = svg.index(">") + 1 svg = svg[:i] + "\n " + "\n ".join(box) + svg[i:] assert "\n\n" not in svg assert ".md:" not in svg OUT.write_text(svg) print(f"scris {OUT.name}: H {H} L {L} C {C} -> PPQ {PP}, SQ {S1}, R1 {R1}")