diff --git a/gen/strategii/atmi_aplus.svg b/gen/strategii/atmi_aplus.svg
deleted file mode 100644
index 07e53ee..0000000
--- a/gen/strategii/atmi_aplus.svg
+++ /dev/null
@@ -1,119 +0,0 @@
-
\ No newline at end of file
diff --git a/gen/strategii/atmi_aplus.py b/gen/strategii/atmi_corectie.py
similarity index 100%
rename from gen/strategii/atmi_aplus.py
rename to gen/strategii/atmi_corectie.py
diff --git a/gen/strategii/atmi_aplus.spec.txt b/gen/strategii/atmi_corectie.spec.txt
similarity index 100%
rename from gen/strategii/atmi_aplus.spec.txt
rename to gen/strategii/atmi_corectie.spec.txt
diff --git a/gen/strategii/selectia_ansamblu.py b/gen/strategii/selectia_ansamblu.py
index 3feb9ce..8b39fa5 100644
--- a/gen/strategii/selectia_ansamblu.py
+++ b/gen/strategii/selectia_ansamblu.py
@@ -1,10 +1,16 @@
"""ULTA — daily (pivoți monthly): diagrama de ansamblu a selecției (TIP: PRET).
-Citește `gen/strategii/selectia_ansamblu.spec.txt`. Un simbol care vine dintr-un
-downtrend weekly, atinge suportul monthly 355.48 și face un buy doji la 373.30
-cu RVOL 0.61; apoi confirmarea (intrare 374.80) și drumul spre pivot/TP1 383.74,
-respectiv TP2 402.00. Grafic daily, 32 de candele, serie continuă, cu panou de
-volum și SMA-20 — construit prin `svg_candles` (from_closes), la scară.
+Rolul diagramei în capitol: arată **unde se termină selecția**. Filtrul citește
+contextul (downtrend, suportul monthly 355.48, pivotul monthly 383.74, buy doji
+la 373.30, RVOL 0.61) și se oprește la „simbolul intră pe listă". Intrarea,
+stopul și ținta nu apar aici, pentru că nu aparțin selecției — sunt ale
+capitolului 1 (Buy Doji). Partea de după linia verticală e desenată gri tocmai
+ca să se vadă că nu mai e treaba filtrului.
+
+Cifrele cursului: close 373.30, suport monthly 355.48, pivot monthly 383.74,
+RVOL 0.61 (`04_MODUL_3/01_filtre_scaner_bull_bear_reversal_pp.md`). Procentele
+de 5.01 % și 2.72 % se recalculează din ele, cu assert. Structura barelor e
+construită, la scară, prin `svg_candles` (from_closes).
Rulează:
python3 gen/strategii/selectia_ansamblu.py
@@ -15,18 +21,20 @@ import sys
from pathlib import Path
sys.path.insert(0, "/workspace/atm-curs-dl")
-from svg_candles import Chart, Level, Mark, MA, from_closes # noqa: E402
+from svg_candles import Chart, Level, Arrow, Zone, MA, from_closes # noqa: E402
OUT = Path(__file__).resolve().parent / "selectia_ansamblu.svg"
GRAY, RED, GREEN, BLUE, ORANGE, TEAL = "#777", "#c00", "#188a3e", "#1a5fb4", "#b06000", "#00a0aa"
+SUPORT, PIVOT, DOJI_CLOSE = 355.48, 383.74, 373.30
+DOJI = 20 # indexul candelei de buy doji
+
# ---------------------------------------------------------------- seria (32 bare)
-# bare 0-11 : downtrend vizibil de la ~395 la ~362 (~0.8%/bara)
-# bare 12-19 : baza/churn 356-373, minimul atinge suportul 355.48 pe bara 15
+# bare 0-11 : downtrend vizibil de la ~395 la ~362 (~0.8 %/bară)
+# bare 12-19 : baza, minimul atinge suportul monthly 355.48 pe bara 15
# bara 20 : buy doji, close 373.30 (open = close[19] = 373.00, corp 0.30)
-# bara 21 : confirmare, inchide peste intrarea 374.80
-# bare 22-31 : urcare spre pivot/TP1 383.74 (bara 26) si apoi spre TP2 402.00
+# bare 21-31 : ce urmează — nu mai e treaba selecției, desenat gri
CLOSES = [
395.00, 391.80, 388.60, 385.20, 382.00, 378.90, 375.70, 372.80, # 0-7
369.90, 367.00, 364.20, 361.80, # 8-11
@@ -38,92 +46,106 @@ CLOSES = [
assert len(CLOSES) == 32, len(CLOSES)
WICKS = [(0.35, 0.40)] * 32
-WICKS[0] = (0.40, 0.50) # prima bara, deschide dintr-un varf al downtrend-ului
+WICKS[0] = (0.40, 0.50) # prima bară, deschide dintr-un vârf al downtrend-ului
WICKS[15] = (0.30, 0.72) # low exact 355.48 = suportul monthly
WICKS[16] = (0.40, 0.30) # rebound, nu sparge suportul
-WICKS[20] = (0.80, 0.30) # doji: high 374.10, low 372.70
-WICKS[31] = (0.55, 0.40) # high 402.05, atinge TP2 402.00
+WICKS[DOJI] = (1.45, 1.45) # doji: corp 0.30 din 3.20 înălțime = 9 %
assert len(WICKS) == 32, len(WICKS)
-# barele 25-31 in crestere; bara 20 (doji) sub media seriei (RVOL 0.61)
+# bara 20 (doji) sub media seriei: exact ce înseamnă RVOL 0.61
VOLS = [
42, 44, 41, 46, 43, 45, 40, 44, 47, 43, # 0-9
40, 42, 38, 41, 52, # 10-14
56, 50, 45, 42, 39, # 15-19
30, # 20 doji, sub medie
- 46, # 21 confirmare
+ 46, # 21
48, 50, 52, 54, 58, 62, 66, 70, 76, 82, # 22-31
]
assert len(VOLS) == 32, len(VOLS)
media_vol = sum(VOLS) / len(VOLS)
-assert VOLS[20] < media_vol, "bara 20 (doji) trebuie sub media seriei"
-assert all(a < b for a, b in zip(VOLS[25:32], VOLS[26:32])), "barele 25-31 nu cresc"
-# RVOL afisat (0.61) ~ raportul barei de doji fata de media seriei
-assert abs(VOLS[20] / media_vol - 0.61) < 0.02, VOLS[20] / media_vol
+assert abs(VOLS[DOJI] / media_vol - 0.61) < 0.02, VOLS[DOJI] / media_vol
cds = from_closes(CLOSES, wicks=WICKS, vols=VOLS, start=396.50)
-# ---------------------------------------------------------------- assert-urile din spec
-assert abs(cds[20].c - 373.30) < 1e-9, "doji-ul trebuie sa inchida la 373.30"
-assert abs(max(cds[20].o, cds[20].c) - min(cds[20].o, cds[20].c)) <= 0.40, "bara 20 nu e doji"
-assert abs(min(c.l for c in cds[12:21]) - 355.48) < 0.05, "suportul 355.48 nu e atins"
-assert 352.00 < 355.48 < 373.30 < 374.80 < 383.74 < 402.00, "ordinea nivelurilor"
-risc = 374.80 - 352.00 # 22.80
-assert abs((383.74 - 374.80) / risc - 0.39) < 0.02, "TP1 nu e ~0.39R"
-assert abs((402.00 - 374.80) / risc - 1.19) < 0.02, "TP2 nu e ~1.19R"
-assert cds[-1].c >= 383.74, "TP1 nu e atins in serie"
-assert min(c.l for c in cds) >= 351.5, "SL-ul de 352.00 nu poate fi sub minimul seriei"
+# barele de după doji sunt gri: nu mai sunt în sarcina filtrului
+for cd in cds[DOJI + 1:]:
+ cd.color = "#bbb"
+
+# ---------------------------------------------------------------- assert-uri de conținut
+assert abs(cds[DOJI].c - DOJI_CLOSE) < 1e-9, "doji-ul trebuie să închidă la 373.30"
+corp = abs(cds[DOJI].o - cds[DOJI].c)
+inaltime = cds[DOJI].h - cds[DOJI].l
+assert corp / inaltime <= 0.10, f"bara {DOJI} nu e doji: corp {corp / inaltime:.0%} din înălțime"
+assert abs(min(c.l for c in cds[12:DOJI + 1]) - SUPORT) < 0.05, "suportul 355.48 nu e atins"
+# de la intrarea în bază și până la doji, prețul stă sub pivot: de asta pivotul
+# e rezistența cea mai apropiată deasupra doji-ului
+assert max(c.h for c in cds[12:DOJI + 1]) < PIVOT, "pivotul nu are voie atins în bază"
for a, b in zip(cds, cds[1:]):
- assert abs(a.c - b.o) < 1e-9, "serie cu gol artificial intre bare"
+ assert abs(a.c - b.o) < 1e-9, "serie cu gol artificial între bare"
-# structura ceruta explicit: doji mic cu fitilele date, confirmare peste intrare
-assert abs(cds[20].h - 374.10) < 0.05 and abs(cds[20].l - 372.70) < 0.05, (cds[20].h, cds[20].l)
-assert cds[21].c > 374.80, "bara 21 nu confirma intrarea"
-assert max(cds[i].h for i in range(22, 27)) >= 383.74, "TP1 nu e atins in jurul barei 26"
-assert cds[31].h >= 402.00, "TP2 nu e atins spre final"
+# procentele din etichete se calculează, nu se scriu de mână
+pct_suport = (DOJI_CLOSE - SUPORT) / SUPORT * 100 # 5.01 %
+pct_pivot = (PIVOT - DOJI_CLOSE) / PIVOT * 100 # 2.72 %
+assert abs(pct_suport - 5.01) < 0.01, pct_suport
+assert abs(pct_pivot - 2.72) < 0.01, pct_pivot
+rvol = VOLS[DOJI] / media_vol
-# ---------------------------------------------------------------- niveluri, etichete
levels = [
- Level(352.00, "SL 352.00", RED, label_at="left"),
- Level(355.48, "suport monthly 355.48", BLUE, label_at="left"),
- Level(374.80, "intrare 374.80", GREEN),
- Level(383.74, "pivot / TP1 383.74", BLUE),
- Level(402.00, "TP2 402.00", BLUE),
+ Level(SUPORT, f"suport monthly {SUPORT:.2f}", BLUE, label_at="left"),
+ Level(PIVOT, f"pivot monthly {PIVOT:.2f}", BLUE),
]
-marks = [
- # „sub bara 0" ar insemna peste candelele care coboara (staircase); dy-ul
- # o ridica deasupra varfului de start, unde textul se citeste curat
- Mark(0, "downtrend weekly", GRAY, "below", dy=-62),
- Mark(20, "buy doji close 373.30 (RVOL 0.61)", TEAL, "below"),
- Mark(21, "intrare 374.80", GREEN, "above"),
- Mark(26, "TP1 383.74 = pivot", BLUE, "above", dy=-8),
- Mark(31, "TP2 402.00", BLUE, "above", dy=-22),
+zones = [
+ Zone(0, 11, "1. downtrend — de asta apare în scaner", RED),
+ Zone(12, DOJI, "", BLUE, p_bot=SUPORT - 0.6),
]
-caption = ("Ale cursului: close 373.30, suport 355.48, pivot 383.74, RVOL 0.61. "
- "Intrarea 374.80, SL 352.00 si TP2 402.00 sunt estimari din 04_MODUL_3/01; "
- "structura barelor dintre niveluri e construita, la scara.")
+arrows = [
+ Arrow(15, f"2. suportul monthly {SUPORT:.2f} a mai întors prețul o dată:\n"
+ f"acolo stau ordine de cumpărare, deci coborârea are unde să se oprească",
+ where="below", price=SUPORT, color=BLUE, dx=-30, dy=34),
+ Arrow(DOJI, f"3. buy doji, close {DOJI_CLOSE:.2f} — aici se oprește selecția\n"
+ f"{pct_suport:.2f} % peste suport, {pct_pivot:.2f} % sub pivot: trece proximitatea față de pivot\n"
+ f"volumul zilei = {rvol:.2f} din medie (RVOL {rvol:.2f}), sub pragul de 1.00: minus, nu veto",
+ where="above", color=TEAL, dx=-250, dy=-66),
+ Arrow(27, "trigger, stop și țintă sunt\nale capitolului Buy Doji",
+ where="right", color=GRAY, dx=16, dy=-40),
+]
+
+caption = ("Ale cursului: close 373.30, suport monthly 355.48, pivot monthly 383.74, RVOL 0.61. "
+ "Procentele sunt calculate din ele. Structura barelor e construită, la scară. "
+ "Intrarea, stopul și ținta nu apar pe desen: nu aparțin selecției.")
ch = Chart(
- candles=cds, levels=levels, marks=marks,
+ candles=cds, levels=levels, zones=zones, arrows=arrows,
mas=[MA(20, ORANGE, dash="4 3", text="SMA-20")],
scale=8.5, gap=15, body_w=9, left=44, width=640, vol_h=70,
vol_label="volum",
- title="ULTA — daily (pivoți monthly)",
+ title="ULTA — daily: ce citește selecția și unde se oprește",
caption=caption,
)
svg = ch.render()
-# ---------------------------------------------------------------- verificarea de scara
-ys = {p: ch._y(p) for p in (352.00, 355.48, 374.80, 383.74, 402.00)}
-px_risc = ys[352.00] - ys[374.80] # y creste in jos, deci SL-ul are y mai mare
-assert abs((ys[374.80] - ys[383.74]) / px_risc - (383.74 - 374.80) / risc) < 1e-9, "TP1 la scara gresita"
-assert abs((ys[374.80] - ys[402.00]) / px_risc - (402.00 - 374.80) / risc) < 1e-9, "TP2 la scara gresita"
+# ---------------------------------------------------------------- linia verticală de predare
+# offsetul intern al randării, citit din prima linie de Level desenată
+m_off = re.search(r']*fill="' + RED + r'"', svg)
+assert m_dx, "nu găsesc dreptunghiul primei zone, din care citesc offsetul pe x"
+DX = float(m_dx.group(1)) - (ch._cx(0) - ch.body_w / 2 - 5)
+x_sep = ch._cx(DOJI) + DX + ch.gap / 2
+y_top = ch._y(max(c.h for c in cds)) + OFF + 4
+y_bot = ch._y(min(c.l for c in cds)) + OFF + 16
+sep = (f''
+ f'aici se termină selecția'
+ f'aici începe capitolul 1')
+svg = svg.replace("", sep + "")
-# ---------------------------------------------------------------- finisaj text
-# caption-ul pe un singur rand depaseste latimea panzei (se taie la viewBox):
-# il rupem in linii si crestem inaltimea desenului.
+# ---------------------------------------------------------------- caption pe mai multe rânduri
def _wrap(text: str, max_chars: int) -> list[str]:
lines, cur = [], ""
for w in text.split():
@@ -138,25 +160,27 @@ def _wrap(text: str, max_chars: int) -> list[str]:
cap_lines = _wrap(caption, 92)
-m = re.search(r'' + re.escape(caption) + r"\s*", svg)
-assert m, "caption-ul nu a fost gasit in SVG"
+m = re.search(r'' + re.escape(caption) + r"", svg)
+assert m, "caption-ul nu a fost găsit în SVG"
y0 = int(m.group(1))
wrapped = "\n ".join(f'{ln}'
for i, ln in enumerate(cap_lines))
-svg = svg[:m.start()] + wrapped + "\n"
+svg = svg[:m.start()] + wrapped + svg[m.end():]
vm = re.search(r'viewBox="0 0 (\d+) (\d+)"', svg)
assert vm
svg = svg.replace(vm.group(0),
- f'viewBox="0 0 {vm.group(1)} {int(vm.group(2)) + 17 * (len(cap_lines) - 1)}"', 1)
+ f'viewBox="0 0 {vm.group(1)} {int(vm.group(2)) + 17 * (len(cap_lines) - 1) + 24}"', 1)
-# „SMA-20" (x=515, y=269) sta la 12.6px de eticheta „intrare 374.80" (y=281.6),
-# adica lipite: o ridicam 12px pe linia libera de deasupra.
-svg, n = re.subn(r'(SMA-20)',
- lambda mm: f'{mm.group(1)}{int(mm.group(2)) - 12}{mm.group(3)}', svg)
-assert n == 1, f"eticheta SMA-20: {n} potriviri"
+# ---------------------------------------------------------------- nicio cifră inventată în etichete
+desenate = {f"{SUPORT:.2f}", f"{PIVOT:.2f}", f"{DOJI_CLOSE:.2f}"}
+for txt in re.findall(r"]*>([^<]*)", svg):
+ for nr in re.findall(r"\d+\.\d\d", txt):
+ assert nr in desenate | {f"{pct_suport:.2f}", f"{pct_pivot:.2f}",
+ f"{rvol:.2f}", "1.00"}, \
+ f"eticheta numește {nr}, care nu e un nivel desenat: {txt!r}"
-assert "
\ No newline at end of file
+
\ No newline at end of file
diff --git a/gen/strategii/selectia_cadrane.py b/gen/strategii/selectia_cadrane.py
index e19bd84..8b6ac6d 100644
--- a/gen/strategii/selectia_cadrane.py
+++ b/gen/strategii/selectia_cadrane.py
@@ -32,7 +32,7 @@ Rulare: .venv/bin/python gen/strategii/selectia_cadrane.py
import html
from pathlib import Path
-W, H = 700, 720
+W, H = 700, 812
BLACK = "#000000"
GRAY = "#777777"
@@ -46,7 +46,7 @@ RED_BG = "#fdeeee"
# ---------------------------------------------------------------- geometrie
PLOT_X0, PLOT_X1 = 130.0, 570.0
-PLOT_Y0, PLOT_Y1 = 134.0, 414.0
+PLOT_Y0, PLOT_Y1 = 134.0, 502.0
CX = (PLOT_X0 + PLOT_X1) / 2.0 # 350
CY = (PLOT_Y0 + PLOT_Y1) / 2.0 # 266
@@ -61,7 +61,7 @@ Q2 = {"x": CX + GUT / 2, "y": CY + GUT / 2} # sub 0, peste MA
for _q in (Q1, Q2, Q3, Q4):
_q["w"], _q["h"] = CW, CH
-BAND = {"x": 40.0, "y": 460.0, "w": 620.0, "h": 196.0}
+BAND = {"x": 40.0, "y": 556.0, "w": 620.0, "h": 196.0}
# ---------------------------------------------------------------- collect
TEXTS = [] # (x, y, s, size, weight, fill, anchor)
@@ -97,6 +97,39 @@ def line(x1, y1, x2, y2, stroke=GRAY, width=1.0, dash=None):
f'stroke="{stroke}" stroke-width="{width}"{d}/>')
+def ma4(vals):
+ """Media mobilă pe 4, ca în indicatorul cursului: histogramă + MA peste ea."""
+ return [sum(vals[max(0, i - 3):i + 1]) / len(vals[max(0, i - 3):i + 1])
+ for i in range(len(vals))]
+
+
+def sketch(q, dy, vals, color):
+ """Mini-histogramă RS cu linia de 0 și media mobilă peste ea, în celula q.
+
+ Ultima bară e cea care decide cadranul, așa că e desenată plină, iar
+ poziția ei față de 0 și față de MA e verificată prin assert de mai jos.
+ """
+ w, h = 158.0, 46.0
+ x0 = q["x"] + (q["w"] - w) / 2.0
+ y0 = q["y"] + dy
+ yz = y0 + h / 2.0 # linia de 0, la mijloc
+ unit = (h / 2.0 - 3) / max(abs(v) for v in vals)
+ bw = w / (len(vals) * 1.6)
+ out = [f'',
+ line(x0, yz, x0 + w, yz, BLACK, 1.0)]
+ xs = [x0 + w * (i + 0.5) / len(vals) for i in range(len(vals))]
+ for i, v in enumerate(vals):
+ top = yz - v * unit if v > 0 else yz
+ out.append(f'')
+ pts = " ".join(f"{xs[i]:.1f},{yz - m * unit:.1f}" for i, m in enumerate(ma4(vals)))
+ out.append(f'')
+ return out
+
+
def cell_text(q, dy, s, *a, **k):
add(q["x"] + q["w"] / 2.0, q["y"] + dy, s, *a, **k)
@@ -134,67 +167,76 @@ p.append(rect(Q4["x"], Q4["y"], CW, CH, "Q4", fill=RED_BG, stroke=RED, sw=1.6,
dash="6 4"))
p.append(rect(Q2["x"], Q2["y"], CW, CH, "Q2", fill=GREEN_BG, stroke=GREEN, sw=1.6))
+# seriile mini-histogramelor: ultima bară decide cadranul
+H3 = [6, 6, 5, 5, 4, 3, 3, 2, 1] # peste 0, dar sub MA
+H1 = [-1, 0, 1, 2, 2, 3, 4, 5, 6] # peste 0 și peste MA
+H4 = [1, 0, -1, -2, -2, -3, -4, -5, -6] # sub 0 și sub MA
+H2 = [-6, -6, -5, -5, -4, -3, -3, -2, -1] # sub 0, dar peste MA
+
# Cadran 3 — top-left: peste 0, sub MA -> SHORT
-cell_text(Q3, 30, "Cadran 3", 16, "bold", BLACK)
-cell_text(Q3, 52, "înrăutățire", 14, "bold", RED)
-cell_text(Q3, 80, "peste 0, dar sub MA", 13, "normal", BLACK)
-cell_text(Q3, 112, "SHORT", 16, "bold", RED)
+cell_text(Q3, 26, "Cadran 3", 16, "bold", BLACK)
+cell_text(Q3, 48, "înrăutățire", 14, "bold", RED)
+cell_text(Q3, 70, "peste 0, dar sub MA", 13, "normal", BLACK)
+cell_text(Q3, 94, "SHORT", 16, "bold", RED)
+p += sketch(Q3, 106, H3, RED)
# Cadran 1 — top-right: peste 0, peste MA -> LONG
-cell_text(Q1, 30, "Cadran 1", 16, "bold", BLACK)
-cell_text(Q1, 52, "supraperformanță", 14, "bold", GREEN)
-cell_text(Q1, 80, "peste 0 și peste MA", 13, "normal", BLACK)
-cell_text(Q1, 112, "LONG", 16, "bold", GREEN)
+cell_text(Q1, 26, "Cadran 1", 16, "bold", BLACK)
+cell_text(Q1, 48, "supraperformanță", 14, "bold", GREEN)
+cell_text(Q1, 70, "peste 0 și peste MA", 13, "normal", BLACK)
+cell_text(Q1, 94, "LONG", 16, "bold", GREEN)
+p += sketch(Q1, 106, H1, GREEN)
# Cadran 4 — bottom-left: sub 0, sub MA -> SHORT / stai pe margine
-cell_text(Q4, 26, "Cadran 4", 16, "bold", BLACK)
-cell_text(Q4, 48, "subperformanță", 14, "bold", RED)
-cell_text(Q4, 74, "sub 0 și sub MA", 13, "normal", BLACK)
-cell_text(Q4, 100, "SHORT", 15, "bold", RED)
-cell_text(Q4, 122, "stai pe margine", 13, "normal", RED)
+cell_text(Q4, 24, "Cadran 4", 16, "bold", BLACK)
+cell_text(Q4, 46, "subperformanță", 14, "bold", RED)
+cell_text(Q4, 68, "sub 0 și sub MA", 13, "normal", BLACK)
+cell_text(Q4, 90, "SHORT — stai pe margine", 14, "bold", RED)
+p += sketch(Q4, 102, H4, RED)
# Cadran 2 — bottom-right: sub 0, peste MA -> LONG (zona de cumpărat)
-cell_text(Q2, 26, "Cadran 2", 16, "bold", BLACK)
-cell_text(Q2, 48, "îmbunătățire", 14, "bold", GREEN)
-cell_text(Q2, 74, "sub 0, dar peste MA", 13, "normal", BLACK)
-cell_text(Q2, 100, "LONG", 15, "bold", GREEN)
-cell_text(Q2, 122, "zona de cumpărat", 13, "normal", GREEN)
+cell_text(Q2, 24, "Cadran 2", 16, "bold", BLACK)
+cell_text(Q2, 46, "îmbunătățire", 14, "bold", GREEN)
+cell_text(Q2, 68, "sub 0, dar peste MA", 13, "normal", BLACK)
+cell_text(Q2, 90, "LONG — zona de cumpărat", 14, "bold", GREEN)
+p += sketch(Q2, 102, H2, GREEN)
+
+# fiecare schiță trebuie să arate exact cadranul pe care îl ilustrează
+for _nume, _h, _peste0, _pesteMA in (("3", H3, True, False), ("1", H1, True, True),
+ ("4", H4, False, False), ("2", H2, False, True)):
+ _last, _ma = _h[-1], ma4(_h)[-1]
+ assert (_last > 0) == _peste0, f"schița cadranului {_nume}: ultima bară față de 0"
+ assert (_last > _ma) == _pesteMA, f"schița cadranului {_nume}: ultima bară față de MA"
# ---- concluzia de sub matrice
-add(W / 2, 442, "Long = cadranele 1-2 · Short = cadranele 3-4",
+add(W / 2, 530, "Long = cadranele 1-2 · Short = cadranele 3-4",
14, "bold", BLACK)
+add(W / 2, 548, "în fiecare cadran: histograma RS (barele), linia de 0 și media mobilă (punctat portocaliu)",
+ 13, "normal", GRAY)
# ---- banda de avertisment (cadranul 4)
p.append(rect(BAND["x"], BAND["y"], BAND["w"], BAND["h"], "band",
fill="#fdf0e0", stroke=ORANGE, sw=1.6))
-add(BAND["x"] + 20, 488, "Avertisment — cadranul 4 nu se tranzacționează pe orb",
+add(BAND["x"] + 20, 584, "Avertisment — cadranul 4 nu se tranzacționează pe orb",
15, "bold", RED, "start")
-add(BAND["x"] + 20, 516,
+add(BAND["x"] + 20, 612,
"„Cadranul 4 nu se tranzacționează pe orb: aștepți trecerea în 2 sau 1,",
13, "normal", BLACK, "start")
-add(BAND["x"] + 20, 536, "ori un MP4-1 / MBT-10 long ca semn de schimbare.”",
+add(BAND["x"] + 20, 632, "ori un MP4-1 / MBT-10 long ca semn de schimbare.”",
13, "normal", BLACK, "start")
-add(BAND["x"] + 20, 566,
+add(BAND["x"] + 20, 662,
"„Un setup de bottom cu RS fără îmbunătățire are șanse mai mici.”",
13, "bold", BLACK, "start")
-add(BAND["x"] + 20, 596,
+add(BAND["x"] + 20, 692,
"Notă: transcrierea descrierii cadranului 4 are o eroare (îl descrie ca pe",
13, "normal", GRAY, "start")
-add(BAND["x"] + 20, 616,
- "cadranul 3); definiția de mai sus e completarea sumarului —",
+add(BAND["x"] + 20, 712,
+ "cadranul 3, care e altceva). Definiția din tabloul de mai sus e cea",
13, "normal", GRAY, "start")
-add(BAND["x"] + 20, 636,
- "03_MODUL_2/06_indicatorul_de_performanta.md:41-48.",
+add(BAND["x"] + 20, 732,
+ "corectă și e singura folosită în tot capitolul.",
13, "normal", GRAY, "start")
-# ---- surse
-add(W / 2, 686,
- "Surse: 08_ANALIZA_ZILNICA/11_selectia_simbolului.md:486-499, :501-508;",
- 13, "normal", GRAY)
-add(W / 2, 704,
- "03_MODUL_2/06_indicatorul_de_performanta.md:31-39.",
- 13, "normal", GRAY)
-
# =============================================================== EMITERE
head = (f'