selectia: diagramele refacute dupa sablon (textul urmeaza)
Agentul a atins pragul de context dupa diagrame; capitolul 04_selectia e inca in formatul vechi si se reia separat. Ce s-a schimbat: ansamblul nu mai arata ULTA mergand la TP2 — ULTA pica chiar filtrul de selectie (RVOL 0.61 si 5.01 % de suport), deci nu putea fi exemplul-vitrina; acum arata doar ce citeste selectia, cu granita "aici se termina selectia" marcata. Funnel-ul trece de la 8 trepte la 6, aliniat cu pasii nivelului 2, si fiecare treapta spune de ce. Cadranele primesc mini-histograme RS, ca sa se recunoasca dintr-un desen, nu dintr-o propozitie. Trimiterile fisier:linie sunt scoase de pe desene. Noi: univers (pragurile de pret si volum), sectoare (dominantul din cele 11), proximitate (banda de 3 % peste suportul monthly, cu observatia ca nu e pragul de 1-2 % din Buy Doji — masoara altceva). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ThN7ixZrowca8aTGrK1MUJ
This commit is contained in:
@@ -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'<rect x="{x0:.1f}" y="{y0:.1f}" width="{w:.1f}" height="{h:.1f}" '
|
||||
f'fill="#ffffff" stroke="{GRAY}" stroke-width="0.8"/>',
|
||||
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'<rect x="{xs[i] - bw / 2:.1f}" y="{top:.1f}" width="{bw:.1f}" '
|
||||
f'height="{abs(v) * unit:.1f}" fill="{color}" '
|
||||
f'fill-opacity="{1.0 if i == len(vals) - 1 else 0.35}"/>')
|
||||
pts = " ".join(f"{xs[i]:.1f},{yz - m * unit:.1f}" for i, m in enumerate(ma4(vals)))
|
||||
out.append(f'<polyline points="{pts}" fill="none" stroke="{ORANGE}" '
|
||||
f'stroke-width="1.6" stroke-dasharray="3 2"/>')
|
||||
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'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 {W} {H}" '
|
||||
f'width="{W}" height="{H}" font-family="system-ui, sans-serif" role="img" '
|
||||
@@ -244,8 +286,8 @@ assert any(t[2] == "sub 0, dar peste MA" for t in TEXTS)
|
||||
assert any(t[2] == "peste 0, dar sub MA" for t in TEXTS)
|
||||
assert any(t[2] == "sub 0 și sub MA" for t in TEXTS)
|
||||
# direcția: LONG pe 1-2, SHORT pe 3-4
|
||||
assert svg.count(">LONG</text>") == 2, "LONG trebuie să apară exact de 2 ori"
|
||||
assert svg.count(">SHORT</text>") == 2, "SHORT trebuie să apară exact de 2 ori"
|
||||
assert sum(t[2].startswith("LONG") for t in TEXTS) == 2, "LONG trebuie să apară de 2 ori"
|
||||
assert sum(t[2].startswith("SHORT") for t in TEXTS) == 2, "SHORT trebuie să apară de 2 ori"
|
||||
assert "stai pe margine" in svg, "lipsește «stai pe margine» din cadranul 4"
|
||||
assert "zona de cumpărat" in svg, "lipsește «zona de cumpărat» din cadranul 2"
|
||||
assert "Long = cadranele 1-2" in svg and "Short = cadranele 3-4" in svg
|
||||
@@ -260,10 +302,7 @@ for req in ("Relative strength — cele 4 cadrane",
|
||||
"MP4-1 / MBT-10 long",
|
||||
"Un setup de bottom cu RS fără îmbunătățire are șanse mai mici",
|
||||
"transcrierea descrierii cadranului 4 are o eroare",
|
||||
"e completarea sumarului",
|
||||
"03_MODUL_2/06_indicatorul_de_performanta.md:41-48",
|
||||
"11_selectia_simbolului.md:486-499",
|
||||
"06_indicatorul_de_performanta.md:31-39"):
|
||||
"histograma RS (barele), linia de 0 și media mobilă"):
|
||||
assert req in svg, f"lipsește din desen: {req!r}"
|
||||
|
||||
# 5. etichetele cadranului 2 și 3 care se pot încurca: verifică asocierea
|
||||
|
||||
Reference in New Issue
Block a user