Files
atm-curs-dl/gen/strategii/atmi_pivoti.py
Claude Agent c08c857274 atmi: diagramele refacute, cinci noi, si fisa de surse
Noi: pivoti (PPQ/SQ calculati din trimestrul precedent, cu formula pe
desen), perechi_tf (weekly -> daily ca descompunere reala, cu caseta,
ghidaje si PPQ pe ambele panouri), trigger (BIM apoi verde, fata de
verde inainte de BIM — cutitul in cadere), risc (ce inseamna "fara
stop": 24 de bare sub apa, -20 % pe pozitie), reinvestire (ciclul
banilor pe trei cicluri).

aplus devine corectie: diagrama arata un prag de corectie, nu un setup
A+, si numele vechi trimitea la altceva.

Trei bug-uri reale: exemplul era etichetat weekly cu 20 de bare, dar
textul spunea "un an mai tarziu" — trecut pe monthly cu assert pe numarul
de luni; ansamblul avea o trimitere fisier:linie desenata in SVG; si
benzile PPQ/SQ erau inversate ca sens, cu SQ fix pe intrare.

PPQ 95.80 si SQ 90.80 sunt completare proprie — cursul spune explicit ca
nu da valorile; derivate cu formula standard, cu assert.

Textul capitolului e neatins — agentul a atins pragul de context.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ThN7ixZrowca8aTGrK1MUJ
2026-09-20 12:46:55 +00:00

118 lines
5.4 KiB
Python

"""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'<text x="24" y="22" fill="{INK}" style="font-weight:bold">'
f'SPY — daily: pivoții trimestrului nou, calculați din trimestrul precedent</text>',
f'<rect x="24" y="34" width="430" height="54" fill="#f4f4f8" stroke="#ccc"/>',
f'<text x="46" y="110" fill="{GRAY}" style="font-size:11px;font-weight:bold">'
f'trimestrul precedent</text>',
f'<text x="446" y="110" fill="{BLUE}" style="font-size:11px;font-weight:bold">'
f'trimestrul nou: aici tranzacționezi</text>']
for i, s in enumerate(form):
box.append(f'<text x="34" y="{50 + i * 15}" fill="{INK}" '
f'style="font-family:monospace;font-size:11px">{s}</text>')
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}")