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:
@@ -1,19 +1,20 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Fluxul de selecție — palnia de filtrare de la scanner la lista scurtă.
|
||||
|
||||
Diagramă conceptuală (NU grafic de preț): palnie cu 8 trepte care se
|
||||
îngustează de sus în jos, apoi lista scurtă; cutie separată de note laterale.
|
||||
Pentru `strategii/04_selectia.md`, Nivel 1, §1.2 „Fluxul de filtrare, pas cu
|
||||
pas". Citește specificația `gen/strategii/selectia_funnel.spec.txt` și scrie
|
||||
`gen/strategii/selectia_funnel.svg`.
|
||||
Diagramă conceptuală (NU grafic de preț): palnie cu 6 trepte care se
|
||||
îngustează de sus în jos, apoi lista scurtă; cutie separată cu ce rămâne pe
|
||||
nivelul 3. Pentru `summaries/17_STRATEGII/04_selectia.md`, nivelul 1 — harta
|
||||
celor șase pași din nivelul 2. Scrie `gen/strategii/selectia_funnel.svg`.
|
||||
|
||||
Fiecare treaptă spune pragul ȘI de ce există pragul; trimiterile la material
|
||||
nu stau pe desen, ci în `summaries/17_STRATEGII/fise/04_selectia_surse.md`.
|
||||
|
||||
Nu folosește `svg_candles` / `pchart`: SVG-ul e construit ca string, doar
|
||||
stdlib.
|
||||
|
||||
Fiecare treaptă are titlul, subtitlul cu pragul și trimiterea (sursa).
|
||||
Toate cifrele din desen (pragurile, „max ~300 simboluri”, „top 10”) sunt
|
||||
preluate textual din specificație; nu se inventează valori de RS sau de
|
||||
sectoare.
|
||||
Fiecare treaptă are titlul, pragul și motivul pragului. Toate cifrele din
|
||||
desen (pragurile, „max ~300 de simboluri”, „top 10”) vin din material; nu se
|
||||
inventează valori de RS sau de sectoare.
|
||||
|
||||
Rulare: .venv/bin/python gen/strategii/selectia_funnel.py
|
||||
"""
|
||||
@@ -22,7 +23,7 @@ import re
|
||||
from pathlib import Path
|
||||
|
||||
W = 700
|
||||
H = 1024
|
||||
H = 840
|
||||
|
||||
BLACK = "#000000"
|
||||
GRAY = "#777777"
|
||||
@@ -38,60 +39,53 @@ NOTE_BG = "#fdf0e0"
|
||||
# ---------------------------------------------------------------- geometrie
|
||||
CX = W / 2.0 # 350: axa palniei
|
||||
TOPW = 610.0 # lățimea gurii palniei
|
||||
NARROW = 24.0 # cât se strânge pe fiecare treaptă
|
||||
NARROW = 30.0 # cât se strânge pe fiecare treaptă
|
||||
Y0 = 100.0
|
||||
HSTEP = 76.0
|
||||
|
||||
LIST_W, LIST_Y, LIST_H = 410.0, 722.0, 62.0
|
||||
NOTE = {"x": 40.0, "y": 802.0, "w": 620.0, "h": 200.0}
|
||||
LIST_W, LIST_Y, LIST_H = 410.0, 566.0, 62.0
|
||||
NOTE = {"x": 40.0, "y": 648.0, "w": 620.0, "h": 176.0}
|
||||
|
||||
# ---------------------------------------------------------------- conținut
|
||||
# (titlu, subtitlu, [linii de sursă])
|
||||
STEPS = [
|
||||
("Scanner — multe semnale",
|
||||
"zeci sau sute de semnale",
|
||||
["08_ANALIZA_ZILNICA/11_selectia_simbolului.md:631-637"]),
|
||||
("Filtre de bază",
|
||||
"close > 30-40 $; volum mediu 3 luni > 1M (min 500k)",
|
||||
["09_QA/28_2025-05-27.md:372-380;",
|
||||
"03_MODUL_2/11_construire_scanere_sf_byd_sld.md:70-73"]),
|
||||
("Fundamental",
|
||||
"ATM score peste 7-8; 12-13 = spuma; F-score 6-9",
|
||||
["08_ANALIZA_ZILNICA/11_selectia_simbolului.md:199-221"]),
|
||||
("Universul și lichiditatea",
|
||||
"close peste 30-40 $; volum mediu ≥ 500.000 de acțiuni, ideal peste 1 milion",
|
||||
["de ce: pe un simbol subțire, ordinul tău mută singur prețul"]),
|
||||
("Scorul fundamental",
|
||||
"ATM score peste 7-8 (12-13 = spuma); F-score 6-9",
|
||||
["de ce: instituționalii cumpără bilanț, nu desen"]),
|
||||
("Sectorul care domină",
|
||||
"cele 11 sectoare S&P, sortate cadran 1 + valoarea RS",
|
||||
["08_ANALIZA_ZILNICA/11_selectia_simbolului.md:639-717"]),
|
||||
("Doar suport / pivot, după downtrend",
|
||||
"suport monthly, quarterly, anual sau pivot; proximitate ≤ 3%",
|
||||
["08_ANALIZA_ZILNICA/11_selectia_simbolului.md:719-728, 787-803"]),
|
||||
("Relative strength: cadran 1-2",
|
||||
"doar cadranele 1 și 2, RS pozitiv",
|
||||
["08_ANALIZA_ZILNICA/11_selectia_simbolului.md:730-739"]),
|
||||
("Relative volume peste 100%",
|
||||
"numeri din ce sector vin cele mai multe semnale",
|
||||
["de ce: multe semnale în același sector = bani care intră acolo"]),
|
||||
("Suport sau pivot, după downtrend",
|
||||
"proximitate până la 3 % (4 % „e cam departe”)",
|
||||
["de ce: la un nivel, cumpărătorii au motiv să apară"]),
|
||||
("Relative strength: cadranul 1 sau 2",
|
||||
"simbolul se mișcă mai bine decât indicele de referință",
|
||||
["de ce: cumperi ce urcă mai tare decât piața"]),
|
||||
("Relative volume peste 100 %",
|
||||
"candela de volum / media ultimelor 10 candele",
|
||||
["08_ANALIZA_ZILNICA/11_selectia_simbolului.md:741-747"]),
|
||||
("Stele (Trinity)",
|
||||
"RS + Power + volum, cadran 1",
|
||||
["08_ANALIZA_ZILNICA/11_selectia_simbolului.md:776-785"]),
|
||||
["de ce: confirmă că azi chiar participă lumea, nu doar tu"]),
|
||||
]
|
||||
|
||||
LIST = ("Listă scurtă",
|
||||
"câteva idei pe care le urmărești",
|
||||
"08_ANALIZA_ZILNICA/11_selectia_simbolului.md:42-50")
|
||||
"nicio poziție deschisă: trigger-ul e al altui capitol")
|
||||
|
||||
TITLE = "Fluxul de selecție — de la scanner la lista scurtă"
|
||||
SUBTITLE = ("selecția se face înainte de semnalul tehnic; "
|
||||
"ea nu spune CÂND intri")
|
||||
CAPTION = "Palnia se îngustează de sus în jos: 8 filtre, apoi lista scurtă."
|
||||
CAPTION = "Palnia se îngustează de sus în jos: 6 filtre, apoi lista scurtă."
|
||||
|
||||
NOTE_TITLE = "Note laterale"
|
||||
NOTE1 = ["După corecție masivă: doji / hammer la suporturi mari",
|
||||
"(monthly, quarterly, anual); scanner de apropiere de suport",
|
||||
"până la 3% (4% e cam departe)."]
|
||||
NOTE1_SRC = "08_ANALIZA_ZILNICA/11_selectia_simbolului.md:787-803"
|
||||
NOTE2 = ["Radarscreen (max ~300 simboluri): repetă fluxul — sectoare top 10,",
|
||||
"RS, apoi 3 stele."]
|
||||
NOTE2_SRC = "08_ANALIZA_ZILNICA/11_selectia_simbolului.md:815-825"
|
||||
NOTE_TITLE = "Ce nu intră în cei șase pași (rafinări, nivelul 3)"
|
||||
NOTE1 = ["Sortarea finală după 3 stele (Trinity: relative strength, Power și",
|
||||
"volum, toate în cadranul 1) și departajarea între doi candidați",
|
||||
"rămași: trend, apoi volum, apoi fundamental."]
|
||||
NOTE1_SRC = "un scor de 7 nu e motiv să-l iei, dacă ai altul mai bun"
|
||||
NOTE2 = ["Radarscreen (maximum ~300 de simboluri: cele 11 sectoare × top 10):",
|
||||
"același flux, rulat pe o listă fixă, nu pe tot scanerul."]
|
||||
NOTE2_SRC = "după o corecție mare, cauți doji sau hammer la suporturile mari"
|
||||
|
||||
# ---------------------------------------------------------------- colect
|
||||
TEXTS = [] # (x, y, s, size, weight, fill, anchor)
|
||||
@@ -143,7 +137,7 @@ add(W / 2, 34, TITLE, 20, "bold")
|
||||
add(W / 2, 57, SUBTITLE, 13, "normal", GRAY)
|
||||
add(W / 2, 79, CAPTION, 13, "normal", GRAY)
|
||||
|
||||
# ---- palnia: 8 trepte
|
||||
# ---- palnia: 6 trepte
|
||||
for i, (titlu, subtitlu, surse) in enumerate(STEPS):
|
||||
y = Y0 + i * HSTEP
|
||||
wt = TOPW - i * NARROW
|
||||
@@ -152,7 +146,7 @@ for i, (titlu, subtitlu, surse) in enumerate(STEPS):
|
||||
add(CX, y + 25, f"{i + 1}. {titlu}", 14.5, "bold", BLACK)
|
||||
add(CX, y + 45, subtitlu, 13, "normal", BLACK)
|
||||
for k, src in enumerate(surse):
|
||||
add(CX, y + 59 + k * 14, src, 13, "normal", GRAY)
|
||||
add(CX, y + 60 + k * 15, src, 13, "normal", GRAY)
|
||||
|
||||
# ---- lista scurtă (vârful palniei, cutie separată)
|
||||
p.append(rect(CX - LIST_W / 2, LIST_Y, LIST_W, LIST_H, "list",
|
||||
@@ -165,21 +159,21 @@ add(CX, LIST_Y + 57, LIST[2], 13, "normal", GRAY)
|
||||
p.append(rect(NOTE["x"], NOTE["y"], NOTE["w"], NOTE["h"], "note",
|
||||
fill=NOTE_BG, stroke=ORANGE, sw=1.6, rx=8))
|
||||
nx = NOTE["x"] + 20
|
||||
add(nx, NOTE["y"] + 28, NOTE_TITLE, 15, "bold", ORANGE, "start")
|
||||
add(nx, NOTE["y"] + 56, NOTE1[0], 13, "normal", BLACK, "start")
|
||||
add(nx, NOTE["y"] + 75, NOTE1[1], 13, "normal", BLACK, "start")
|
||||
add(nx, NOTE["y"] + 94, NOTE1[2], 13, "normal", BLACK, "start")
|
||||
add(nx, NOTE["y"] + 115, NOTE1_SRC, 13, "normal", GRAY, "start")
|
||||
add(nx, NOTE["y"] + 150, NOTE2[0], 13, "normal", BLACK, "start")
|
||||
add(nx, NOTE["y"] + 169, NOTE2[1], 13, "normal", BLACK, "start")
|
||||
add(nx, NOTE["y"] + 190, NOTE2_SRC, 13, "normal", GRAY, "start")
|
||||
add(nx, NOTE["y"] + 26, NOTE_TITLE, 15, "bold", ORANGE, "start")
|
||||
add(nx, NOTE["y"] + 50, NOTE1[0], 13, "normal", BLACK, "start")
|
||||
add(nx, NOTE["y"] + 68, NOTE1[1], 13, "normal", BLACK, "start")
|
||||
add(nx, NOTE["y"] + 86, NOTE1[2], 13, "normal", BLACK, "start")
|
||||
add(nx, NOTE["y"] + 104, NOTE1_SRC, 13, "normal", GRAY, "start")
|
||||
add(nx, NOTE["y"] + 130, NOTE2[0], 13, "normal", BLACK, "start")
|
||||
add(nx, NOTE["y"] + 148, NOTE2[1], 13, "normal", BLACK, "start")
|
||||
add(nx, NOTE["y"] + 166, NOTE2_SRC, 13, "normal", GRAY, "start")
|
||||
|
||||
# =============================================================== 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" '
|
||||
f'role="img" aria-label="Palnia de selectie: 8 trepte de filtrare de la '
|
||||
f'scanner la lista scurta, fiecare cu pragul si sursa ei, plus note '
|
||||
f'laterale despre suporturi si Radarscreen">')
|
||||
f'role="img" aria-label="Palnia de selectie: 6 trepte de filtrare de la '
|
||||
f'scanner la lista scurta, fiecare cu pragul ei si cu motivul pentru '
|
||||
f'care exista pragul, plus rafinarile de la nivelul 3">')
|
||||
body = [head, f'<rect x="0" y="0" width="{W}" height="{H}" fill="#ffffff"/>']
|
||||
body += p
|
||||
for x, y, s, size, weight, fill, anchor in TEXTS:
|
||||
@@ -189,10 +183,10 @@ svg = "\n".join(body) + "\n"
|
||||
|
||||
# =============================================================== VERIFICARE
|
||||
# 1. palnia are exact 8 trepte, conectate și tot mai înguste
|
||||
assert len(STEPS) == 8, f"aștept 8 trepte, am {len(STEPS)}"
|
||||
assert len(STEPS) == 6, f"aștept 6 trepte, am {len(STEPS)}"
|
||||
traps = [s for s in SHAPES if s[4].startswith("step")]
|
||||
assert len(traps) == 8, f"aștept 8 trapezoide, am {len(traps)}"
|
||||
assert len(WIDTHS) == 8
|
||||
assert len(traps) == 6, f"aștept 6 trapezoide, am {len(traps)}"
|
||||
assert len(WIDTHS) == 6
|
||||
for i, (wt, wb) in enumerate(WIDTHS):
|
||||
assert wt > wb, f"treapta {i} nu se îngustează"
|
||||
if i:
|
||||
@@ -208,7 +202,8 @@ for i, (titlu, subtitlu, surse) in enumerate(STEPS):
|
||||
assert any(t[2] == subtitlu for t in TEXTS), \
|
||||
f"lipsește subtitlul treptei {i + 1}: {subtitlu!r}"
|
||||
for src in surse:
|
||||
assert src in svg, f"lipsește sursa treptei {i + 1}: {src!r}"
|
||||
assert src in svg, f"lipsește «de ce»-ul treptei {i + 1}: {src!r}"
|
||||
assert surse[0].startswith("de ce:"), f"treapta {i + 1} nu spune de ce"
|
||||
assert any(t[2] == LIST[0] for t in TEXTS), "lipsește «Listă scurtă»"
|
||||
assert "câteva idei pe care le urmărești" in svg
|
||||
|
||||
@@ -219,7 +214,7 @@ for line in NOTE1 + [NOTE1_SRC] + NOTE2 + [NOTE2_SRC]:
|
||||
assert line in svg, f"lipsește din note: {line!r}"
|
||||
|
||||
# 4. fiecare textul încape în lățimea treptei lui (muchia de jos, cea îngustă)
|
||||
for i in range(8):
|
||||
for i in range(len(STEPS)):
|
||||
ytop = Y0 + i * HSTEP
|
||||
ybot = ytop + HSTEP
|
||||
wb = TOPW - (i + 1) * NARROW
|
||||
@@ -259,7 +254,7 @@ for i in range(len(boxes)):
|
||||
raise AssertionError(f"etichete suprapuse: {s1!r} / {s2!r}")
|
||||
|
||||
# 6. cutiile stau una sub alta, în ordinea palnie -> listă -> note
|
||||
assert LIST_Y >= Y0 + 8 * HSTEP, "lista scurtă se suprapune cu palnia"
|
||||
assert LIST_Y >= Y0 + len(STEPS) * HSTEP, "lista scurtă se suprapune cu palnia"
|
||||
assert NOTE["y"] >= LIST_Y + LIST_H, "notele se suprapun cu lista scurtă"
|
||||
assert NOTE["y"] + NOTE["h"] <= H, "notele ies din panză"
|
||||
|
||||
@@ -270,9 +265,9 @@ assert "<circle" not in svg and "<line" not in svg, "doar palnie, fără axe"
|
||||
|
||||
# 8. singurele cifre din desen (fără referințele de sursă) sunt pragurile
|
||||
# din specificație
|
||||
content = [t[2] for t in TEXTS if ".md:" not in t[2]]
|
||||
content = [t[2] for t in TEXTS]
|
||||
spec_numbers = {"1", "2", "3", "4", "5", "6", "7", "8", "9",
|
||||
"30", "40", "500", "11", "12", "13", "100", "10", "300"}
|
||||
"30", "40", "500", "000", "11", "12", "13", "100", "10", "300"}
|
||||
nums = set(re.findall(r"\d+", " ".join(content)))
|
||||
assert nums <= spec_numbers, f"cifre neașteptate în desen: {nums - spec_numbers}"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user