Nivelurile 1-2-3, cei 6 pasi cu diagrama fiecare, mini-glosar de 34 de termeni, oglinda pe short cu diagrama ei proprie, checklist. Sursele in fise/02_mp2_surse.md. Toate diagramele procedurii ies acum dintr-o singura serie (mp2_serie.py), deci capitolul nu mai poate avea doua reguli numerice. Ansamblul folosea NVDA cu stop la swing low absolut (-23 %), adica alta regula decat procedura celor 4 bare; NVDA a devenit "bottom", la nivelul 3, marcat explicit ca exceptie. perechi_tf e diagrama cu doua timeframe-uri: panoul mic e descompunerea reala a ultimelor 2 candele daily (1 zi = 7 bare de 60 min), cu pivotul weekly pe ambele panouri si conector. Pivotii se calculeaza din serie, nu sunt scrisi de mana. Reparate: trail-ul din proza era 600.05, calculul din serie da 600.75; doua SVG-uri aveau trimiteri fisier:linie desenate pe ele. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ThN7ixZrowca8aTGrK1MUJ
80 lines
3.6 KiB
Python
80 lines
3.6 KiB
Python
"""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'<polyline points="{S.trepte(ch, S.PPD_BARA, off)}" fill="none" stroke="{BLUE}" '
|
|
f'stroke-width="1.8"/>',
|
|
]
|
|
# 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'<text x="{ch._cx(d * S.BARE_ZI + b):.1f}" y="{ch._y(S.PPD[d]) + off + dy_:.1f}" '
|
|
f'fill="{BLUE}" text-anchor="middle" style="font-weight:bold">{S.PPD[d]:.2f}</text>')
|
|
|
|
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'<text x="24" y="{h + 6 + 19 * i:.1f}" fill="{c}"'
|
|
f'{" style=\'font-weight:bold\'" if i == 3 else ""}>{t}</text>'
|
|
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("</svg>", " " + "\n ".join(blocs) + "\n</svg>")
|
|
|
|
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)
|