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
118 lines
5.4 KiB
Python
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}")
|