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:
Claude Agent
2026-09-20 12:43:12 +00:00
parent 63c01b5ee9
commit f1033a916c
19 changed files with 1407 additions and 670 deletions

View File

@@ -1,119 +0,0 @@
<svg viewBox="0 0 680 508" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif">
<rect x="24" y="221.6" width="642" height="18.0" fill="#777" opacity="0.10"/>
<text x="24" y="48" fill="#333" style="font-weight:bold">SPY — daily: aceeași corecție, 4.0 % (DA) vs. 3.9 % (NU)</text>
<line x1="24" y1="156.8" x2="666" y2="156.8" stroke="#333" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="652" y="150.8" fill="#333" text-anchor="end">100.00 — swing high</text>
<line x1="24" y1="228.8" x2="666" y2="228.8" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="652" y="222.8" fill="#188a3e" text-anchor="end">96.00 = 4.0 % — DA, intri</text>
<line x1="24" y1="56.0" x2="666" y2="56.0" stroke="#1a5fb4" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="652" y="50.0" fill="#1a5fb4" text-anchor="end">TP +10 % = 105.60</text>
<line x1="44.0" y1="332.3" x2="44.0" y2="353.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="39.5" y="336.8" width="9" height="10.8" fill="#188a3e"/>
<line x1="60.0" y1="316.1" x2="60.0" y2="342.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="55.5" y="320.6" width="9" height="16.2" fill="#188a3e"/>
<line x1="76.0" y1="301.7" x2="76.0" y2="326.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="71.5" y="306.2" width="9" height="14.4" fill="#188a3e"/>
<line x1="92.0" y1="289.1" x2="92.0" y2="311.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="87.5" y="293.6" width="9" height="12.6" fill="#188a3e"/>
<line x1="108.0" y1="274.7" x2="108.0" y2="299.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="103.5" y="279.2" width="9" height="14.4" fill="#188a3e"/>
<line x1="124.0" y1="260.3" x2="124.0" y2="284.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="119.5" y="264.8" width="9" height="14.4" fill="#188a3e"/>
<line x1="140.0" y1="247.7" x2="140.0" y2="270.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="135.5" y="252.2" width="9" height="12.6" fill="#188a3e"/>
<line x1="156.0" y1="235.1" x2="156.0" y2="257.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="151.5" y="239.6" width="9" height="12.6" fill="#188a3e"/>
<line x1="172.0" y1="222.5" x2="172.0" y2="245.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="167.5" y="227.0" width="9" height="12.6" fill="#188a3e"/>
<line x1="188.0" y1="206.3" x2="188.0" y2="232.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="183.5" y="210.8" width="9" height="16.2" fill="#188a3e"/>
<line x1="204.0" y1="182.9" x2="204.0" y2="216.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="199.5" y="187.4" width="9" height="23.4" fill="#188a3e"/>
<line x1="220.0" y1="156.8" x2="220.0" y2="192.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="215.5" y="156.8" width="9" height="30.6" fill="#188a3e"/>
<line x1="236.0" y1="152.3" x2="236.0" y2="174.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="231.5" y="156.8" width="9" height="12.6" fill="#c00"/>
<line x1="252.0" y1="164.9" x2="252.0" y2="189.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="247.5" y="169.4" width="9" height="14.4" fill="#c00"/>
<line x1="268.0" y1="179.3" x2="268.0" y2="203.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="263.5" y="183.8" width="9" height="14.4" fill="#c00"/>
<line x1="284.0" y1="193.7" x2="284.0" y2="214.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="279.5" y="198.2" width="9" height="10.8" fill="#c00"/>
<line x1="300.0" y1="204.5" x2="300.0" y2="223.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="295.5" y="209.0" width="9" height="9.0" fill="#c00"/>
<line x1="316.0" y1="213.5" x2="316.0" y2="230.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="311.5" y="218.0" width="9" height="7.2" fill="#c00"/>
<line x1="332.0" y1="221.6" x2="332.0" y2="237.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="327.5" y="225.2" width="9" height="4.0" fill="#c00"/>
<line x1="348.0" y1="225.2" x2="348.0" y2="231.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="343.5" y="228.8" width="9" height="1.6" fill="#188a3e"/>
<line x1="364.0" y1="206.3" x2="364.0" y2="234.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="359.5" y="210.8" width="9" height="18.0" fill="#188a3e"/>
<line x1="380.0" y1="190.1" x2="380.0" y2="216.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="375.5" y="194.6" width="9" height="16.2" fill="#188a3e"/>
<line x1="396.0" y1="173.9" x2="396.0" y2="200.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="391.5" y="178.4" width="9" height="16.2" fill="#188a3e"/>
<line x1="412.0" y1="157.7" x2="412.0" y2="183.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="407.5" y="162.2" width="9" height="16.2" fill="#188a3e"/>
<line x1="428.0" y1="143.3" x2="428.0" y2="167.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="423.5" y="147.8" width="9" height="14.4" fill="#188a3e"/>
<line x1="444.0" y1="128.9" x2="444.0" y2="153.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="439.5" y="133.4" width="9" height="14.4" fill="#188a3e"/>
<line x1="460.0" y1="114.5" x2="460.0" y2="138.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="455.5" y="119.0" width="9" height="14.4" fill="#188a3e"/>
<line x1="476.0" y1="100.1" x2="476.0" y2="124.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="471.5" y="104.6" width="9" height="14.4" fill="#188a3e"/>
<line x1="492.0" y1="85.7" x2="492.0" y2="110.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="487.5" y="90.2" width="9" height="14.4" fill="#188a3e"/>
<line x1="508.0" y1="71.3" x2="508.0" y2="95.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="503.5" y="75.8" width="9" height="14.4" fill="#188a3e"/>
<line x1="524.0" y1="60.5" x2="524.0" y2="81.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="519.5" y="65.0" width="9" height="10.8" fill="#188a3e"/>
<line x1="540.0" y1="56.0" x2="540.0" y2="70.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="535.5" y="56.0" width="9" height="9.0" fill="#188a3e"/>
<line x1="24" y1="449.0" x2="666" y2="449.0" stroke="#888"/>
<rect x="39.5" y="410.8" width="9" height="38.2" fill="#188a3e" opacity="0.55"/>
<rect x="55.5" y="409.2" width="9" height="39.8" fill="#188a3e" opacity="0.55"/>
<rect x="71.5" y="412.4" width="9" height="36.6" fill="#188a3e" opacity="0.55"/>
<rect x="87.5" y="407.6" width="9" height="41.4" fill="#188a3e" opacity="0.55"/>
<rect x="103.5" y="406.0" width="9" height="43.0" fill="#188a3e" opacity="0.55"/>
<rect x="119.5" y="409.2" width="9" height="39.8" fill="#188a3e" opacity="0.55"/>
<rect x="135.5" y="404.5" width="9" height="44.5" fill="#188a3e" opacity="0.55"/>
<rect x="151.5" y="407.6" width="9" height="41.4" fill="#188a3e" opacity="0.55"/>
<rect x="167.5" y="402.9" width="9" height="46.1" fill="#188a3e" opacity="0.55"/>
<rect x="183.5" y="401.3" width="9" height="47.7" fill="#188a3e" opacity="0.55"/>
<rect x="199.5" y="398.1" width="9" height="50.9" fill="#188a3e" opacity="0.55"/>
<rect x="215.5" y="391.7" width="9" height="57.3" fill="#188a3e" opacity="0.55"/>
<rect x="231.5" y="393.3" width="9" height="55.7" fill="#c00" opacity="0.55"/>
<rect x="247.5" y="390.1" width="9" height="58.9" fill="#c00" opacity="0.55"/>
<rect x="263.5" y="387.0" width="9" height="62.0" fill="#c00" opacity="0.55"/>
<rect x="279.5" y="383.8" width="9" height="65.2" fill="#c00" opacity="0.55"/>
<rect x="295.5" y="380.6" width="9" height="68.4" fill="#c00" opacity="0.55"/>
<rect x="311.5" y="385.4" width="9" height="63.6" fill="#c00" opacity="0.55"/>
<rect x="327.5" y="382.2" width="9" height="66.8" fill="#c00" opacity="0.55"/>
<rect x="343.5" y="379.0" width="9" height="70.0" fill="#188a3e" opacity="0.55"/>
<rect x="359.5" y="391.7" width="9" height="57.3" fill="#188a3e" opacity="0.55"/>
<rect x="375.5" y="396.5" width="9" height="52.5" fill="#188a3e" opacity="0.55"/>
<rect x="391.5" y="399.7" width="9" height="49.3" fill="#188a3e" opacity="0.55"/>
<rect x="407.5" y="402.9" width="9" height="46.1" fill="#188a3e" opacity="0.55"/>
<rect x="423.5" y="406.0" width="9" height="43.0" fill="#188a3e" opacity="0.55"/>
<rect x="439.5" y="409.2" width="9" height="39.8" fill="#188a3e" opacity="0.55"/>
<rect x="455.5" y="412.4" width="9" height="36.6" fill="#188a3e" opacity="0.55"/>
<rect x="471.5" y="399.7" width="9" height="49.3" fill="#188a3e" opacity="0.55"/>
<rect x="487.5" y="394.9" width="9" height="54.1" fill="#188a3e" opacity="0.55"/>
<rect x="503.5" y="391.7" width="9" height="57.3" fill="#188a3e" opacity="0.55"/>
<rect x="519.5" y="387.0" width="9" height="62.0" fill="#188a3e" opacity="0.55"/>
<rect x="535.5" y="380.6" width="9" height="68.4" fill="#188a3e" opacity="0.55"/>
<text x="24" y="373.0" fill="#555">volum</text>
<text x="332.0" y="209.6" fill="#188a3e" text-anchor="middle" style="font-weight:bold">BIM</text>
<text x="348.0" y="271.9" fill="#188a3e" text-anchor="middle" style="font-weight:bold">candelă verde → trigger</text>
<text x="24" y="471.0" fill="#188a3e">Regula e pe procent, nu pe cât de dramatică arată linia: calea NU pare o cădere mare, dar e 3.9 %.</text>
<text x="24" y="496" fill="#555">Calea DA (candele): 4.0 % la 96.00. Calea NU (punctat): 3.9 % („3.93 %” în curs) — fără intrare.</text>
<polyline points="220.0,156.8 236.0,167.6 252.0,181.1 268.0,193.7 284.0,204.5 300.0,214.4 316.0,227.0 332.0,234.2 348.0,240.5 380.0,247.7 412.0,253.1 444.0,256.7" fill="none" stroke="#c00" stroke-width="1.8" stroke-dasharray="5 4"/>
<line x1="24" y1="227.0" x2="666" y2="227.0" stroke="#c00" stroke-width="1.5" stroke-dasharray="4 3"/>
<circle cx="316.0" cy="227.0" r="3.5" fill="#c00"/>
<text x="652" y="239.0" fill="#c00" text-anchor="end">96.10 = 3.9 % — NU, sub prag</text>
<text x="652" y="252.6" fill="#777" text-anchor="end">zonă quarterly</text>
<text x="24" y="183.8" fill="#188a3e" style="font-weight:bold">calea DA (candelele)</text>
<text x="444.0" y="272.7" fill="#c00" style="font-weight:bold">calea NU (continuă în jos)</text>
</svg>

Before

Width:  |  Height:  |  Size: 9.8 KiB

View File

@@ -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'<line x1="24" y1="([\d.]+)"', svg)
assert m_off, "nu găsesc linia primului Level, din care citesc offsetul pe y"
OFF = float(m_off.group(1)) - ch._y(levels[0].price)
# render() mută și `left`; offsetul pe x se citește din dreptunghiul primei zone
m_dx = re.search(r'<rect x="([\d.]+)"[^>]*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'<line x1="{x_sep:.1f}" y1="{y_top:.1f}" x2="{x_sep:.1f}" y2="{y_bot:.1f}" '
f'stroke="#444" stroke-width="1.5" stroke-dasharray="6 4"/>'
f'<text x="{x_sep - 6:.1f}" y="{y_bot + 14:.1f}" fill="#444" text-anchor="end" '
f'style="font-weight:bold">aici se termină selecția</text>'
f'<text x="{x_sep + 6:.1f}" y="{y_bot + 14:.1f}" fill="#999">aici începe capitolul 1</text>')
svg = svg.replace("</svg>", sep + "</svg>")
# ---------------------------------------------------------------- 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'<text x="24" y="(\d+)" fill="#555">' + re.escape(caption) + r"</text>\s*</svg>", svg)
assert m, "caption-ul nu a fost gasit in SVG"
m = re.search(r'<text x="24" y="(\d+)" fill="#555">' + re.escape(caption) + r"</text>", svg)
assert m, "caption-ul nu a fost găsit în SVG"
y0 = int(m.group(1))
wrapped = "\n ".join(f'<text x="24" y="{y0 + 17 * i}" fill="#555">{ln}</text>'
for i, ln in enumerate(cap_lines))
svg = svg[:m.start()] + wrapped + "\n</svg>"
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'(<text x="\d+" y=")(\d+)(" fill="#b06000">SMA-20</text>)',
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"<text[^>]*>([^<]*)</text>", 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 "<svg" in svg and "\n\n" not in svg, "linie goala in SVG"
assert "<svg" in svg and "\n\n" not in svg, "linie goală în SVG"
OUT.write_text(svg)
print(f"scris {OUT.name}: {len(cds)} candele, doji {cds[20].c:.2f} (RVOL {VOLS[20]/media_vol:.2f}), "
f"suport {min(c.l for c in cds[12:21]):.2f}, intrare 374.80, SL 352.00, "
f"TP1 383.74 = 0.39R, TP2 402.00 = 1.19R, ultimul close {cds[-1].c:.2f}")
print(f"scris {OUT.name}: 32 candele, doji {cds[DOJI].c:.2f} (RVOL {rvol:.2f}), "
f"suport {SUPORT:.2f} ({pct_suport:.2f} % sub doji), pivot {PIVOT:.2f} "
f"({pct_pivot:.2f} % peste doji), fără intrare/stop/țintă pe desen")

View File

@@ -1,121 +1,126 @@
<svg viewBox="0 0 640 653" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif">
<text x="24" y="48" fill="#333" style="font-weight:bold">ULTA — daily (pivoți monthly)</text>
<line x1="24" y1="481.4" x2="626" y2="481.4" stroke="#c00" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30" y="475.4" fill="#c00">SL 352.00</text>
<line x1="24" y1="451.8" x2="626" y2="451.8" stroke="#1a5fb4" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30" y="445.8" fill="#1a5fb4">suport monthly 355.48</text>
<line x1="24" y1="287.6" x2="626" y2="287.6" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="612" y="281.6" fill="#188a3e" text-anchor="end">intrare 374.80</text>
<line x1="24" y1="211.6" x2="626" y2="211.6" stroke="#1a5fb4" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="612" y="205.6" fill="#1a5fb4" text-anchor="end">pivot / TP1 383.74</text>
<line x1="24" y1="56.4" x2="626" y2="56.4" stroke="#1a5fb4" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="612" y="50.4" fill="#1a5fb4" text-anchor="end">TP2 402.00</text>
<polyline points="329.0,311.7 344.0,320.9 359.0,327.8 374.0,332.8 389.0,335.6 404.0,336.3 419.0,335.0 434.0,331.2 449.0,325.4 464.0,317.1 479.0,306.0 494.0,291.9 509.0,275.0" fill="none" stroke="#b06000" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="515" y="257" fill="#b06000">SMA-20</text>
<line x1="44.0" y1="99.8" x2="44.0" y2="120.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="39.5" y="103.2" width="9" height="12.8" fill="#c00"/>
<line x1="59.0" y1="112.9" x2="59.0" y2="146.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="54.5" y="115.9" width="9" height="27.2" fill="#c00"/>
<line x1="74.0" y1="140.1" x2="74.0" y2="173.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="69.5" y="143.1" width="9" height="27.2" fill="#c00"/>
<line x1="89.0" y1="167.3" x2="89.0" y2="202.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="84.5" y="170.3" width="9" height="28.9" fill="#c00"/>
<line x1="104.0" y1="196.2" x2="104.0" y2="229.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="99.5" y="199.2" width="9" height="27.2" fill="#c00"/>
<line x1="119.0" y1="223.4" x2="119.0" y2="256.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="114.5" y="226.4" width="9" height="26.4" fill="#c00"/>
<line x1="134.0" y1="249.8" x2="134.0" y2="283.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="129.5" y="252.8" width="9" height="27.2" fill="#c00"/>
<line x1="149.0" y1="277.0" x2="149.0" y2="308.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="144.5" y="280.0" width="9" height="24.6" fill="#c00"/>
<line x1="164.0" y1="301.6" x2="164.0" y2="332.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="159.5" y="304.6" width="9" height="24.7" fill="#c00"/>
<line x1="179.0" y1="326.3" x2="179.0" y2="357.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="174.5" y="329.3" width="9" height="24.6" fill="#c00"/>
<line x1="194.0" y1="350.9" x2="194.0" y2="381.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="189.5" y="353.9" width="9" height="23.8" fill="#c00"/>
<line x1="209.0" y1="374.8" x2="209.0" y2="401.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="204.5" y="377.7" width="9" height="20.4" fill="#c00"/>
<line x1="224.0" y1="383.2" x2="224.0" y2="401.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="219.5" y="386.2" width="9" height="11.9" fill="#188a3e"/>
<line x1="239.0" y1="383.2" x2="239.0" y2="408.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="234.5" y="386.2" width="9" height="18.7" fill="#c00"/>
<line x1="254.0" y1="401.9" x2="254.0" y2="429.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="249.5" y="404.9" width="9" height="21.2" fill="#c00"/>
<line x1="269.0" y1="423.6" x2="269.0" y2="451.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="264.5" y="426.2" width="9" height="19.6" fill="#c00"/>
<line x1="284.0" y1="410.0" x2="284.0" y2="448.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="279.5" y="413.4" width="9" height="32.3" fill="#188a3e"/>
<line x1="299.0" y1="367.9" x2="299.0" y2="416.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="294.5" y="370.9" width="9" height="42.5" fill="#188a3e"/>
<line x1="314.0" y1="329.7" x2="314.0" y2="374.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="309.5" y="332.7" width="9" height="38.2" fill="#188a3e"/>
<line x1="329.0" y1="299.9" x2="329.0" y2="336.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="324.5" y="302.9" width="9" height="29.8" fill="#188a3e"/>
<line x1="344.0" y1="293.6" x2="344.0" y2="305.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="339.5" y="300.4" width="9" height="2.6" fill="#188a3e"/>
<line x1="359.0" y1="277.8" x2="359.0" y2="303.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="354.5" y="280.8" width="9" height="19.6" fill="#188a3e"/>
<line x1="374.0" y1="265.9" x2="374.0" y2="284.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="369.5" y="268.9" width="9" height="11.9" fill="#188a3e"/>
<line x1="389.0" y1="253.2" x2="389.0" y2="272.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="384.5" y="256.2" width="9" height="12.8" fill="#188a3e"/>
<line x1="404.0" y1="237.1" x2="404.0" y2="259.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="399.5" y="240.0" width="9" height="16.1" fill="#188a3e"/>
<line x1="419.0" y1="223.4" x2="419.0" y2="243.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="414.5" y="226.4" width="9" height="13.6" fill="#188a3e"/>
<line x1="434.0" y1="202.2" x2="434.0" y2="229.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="429.5" y="205.2" width="9" height="21.2" fill="#188a3e"/>
<line x1="449.0" y1="185.2" x2="449.0" y2="208.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="444.5" y="188.2" width="9" height="17.0" fill="#188a3e"/>
<line x1="464.0" y1="159.7" x2="464.0" y2="191.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="459.5" y="162.7" width="9" height="25.5" fill="#188a3e"/>
<line x1="479.0" y1="129.9" x2="479.0" y2="166.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="474.5" y="132.9" width="9" height="29.8" fill="#188a3e"/>
<line x1="494.0" y1="91.7" x2="494.0" y2="136.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="489.5" y="94.7" width="9" height="38.2" fill="#188a3e"/>
<line x1="509.0" y1="56.0" x2="509.0" y2="98.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="504.5" y="60.7" width="9" height="34.0" fill="#188a3e"/>
<line x1="24" y1="577.4" x2="626" y2="577.4" stroke="#888"/>
<rect x="39.5" y="541.6" width="9" height="35.9" fill="#c00" opacity="0.55"/>
<rect x="54.5" y="539.9" width="9" height="37.6" fill="#c00" opacity="0.55"/>
<rect x="69.5" y="542.4" width="9" height="35.0" fill="#c00" opacity="0.55"/>
<rect x="84.5" y="538.2" width="9" height="39.3" fill="#c00" opacity="0.55"/>
<rect x="99.5" y="540.7" width="9" height="36.7" fill="#c00" opacity="0.55"/>
<rect x="114.5" y="539.0" width="9" height="38.4" fill="#c00" opacity="0.55"/>
<rect x="129.5" y="543.3" width="9" height="34.1" fill="#c00" opacity="0.55"/>
<rect x="144.5" y="539.9" width="9" height="37.6" fill="#c00" opacity="0.55"/>
<rect x="159.5" y="537.3" width="9" height="40.1" fill="#c00" opacity="0.55"/>
<rect x="174.5" y="540.7" width="9" height="36.7" fill="#c00" opacity="0.55"/>
<rect x="189.5" y="543.3" width="9" height="34.1" fill="#c00" opacity="0.55"/>
<rect x="204.5" y="541.6" width="9" height="35.9" fill="#c00" opacity="0.55"/>
<rect x="219.5" y="545.0" width="9" height="32.4" fill="#188a3e" opacity="0.55"/>
<rect x="234.5" y="542.4" width="9" height="35.0" fill="#c00" opacity="0.55"/>
<rect x="249.5" y="533.0" width="9" height="44.4" fill="#c00" opacity="0.55"/>
<rect x="264.5" y="529.6" width="9" height="47.8" fill="#c00" opacity="0.55"/>
<rect x="279.5" y="534.7" width="9" height="42.7" fill="#188a3e" opacity="0.55"/>
<rect x="294.5" y="539.0" width="9" height="38.4" fill="#188a3e" opacity="0.55"/>
<rect x="309.5" y="541.6" width="9" height="35.9" fill="#188a3e" opacity="0.55"/>
<rect x="324.5" y="544.1" width="9" height="33.3" fill="#188a3e" opacity="0.55"/>
<rect x="339.5" y="551.8" width="9" height="25.6" fill="#188a3e" opacity="0.55"/>
<rect x="354.5" y="538.2" width="9" height="39.3" fill="#188a3e" opacity="0.55"/>
<rect x="369.5" y="536.4" width="9" height="41.0" fill="#188a3e" opacity="0.55"/>
<rect x="384.5" y="534.7" width="9" height="42.7" fill="#188a3e" opacity="0.55"/>
<rect x="399.5" y="533.0" width="9" height="44.4" fill="#188a3e" opacity="0.55"/>
<rect x="414.5" y="531.3" width="9" height="46.1" fill="#188a3e" opacity="0.55"/>
<rect x="429.5" y="527.9" width="9" height="49.5" fill="#188a3e" opacity="0.55"/>
<rect x="444.5" y="524.5" width="9" height="52.9" fill="#188a3e" opacity="0.55"/>
<rect x="459.5" y="521.1" width="9" height="56.3" fill="#188a3e" opacity="0.55"/>
<rect x="474.5" y="517.7" width="9" height="59.8" fill="#188a3e" opacity="0.55"/>
<rect x="489.5" y="512.5" width="9" height="64.9" fill="#188a3e" opacity="0.55"/>
<rect x="504.5" y="507.4" width="9" height="70.0" fill="#188a3e" opacity="0.55"/>
<text x="24" y="501.4" fill="#555">volum</text>
<text x="32.0" y="78.2" fill="#777" text-anchor="start" style="font-weight:bold">downtrend weekly</text>
<text x="344.0" y="325.5" fill="#00a0aa" text-anchor="middle" style="font-weight:bold">buy doji close 373.30 (RVOL 0.61)</text>
<text x="359.0" y="267.8" fill="#188a3e" text-anchor="middle" style="font-weight:bold">intrare 374.80</text>
<text x="434.0" y="184.2" fill="#1a5fb4" text-anchor="middle" style="font-weight:bold">TP1 383.74 = pivot</text>
<text x="509.0" y="24.0" fill="#1a5fb4" text-anchor="middle" style="font-weight:bold">TP2 402.00</text>
<text x="24" y="607" fill="#555">Ale cursului: close 373.30, suport 355.48, pivot 383.74, RVOL 0.61. Intrarea 374.80, SL</text>
<text x="24" y="624" fill="#555">352.00 si TP2 402.00 sunt estimari din 04_MODUL_3/01; structura barelor dintre niveluri e</text>
<text x="24" y="641" fill="#555">construita, la scara.</text>
</svg>
<svg viewBox="0 0 836 803" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif">
<text x="24" y="104" fill="#333" style="font-weight:bold">ULTA — daily: ce citește selecția și unde se oprește</text>
<rect x="188.3" y="146.0" width="184.0" height="317.7" fill="#c00" fill-opacity="0.08" stroke="#c00" stroke-width="1"/>
<text x="188.3" y="141.0" fill="#c00" style="font-weight:bold">1. downtrend — de asta apare în scaner</text>
<rect x="368.3" y="334.3" width="139.0" height="176.9" fill="#1a5fb4" fill-opacity="0.08" stroke="#1a5fb4" stroke-width="1"/>
<line x1="24" y1="506.1" x2="822" y2="506.1" stroke="#1a5fb4" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30" y="500.1" fill="#1a5fb4">suport monthly 355.48</text>
<line x1="24" y1="265.9" x2="822" y2="265.9" stroke="#1a5fb4" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="808" y="259.9" fill="#1a5fb4" text-anchor="end">pivot monthly 383.74</text>
<polyline points="482.8,365.9 497.8,375.2 512.8,382.1 527.8,387.0 542.8,389.8 557.8,390.5 572.8,389.2 587.8,385.5 602.8,379.6 617.8,371.3 632.8,360.3 647.8,346.1 662.8,329.2" fill="none" stroke="#b06000" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="669" y="323" fill="#b06000">SMA-20</text>
<line x1="197.8" y1="154.0" x2="197.8" y2="174.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="193.3" y="157.4" width="9" height="12.8" fill="#c00"/>
<line x1="212.8" y1="167.2" x2="212.8" y2="200.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="208.3" y="170.1" width="9" height="27.2" fill="#c00"/>
<line x1="227.8" y1="194.4" x2="227.8" y2="227.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="223.3" y="197.3" width="9" height="27.2" fill="#c00"/>
<line x1="242.8" y1="221.6" x2="242.8" y2="256.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="238.3" y="224.5" width="9" height="28.9" fill="#c00"/>
<line x1="257.8" y1="250.5" x2="257.8" y2="284.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="253.3" y="253.4" width="9" height="27.2" fill="#c00"/>
<line x1="272.8" y1="277.7" x2="272.8" y2="310.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="268.3" y="280.6" width="9" height="26.4" fill="#c00"/>
<line x1="287.8" y1="304.0" x2="287.8" y2="337.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="283.3" y="307.0" width="9" height="27.2" fill="#c00"/>
<line x1="302.8" y1="331.2" x2="302.8" y2="362.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="298.3" y="334.2" width="9" height="24.6" fill="#c00"/>
<line x1="317.8" y1="355.9" x2="317.8" y2="386.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="313.3" y="358.8" width="9" height="24.7" fill="#c00"/>
<line x1="332.8" y1="380.5" x2="332.8" y2="411.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="328.3" y="383.5" width="9" height="24.6" fill="#c00"/>
<line x1="347.8" y1="405.2" x2="347.8" y2="435.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="343.3" y="408.1" width="9" height="23.8" fill="#c00"/>
<line x1="362.8" y1="429.0" x2="362.8" y2="455.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="358.3" y="431.9" width="9" height="20.4" fill="#c00"/>
<line x1="377.8" y1="437.5" x2="377.8" y2="455.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="373.3" y="440.4" width="9" height="11.9" fill="#188a3e"/>
<line x1="392.8" y1="437.5" x2="392.8" y2="462.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="388.3" y="440.4" width="9" height="18.7" fill="#c00"/>
<line x1="407.8" y1="456.2" x2="407.8" y2="483.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="403.3" y="459.1" width="9" height="21.2" fill="#c00"/>
<line x1="422.8" y1="477.8" x2="422.8" y2="506.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="418.3" y="480.4" width="9" height="19.6" fill="#c00"/>
<line x1="437.8" y1="464.2" x2="437.8" y2="502.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="433.3" y="467.6" width="9" height="32.3" fill="#188a3e"/>
<line x1="452.8" y1="422.2" x2="452.8" y2="471.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="448.3" y="425.1" width="9" height="42.5" fill="#188a3e"/>
<line x1="467.8" y1="383.9" x2="467.8" y2="428.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="463.3" y="386.9" width="9" height="38.2" fill="#188a3e"/>
<line x1="482.8" y1="354.2" x2="482.8" y2="390.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="478.3" y="357.1" width="9" height="29.8" fill="#188a3e"/>
<line x1="497.8" y1="342.3" x2="497.8" y2="369.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="493.3" y="354.6" width="9" height="2.6" fill="#188a3e"/>
<line x1="512.8" y1="332.1" x2="512.8" y2="358.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="508.3" y="335.0" width="9" height="19.6" fill="#bbb"/>
<line x1="527.8" y1="320.2" x2="527.8" y2="338.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="523.3" y="323.1" width="9" height="11.9" fill="#bbb"/>
<line x1="542.8" y1="307.4" x2="542.8" y2="326.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="538.3" y="310.4" width="9" height="12.8" fill="#bbb"/>
<line x1="557.8" y1="291.3" x2="557.8" y2="313.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="553.3" y="294.2" width="9" height="16.1" fill="#bbb"/>
<line x1="572.8" y1="277.7" x2="572.8" y2="297.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="568.3" y="280.6" width="9" height="13.6" fill="#bbb"/>
<line x1="587.8" y1="256.4" x2="587.8" y2="284.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="583.3" y="259.4" width="9" height="21.2" fill="#bbb"/>
<line x1="602.8" y1="239.4" x2="602.8" y2="262.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="598.3" y="242.4" width="9" height="17.0" fill="#bbb"/>
<line x1="617.8" y1="213.9" x2="617.8" y2="245.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="613.3" y="216.9" width="9" height="25.5" fill="#bbb"/>
<line x1="632.8" y1="184.2" x2="632.8" y2="220.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="628.3" y="187.1" width="9" height="29.8" fill="#bbb"/>
<line x1="647.8" y1="145.9" x2="647.8" y2="190.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="643.3" y="148.9" width="9" height="38.2" fill="#bbb"/>
<line x1="662.8" y1="111.9" x2="662.8" y2="152.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="658.3" y="114.9" width="9" height="34.0" fill="#bbb"/>
<line x1="24" y1="703.1" x2="822" y2="703.1" stroke="#888"/>
<rect x="193.3" y="667.2" width="9" height="35.9" fill="#c00" opacity="0.55"/>
<rect x="208.3" y="665.5" width="9" height="37.6" fill="#c00" opacity="0.55"/>
<rect x="223.3" y="668.1" width="9" height="35.0" fill="#c00" opacity="0.55"/>
<rect x="238.3" y="663.8" width="9" height="39.3" fill="#c00" opacity="0.55"/>
<rect x="253.3" y="666.4" width="9" height="36.7" fill="#c00" opacity="0.55"/>
<rect x="268.3" y="664.7" width="9" height="38.4" fill="#c00" opacity="0.55"/>
<rect x="283.3" y="668.9" width="9" height="34.1" fill="#c00" opacity="0.55"/>
<rect x="298.3" y="665.5" width="9" height="37.6" fill="#c00" opacity="0.55"/>
<rect x="313.3" y="662.9" width="9" height="40.1" fill="#c00" opacity="0.55"/>
<rect x="328.3" y="666.4" width="9" height="36.7" fill="#c00" opacity="0.55"/>
<rect x="343.3" y="668.9" width="9" height="34.1" fill="#c00" opacity="0.55"/>
<rect x="358.3" y="667.2" width="9" height="35.9" fill="#c00" opacity="0.55"/>
<rect x="373.3" y="670.6" width="9" height="32.4" fill="#188a3e" opacity="0.55"/>
<rect x="388.3" y="668.1" width="9" height="35.0" fill="#c00" opacity="0.55"/>
<rect x="403.3" y="658.7" width="9" height="44.4" fill="#c00" opacity="0.55"/>
<rect x="418.3" y="655.3" width="9" height="47.8" fill="#c00" opacity="0.55"/>
<rect x="433.3" y="660.4" width="9" height="42.7" fill="#188a3e" opacity="0.55"/>
<rect x="448.3" y="664.7" width="9" height="38.4" fill="#188a3e" opacity="0.55"/>
<rect x="463.3" y="667.2" width="9" height="35.9" fill="#188a3e" opacity="0.55"/>
<rect x="478.3" y="669.8" width="9" height="33.3" fill="#188a3e" opacity="0.55"/>
<rect x="493.3" y="677.5" width="9" height="25.6" fill="#188a3e" opacity="0.55"/>
<rect x="508.3" y="663.8" width="9" height="39.3" fill="#bbb" opacity="0.55"/>
<rect x="523.3" y="662.1" width="9" height="41.0" fill="#bbb" opacity="0.55"/>
<rect x="538.3" y="660.4" width="9" height="42.7" fill="#bbb" opacity="0.55"/>
<rect x="553.3" y="658.7" width="9" height="44.4" fill="#bbb" opacity="0.55"/>
<rect x="568.3" y="657.0" width="9" height="46.1" fill="#bbb" opacity="0.55"/>
<rect x="583.3" y="653.6" width="9" height="49.5" fill="#bbb" opacity="0.55"/>
<rect x="598.3" y="650.1" width="9" height="52.9" fill="#bbb" opacity="0.55"/>
<rect x="613.3" y="646.7" width="9" height="56.3" fill="#bbb" opacity="0.55"/>
<rect x="628.3" y="643.3" width="9" height="59.8" fill="#bbb" opacity="0.55"/>
<rect x="643.3" y="638.2" width="9" height="64.9" fill="#bbb" opacity="0.55"/>
<rect x="658.3" y="633.1" width="9" height="70.0" fill="#bbb" opacity="0.55"/>
<text x="24" y="627.1" fill="#555">volum</text>
<line x1="392.8" y1="570.1" x2="419.2" y2="517.2" stroke="#1a5fb4" stroke-width="1.8"/>
<polygon points="422.8,510.1 422.8,519.0 415.6,515.4" fill="#1a5fb4"/>
<text x="392.8" y="584.1" fill="#1a5fb4" text-anchor="middle" style="font-weight:bold">2. suportul monthly 355.48 a mai întors prețul o dată:</text>
<text x="392.8" y="598.1" fill="#1a5fb4" text-anchor="middle" style="font-weight:bold">acolo stau ordine de cumpărare, deci coborârea are unde să se oprească</text>
<line x1="247.8" y1="80.0" x2="492.2" y2="332.5" stroke="#00a0aa" stroke-width="1.8"/>
<polygon points="497.8,338.3 489.4,335.3 495.1,329.7" fill="#00a0aa"/>
<text x="247.8" y="47.0" fill="#00a0aa" text-anchor="middle" style="font-weight:bold">3. buy doji, close 373.30 — aici se oprește selecția</text>
<text x="247.8" y="61.0" fill="#00a0aa" text-anchor="middle" style="font-weight:bold">5.01 % peste suport, 2.72 % sub pivot: trece proximitatea față de pivot</text>
<text x="247.8" y="75.0" fill="#00a0aa" text-anchor="middle" style="font-weight:bold">volumul zilei = 0.61 din medie (RVOL 0.61), sub pragul de 1.00: minus, nu veto</text>
<line x1="657.3" y1="202.4" x2="617.3" y2="237.2" stroke="#777" stroke-width="1.8"/>
<polygon points="611.3,242.4 614.7,234.1 620.0,240.2" fill="#777"/>
<text x="661.3" y="199.4" fill="#777" text-anchor="start" style="font-weight:bold">trigger, stop și țintă sunt</text>
<text x="661.3" y="213.4" fill="#777" text-anchor="start" style="font-weight:bold">ale capitolului Buy Doji</text>
<text x="24" y="733" fill="#555">Ale cursului: close 373.30, suport monthly 355.48, pivot monthly 383.74, RVOL 0.61.</text>
<text x="24" y="750" fill="#555">Procentele sunt calculate din ele. Structura barelor e construită, la scară. Intrarea,</text>
<text x="24" y="767" fill="#555">stopul și ținta nu apar pe desen: nu aparțin selecției.</text>
<line x1="505.3" y1="116.0" x2="505.3" y2="522.1" stroke="#444" stroke-width="1.5" stroke-dasharray="6 4"/><text x="499.3" y="536.1" fill="#444" text-anchor="end" style="font-weight:bold">aici se termină selecția</text><text x="511.3" y="536.1" fill="#999">aici începe capitolul 1</text></svg>

Before

Width:  |  Height:  |  Size: 9.9 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -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

View File

@@ -1,47 +1,92 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 700 720" width="700" height="720" font-family="system-ui, sans-serif" role="img" aria-label="Matricea 2x2 a relative strength: cadranele 1 si 2 sunt pentru long, cadranele 3 si 4 pentru short; cadranul 4 nu se tranzactioneaza pe orb">
<rect x="0" y="0" width="700" height="720" fill="#ffffff"/>
<rect x="130.0" y="134.0" width="440.0" height="280.0" fill="#ffffff" stroke="#777777" stroke-width="1.0"/>
<line x1="130.0" y1="274.0" x2="570.0" y2="274.0" stroke="#777777" stroke-width="1.0" stroke-dasharray="4 4"/>
<line x1="350.0" y1="134.0" x2="350.0" y2="414.0" stroke="#777777" stroke-width="1.0" stroke-dasharray="4 4"/>
<rect x="130.0" y="134.0" width="218.0" height="138.0" fill="#fdeeee" stroke="#c00" stroke-width="1.6"/>
<rect x="352.0" y="134.0" width="218.0" height="138.0" fill="#eef7f0" stroke="#188a3e" stroke-width="1.6"/>
<rect x="130.0" y="276.0" width="218.0" height="138.0" fill="#fdeeee" stroke="#c00" stroke-width="1.6" stroke-dasharray="6 4"/>
<rect x="352.0" y="276.0" width="218.0" height="138.0" fill="#eef7f0" stroke="#188a3e" stroke-width="1.6"/>
<rect x="40.0" y="460.0" width="620.0" height="196.0" fill="#fdf0e0" stroke="#b06000" stroke-width="1.6"/>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 700 812" width="700" height="812" font-family="system-ui, sans-serif" role="img" aria-label="Matricea 2x2 a relative strength: cadranele 1 si 2 sunt pentru long, cadranele 3 si 4 pentru short; cadranul 4 nu se tranzactioneaza pe orb">
<rect x="0" y="0" width="700" height="812" fill="#ffffff"/>
<rect x="130.0" y="134.0" width="440.0" height="368.0" fill="#ffffff" stroke="#777777" stroke-width="1.0"/>
<line x1="130.0" y1="318.0" x2="570.0" y2="318.0" stroke="#777777" stroke-width="1.0" stroke-dasharray="4 4"/>
<line x1="350.0" y1="134.0" x2="350.0" y2="502.0" stroke="#777777" stroke-width="1.0" stroke-dasharray="4 4"/>
<rect x="130.0" y="134.0" width="218.0" height="182.0" fill="#fdeeee" stroke="#c00" stroke-width="1.6"/>
<rect x="352.0" y="134.0" width="218.0" height="182.0" fill="#eef7f0" stroke="#188a3e" stroke-width="1.6"/>
<rect x="130.0" y="320.0" width="218.0" height="182.0" fill="#fdeeee" stroke="#c00" stroke-width="1.6" stroke-dasharray="6 4"/>
<rect x="352.0" y="320.0" width="218.0" height="182.0" fill="#eef7f0" stroke="#188a3e" stroke-width="1.6"/>
<rect x="160.0" y="240.0" width="158.0" height="46.0" fill="#ffffff" stroke="#777777" stroke-width="0.8"/>
<line x1="160.0" y1="263.0" x2="318.0" y2="263.0" stroke="#000000" stroke-width="1.0"/>
<rect x="163.3" y="243.0" width="11.0" height="20.0" fill="#c00" fill-opacity="0.35"/>
<rect x="180.8" y="243.0" width="11.0" height="20.0" fill="#c00" fill-opacity="0.35"/>
<rect x="198.4" y="246.3" width="11.0" height="16.7" fill="#c00" fill-opacity="0.35"/>
<rect x="216.0" y="246.3" width="11.0" height="16.7" fill="#c00" fill-opacity="0.35"/>
<rect x="233.5" y="249.7" width="11.0" height="13.3" fill="#c00" fill-opacity="0.35"/>
<rect x="251.1" y="253.0" width="11.0" height="10.0" fill="#c00" fill-opacity="0.35"/>
<rect x="268.6" y="253.0" width="11.0" height="10.0" fill="#c00" fill-opacity="0.35"/>
<rect x="286.2" y="256.3" width="11.0" height="6.7" fill="#c00" fill-opacity="0.35"/>
<rect x="303.7" y="259.7" width="11.0" height="3.3" fill="#c00" fill-opacity="1.0"/>
<polyline points="168.8,243.0 186.3,243.0 203.9,244.1 221.4,244.7 239.0,246.3 256.6,248.8 274.1,250.5 291.7,253.0 309.2,255.5" fill="none" stroke="#b06000" stroke-width="1.6" stroke-dasharray="3 2"/>
<rect x="382.0" y="240.0" width="158.0" height="46.0" fill="#ffffff" stroke="#777777" stroke-width="0.8"/>
<line x1="382.0" y1="263.0" x2="540.0" y2="263.0" stroke="#000000" stroke-width="1.0"/>
<rect x="385.3" y="263.0" width="11.0" height="3.3" fill="#188a3e" fill-opacity="0.35"/>
<rect x="402.8" y="263.0" width="11.0" height="0.0" fill="#188a3e" fill-opacity="0.35"/>
<rect x="420.4" y="259.7" width="11.0" height="3.3" fill="#188a3e" fill-opacity="0.35"/>
<rect x="438.0" y="256.3" width="11.0" height="6.7" fill="#188a3e" fill-opacity="0.35"/>
<rect x="455.5" y="256.3" width="11.0" height="6.7" fill="#188a3e" fill-opacity="0.35"/>
<rect x="473.1" y="253.0" width="11.0" height="10.0" fill="#188a3e" fill-opacity="0.35"/>
<rect x="490.6" y="249.7" width="11.0" height="13.3" fill="#188a3e" fill-opacity="0.35"/>
<rect x="508.2" y="246.3" width="11.0" height="16.7" fill="#188a3e" fill-opacity="0.35"/>
<rect x="525.7" y="243.0" width="11.0" height="20.0" fill="#188a3e" fill-opacity="1.0"/>
<polyline points="390.8,266.3 408.3,264.7 425.9,263.0 443.4,261.3 461.0,258.8 478.6,256.3 496.1,253.8 513.7,251.3 531.2,248.0" fill="none" stroke="#b06000" stroke-width="1.6" stroke-dasharray="3 2"/>
<rect x="160.0" y="422.0" width="158.0" height="46.0" fill="#ffffff" stroke="#777777" stroke-width="0.8"/>
<line x1="160.0" y1="445.0" x2="318.0" y2="445.0" stroke="#000000" stroke-width="1.0"/>
<rect x="163.3" y="441.7" width="11.0" height="3.3" fill="#c00" fill-opacity="0.35"/>
<rect x="180.8" y="445.0" width="11.0" height="0.0" fill="#c00" fill-opacity="0.35"/>
<rect x="198.4" y="445.0" width="11.0" height="3.3" fill="#c00" fill-opacity="0.35"/>
<rect x="216.0" y="445.0" width="11.0" height="6.7" fill="#c00" fill-opacity="0.35"/>
<rect x="233.5" y="445.0" width="11.0" height="6.7" fill="#c00" fill-opacity="0.35"/>
<rect x="251.1" y="445.0" width="11.0" height="10.0" fill="#c00" fill-opacity="0.35"/>
<rect x="268.6" y="445.0" width="11.0" height="13.3" fill="#c00" fill-opacity="0.35"/>
<rect x="286.2" y="445.0" width="11.0" height="16.7" fill="#c00" fill-opacity="0.35"/>
<rect x="303.7" y="445.0" width="11.0" height="20.0" fill="#c00" fill-opacity="1.0"/>
<polyline points="168.8,441.7 186.3,443.3 203.9,445.0 221.4,446.7 239.0,449.2 256.6,451.7 274.1,454.2 291.7,456.7 309.2,460.0" fill="none" stroke="#b06000" stroke-width="1.6" stroke-dasharray="3 2"/>
<rect x="382.0" y="422.0" width="158.0" height="46.0" fill="#ffffff" stroke="#777777" stroke-width="0.8"/>
<line x1="382.0" y1="445.0" x2="540.0" y2="445.0" stroke="#000000" stroke-width="1.0"/>
<rect x="385.3" y="445.0" width="11.0" height="20.0" fill="#188a3e" fill-opacity="0.35"/>
<rect x="402.8" y="445.0" width="11.0" height="20.0" fill="#188a3e" fill-opacity="0.35"/>
<rect x="420.4" y="445.0" width="11.0" height="16.7" fill="#188a3e" fill-opacity="0.35"/>
<rect x="438.0" y="445.0" width="11.0" height="16.7" fill="#188a3e" fill-opacity="0.35"/>
<rect x="455.5" y="445.0" width="11.0" height="13.3" fill="#188a3e" fill-opacity="0.35"/>
<rect x="473.1" y="445.0" width="11.0" height="10.0" fill="#188a3e" fill-opacity="0.35"/>
<rect x="490.6" y="445.0" width="11.0" height="10.0" fill="#188a3e" fill-opacity="0.35"/>
<rect x="508.2" y="445.0" width="11.0" height="6.7" fill="#188a3e" fill-opacity="0.35"/>
<rect x="525.7" y="445.0" width="11.0" height="3.3" fill="#188a3e" fill-opacity="1.0"/>
<polyline points="390.8,465.0 408.3,465.0 425.9,463.9 443.4,463.3 461.0,461.7 478.6,459.2 496.1,457.5 513.7,455.0 531.2,452.5" fill="none" stroke="#b06000" stroke-width="1.6" stroke-dasharray="3 2"/>
<rect x="40.0" y="556.0" width="620.0" height="196.0" fill="#fdf0e0" stroke="#b06000" stroke-width="1.6"/>
<text x="350.0" y="34.0" font-size="20" font-weight="bold" fill="#000000" text-anchor="middle">Relative strength — cele 4 cadrane</text>
<text x="350.0" y="58.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="middle">RS = cât de bine se mișcă simbolul față de benchmark (ex. SPY)</text>
<text x="350.0" y="80.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="middle">Axa verticală: histograma RS față de 0 (peste / sub 0)</text>
<text x="350.0" y="98.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="middle">Axa orizontală: histograma RS față de MA (peste / sub MA)</text>
<text x="241.0" y="122.0" font-size="14" font-weight="bold" fill="#b06000" text-anchor="middle">sub MA</text>
<text x="461.0" y="122.0" font-size="14" font-weight="bold" fill="#1a5fb4" text-anchor="middle">peste MA</text>
<text x="122.0" y="203.0" font-size="14" font-weight="bold" fill="#188a3e" text-anchor="end">peste 0</text>
<text x="122.0" y="345.0" font-size="14" font-weight="bold" fill="#c00" text-anchor="end">sub 0</text>
<text x="239.0" y="164.0" font-size="16" font-weight="bold" fill="#000000" text-anchor="middle">Cadran 3</text>
<text x="239.0" y="186.0" font-size="14" font-weight="bold" fill="#c00" text-anchor="middle">înrăutățire</text>
<text x="239.0" y="214.0" font-size="13" font-weight="normal" fill="#000000" text-anchor="middle">peste 0, dar sub MA</text>
<text x="239.0" y="246.0" font-size="16" font-weight="bold" fill="#c00" text-anchor="middle">SHORT</text>
<text x="461.0" y="164.0" font-size="16" font-weight="bold" fill="#000000" text-anchor="middle">Cadran 1</text>
<text x="461.0" y="186.0" font-size="14" font-weight="bold" fill="#188a3e" text-anchor="middle">supraperformanță</text>
<text x="461.0" y="214.0" font-size="13" font-weight="normal" fill="#000000" text-anchor="middle">peste 0 și peste MA</text>
<text x="461.0" y="246.0" font-size="16" font-weight="bold" fill="#188a3e" text-anchor="middle">LONG</text>
<text x="239.0" y="302.0" font-size="16" font-weight="bold" fill="#000000" text-anchor="middle">Cadran 4</text>
<text x="239.0" y="324.0" font-size="14" font-weight="bold" fill="#c00" text-anchor="middle">subperformanță</text>
<text x="239.0" y="350.0" font-size="13" font-weight="normal" fill="#000000" text-anchor="middle">sub 0 și sub MA</text>
<text x="239.0" y="376.0" font-size="15" font-weight="bold" fill="#c00" text-anchor="middle">SHORT</text>
<text x="239.0" y="398.0" font-size="13" font-weight="normal" fill="#c00" text-anchor="middle">stai pe margine</text>
<text x="461.0" y="302.0" font-size="16" font-weight="bold" fill="#000000" text-anchor="middle">Cadran 2</text>
<text x="461.0" y="324.0" font-size="14" font-weight="bold" fill="#188a3e" text-anchor="middle">îmbunătățire</text>
<text x="461.0" y="350.0" font-size="13" font-weight="normal" fill="#000000" text-anchor="middle">sub 0, dar peste MA</text>
<text x="461.0" y="376.0" font-size="15" font-weight="bold" fill="#188a3e" text-anchor="middle">LONG</text>
<text x="461.0" y="398.0" font-size="13" font-weight="normal" fill="#188a3e" text-anchor="middle">zona de cumpărat</text>
<text x="350.0" y="442.0" font-size="14" font-weight="bold" fill="#000000" text-anchor="middle">Long = cadranele 1-2 · Short = cadranele 3-4</text>
<text x="60.0" y="488.0" font-size="15" font-weight="bold" fill="#c00" text-anchor="start">Avertisment — cadranul 4 nu se tranzacționează pe orb</text>
<text x="60.0" y="516.0" font-size="13" font-weight="normal" fill="#000000" text-anchor="start">„Cadranul 4 nu se tranzacționează pe orb: aștepți trecerea în 2 sau 1,</text>
<text x="60.0" y="536.0" font-size="13" font-weight="normal" fill="#000000" text-anchor="start">ori un MP4-1 / MBT-10 long ca semn de schimbare.”</text>
<text x="60.0" y="566.0" font-size="13" font-weight="bold" fill="#000000" text-anchor="start">„Un setup de bottom cu RS fără îmbunătățire are șanse mai mici.”</text>
<text x="60.0" y="596.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="start">Notă: transcrierea descrierii cadranului 4 are o eroare (îl descrie ca pe</text>
<text x="60.0" y="616.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="start">cadranul 3); definiția de mai sus e completarea sumarului —</text>
<text x="60.0" y="636.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="start">03_MODUL_2/06_indicatorul_de_performanta.md:41-48.</text>
<text x="350.0" y="686.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="middle">Surse: 08_ANALIZA_ZILNICA/11_selectia_simbolului.md:486-499, :501-508;</text>
<text x="350.0" y="704.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="middle">03_MODUL_2/06_indicatorul_de_performanta.md:31-39.</text>
<text x="122.0" y="225.0" font-size="14" font-weight="bold" fill="#188a3e" text-anchor="end">peste 0</text>
<text x="122.0" y="411.0" font-size="14" font-weight="bold" fill="#c00" text-anchor="end">sub 0</text>
<text x="239.0" y="160.0" font-size="16" font-weight="bold" fill="#000000" text-anchor="middle">Cadran 3</text>
<text x="239.0" y="182.0" font-size="14" font-weight="bold" fill="#c00" text-anchor="middle">înrăutățire</text>
<text x="239.0" y="204.0" font-size="13" font-weight="normal" fill="#000000" text-anchor="middle">peste 0, dar sub MA</text>
<text x="239.0" y="228.0" font-size="16" font-weight="bold" fill="#c00" text-anchor="middle">SHORT</text>
<text x="461.0" y="160.0" font-size="16" font-weight="bold" fill="#000000" text-anchor="middle">Cadran 1</text>
<text x="461.0" y="182.0" font-size="14" font-weight="bold" fill="#188a3e" text-anchor="middle">supraperformanță</text>
<text x="461.0" y="204.0" font-size="13" font-weight="normal" fill="#000000" text-anchor="middle">peste 0 și peste MA</text>
<text x="461.0" y="228.0" font-size="16" font-weight="bold" fill="#188a3e" text-anchor="middle">LONG</text>
<text x="239.0" y="344.0" font-size="16" font-weight="bold" fill="#000000" text-anchor="middle">Cadran 4</text>
<text x="239.0" y="366.0" font-size="14" font-weight="bold" fill="#c00" text-anchor="middle">subperformanță</text>
<text x="239.0" y="388.0" font-size="13" font-weight="normal" fill="#000000" text-anchor="middle">sub 0 și sub MA</text>
<text x="239.0" y="410.0" font-size="14" font-weight="bold" fill="#c00" text-anchor="middle">SHORT — stai pe margine</text>
<text x="461.0" y="344.0" font-size="16" font-weight="bold" fill="#000000" text-anchor="middle">Cadran 2</text>
<text x="461.0" y="366.0" font-size="14" font-weight="bold" fill="#188a3e" text-anchor="middle">îmbunătățire</text>
<text x="461.0" y="388.0" font-size="13" font-weight="normal" fill="#000000" text-anchor="middle">sub 0, dar peste MA</text>
<text x="461.0" y="410.0" font-size="14" font-weight="bold" fill="#188a3e" text-anchor="middle">LONG — zona de cumpărat</text>
<text x="350.0" y="530.0" font-size="14" font-weight="bold" fill="#000000" text-anchor="middle">Long = cadranele 1-2 · Short = cadranele 3-4</text>
<text x="350.0" y="548.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="middle">în fiecare cadran: histograma RS (barele), linia de 0 și media mobilă (punctat portocaliu)</text>
<text x="60.0" y="584.0" font-size="15" font-weight="bold" fill="#c00" text-anchor="start">Avertisment — cadranul 4 nu se tranzacționează pe orb</text>
<text x="60.0" y="612.0" font-size="13" font-weight="normal" fill="#000000" text-anchor="start">„Cadranul 4 nu se tranzacționează pe orb: aștepți trecerea în 2 sau 1,</text>
<text x="60.0" y="632.0" font-size="13" font-weight="normal" fill="#000000" text-anchor="start">ori un MP4-1 / MBT-10 long ca semn de schimbare.”</text>
<text x="60.0" y="662.0" font-size="13" font-weight="bold" fill="#000000" text-anchor="start">„Un setup de bottom cu RS fără îmbunătățire are șanse mai mici.”</text>
<text x="60.0" y="692.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="start">Notă: transcrierea descrierii cadranului 4 are o eroare (îl descrie ca pe</text>
<text x="60.0" y="712.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="start">cadranul 3, care e altceva). Definiția din tabloul de mai sus e cea</text>
<text x="60.0" y="732.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="start">corectă și e singura folosită în tot capitolul.</text>
</svg>

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

@@ -15,7 +15,7 @@ import sys
from pathlib import Path
sys.path.insert(0, "/workspace/atm-curs-dl")
from svg_candles import Candle, Chart, Level, Mark, MA, from_closes # noqa: E402
from svg_candles import Candle, Chart, Level, Arrow, Zone, MA, from_closes # noqa: E402
OUT = Path(__file__).resolve().parent / "selectia_exemplu.svg"
@@ -107,26 +107,33 @@ levels = [
Level(72.00, "TP 72.00", GREEN, label_at="left"),
]
marks = [
Mark(10, "gap down, open 79.20", "#333", "above", dy=-16),
Mark(12, "sell doji close 78.60", RED, "above", dy=-4),
Mark(13, "intrare short 78.10", GREEN, "below", dy=26),
Mark(10, "RVOL 200%", RED, "below", dy=12),
zones = [
Zone(10, 13, "ce l-a scos în față din cele 16 rezultate", RED, p_top=80.4),
]
arrows = [
Arrow(10, f"gap down: deschide la {cds[10].o:.2f}, mult sub\n"
f"închiderea de ieri — vânzare, nu pauză",
where="above", color=RED, dx=-160, dy=32),
Arrow(12, "sell doji close 78.60: vânzătorii și cumpărătorii la egalitate,\nîncă nu e semnal",
where="below", price=77.6, color="#333", dx=-120, dy=70),
Arrow(13, "aici ar intra strategia de intrare, nu selecția:\nînchidere sub low-ul doji-ului",
where="right", price=78.10, color=GREEN, dx=40, dy=110),
]
title = "HIG — daily (Sell Doji + Bear Reversal, RVOL 200%)"
caption = ("RVOL 200% si simbolul sunt reale (04_MODUL_3/01:196-199). Toate "
"nivelurile de preț (79.20 / 78.60 / 78.10 / 82.00 / 72.00) sunt "
"construite in sumarul 04_MODUL_3/01:293-296, nu date de curs; "
"structura barelor e construita, la scara.")
caption = ("Ale cursului: simbolul HIG, semnalul Sell Doji + Bear Reversal și RVOL-ul de 200 %, "
"cel mai mare din cele 16 rezultate ale scanerului. Nivelurile de preț "
"(79.20 / 78.60 / 78.10 / 82.00 / 72.00) și structura barelor sunt construite, la scară: "
"cursul nu dă cifre pentru HIG.")
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=16.0, gap=15, body_w=9, left=44, width=640, vol_h=70,
vol_label="volum",
title="", # titlul se injecteaza sus, ca sa nu se suprapuna
caption=caption, # cu eticheta nivelului "rezistenta 84.50" (stanga)
title=title,
caption=caption,
)
svg = ch.render()
@@ -137,14 +144,28 @@ px_reward = ys[72.00] - ys[78.10]
assert px_risc > 0 and px_reward > 0
assert abs(px_risc / px_reward - risc / reward) < 1e-9, "SL/TP la scara gresita"
# ---------------------------------------------------------------- titlu injectat
m_svg = re.search(r"<svg[^>]*>", svg)
assert m_svg, "tag <svg> lipsa"
svg = svg.replace(
m_svg.group(0),
m_svg.group(0) + f'\n <text x="24" y="16" fill="#333" style="font-weight:bold">{title}</text>',
1,
)
# ---------------------------------------------------------------- RVOL, pe panoul de volum
# RVOL e o afirmație despre volum, deci eticheta stă pe panoul de volum, nu în
# cel de preț: linia întreruptă e media seriei, iar bara 10 e de două ori cât ea.
m_vb = re.search(r'<line x1="24" y1="([\d.]+)" x2="[\d.]+" y2="[\d.]+" stroke="#888"/>', svg)
assert m_vb, "nu gasesc linia de baza a panoului de volum"
vol_base = float(m_vb.group(1))
vmax = max(VOLS)
y_media = vol_base - media_vol / vmax * 70.0 # vol_h = 70
y_bara = vol_base - VOLS[10] / vmax * 70.0
assert abs((vol_base - y_bara) / (vol_base - y_media) - 2.0) < 1e-9, \
"bara de RVOL nu e de doua ori media, desenata"
m_w = re.search(r'viewBox="0 0 (\d+) ', svg)
assert m_w
w_svg = int(m_w.group(1))
vol_note = (f'<line x1="24" y1="{y_media:.1f}" x2="{w_svg - 14}" y2="{y_media:.1f}" '
f'stroke="{GRAY}" stroke-width="1.2" stroke-dasharray="4 3"/>'
f'<text x="{w_svg - 16}" y="{y_media - 4:.1f}" fill="{GRAY}" text-anchor="end">'
f'media volumului pe serie</text>'
f'<text x="92" y="{y_bara - 5:.1f}" fill="{RED}" style="font-weight:bold">'
f'ziua gap-ului: de {VOLS[10] / media_vol:.0f} ori media (RVOL 200 %) — '
f'se vinde dublu față de o zi normală</text>')
svg = svg.replace(m_vb.group(0), m_vb.group(0) + vol_note, 1)
# ---------------------------------------------------------------- caption pe randuri
def _wrap(text: str, max_chars: int) -> list[str]:

View File

@@ -1,113 +1,124 @@
<svg viewBox="0 0 640 433" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif">
<text x="24" y="16" fill="#333" style="font-weight:bold">HIG — daily (Sell Doji + Bear Reversal, RVOL 200%)</text>
<line x1="24" y1="34.0" x2="626" y2="34.0" stroke="#777" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="612" y="28.0" fill="#777" text-anchor="end">rezistenta 84.50</text>
<line x1="24" y1="74.0" x2="626" y2="74.0" stroke="#c00" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="612" y="68.0" fill="#c00" text-anchor="end">SL 82.00</text>
<line x1="24" y1="136.4" x2="626" y2="136.4" stroke="#1a5fb4" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30" y="130.4" fill="#1a5fb4">intrare short 78.10</text>
<line x1="24" y1="234.0" x2="626" y2="234.0" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30" y="228.0" fill="#188a3e">TP 72.00</text>
<polyline points="329.0,107.0 344.0,110.5 359.0,114.3 374.0,119.0 389.0,124.7 404.0,129.8 419.0,136.1 434.0,143.4 449.0,151.7 464.0,160.8 479.0,170.7" fill="none" stroke="#b06000" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="485" y="165" fill="#b06000">SMA-20</text>
<line x1="44.0" y1="98.8" x2="44.0" y2="115.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="39.5" y="106.0" width="9" height="3.2" fill="#188a3e"/>
<line x1="59.0" y1="90.0" x2="59.0" y2="113.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="54.5" y="96.4" width="9" height="9.6" fill="#188a3e"/>
<line x1="74.0" y1="78.8" x2="74.0" y2="102.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="69.5" y="86.8" width="9" height="9.6" fill="#188a3e"/>
<line x1="89.0" y1="66.8" x2="89.0" y2="94.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="84.5" y="75.6" width="9" height="11.2" fill="#188a3e"/>
<line x1="104.0" y1="68.4" x2="104.0" y2="90.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="99.5" y="75.6" width="9" height="6.4" fill="#c00"/>
<line x1="119.0" y1="61.2" x2="119.0" y2="88.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="114.5" y="69.2" width="9" height="12.8" fill="#188a3e"/>
<line x1="134.0" y1="52.4" x2="134.0" y2="77.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="129.5" y="59.6" width="9" height="9.6" fill="#188a3e"/>
<line x1="149.0" y1="42.0" x2="149.0" y2="66.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="144.5" y="48.4" width="9" height="11.2" fill="#188a3e"/>
<line x1="164.0" y1="36.4" x2="164.0" y2="54.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="159.5" y="42.0" width="9" height="6.4" fill="#188a3e"/>
<line x1="179.0" y1="34.0" x2="179.0" y2="49.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="174.5" y="38.8" width="9" height="3.2" fill="#188a3e"/>
<line x1="194.0" y1="112.4" x2="194.0" y2="130.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="189.5" y="118.8" width="9" height="4.0" fill="#c00"/>
<line x1="209.0" y1="115.6" x2="209.0" y2="132.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="204.5" y="122.8" width="9" height="3.2" fill="#c00"/>
<line x1="224.0" y1="120.4" x2="224.0" y2="134.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="219.5" y="126.0" width="9" height="2.4" fill="#c00"/>
<line x1="239.0" y1="122.0" x2="239.0" y2="143.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="234.5" y="128.4" width="9" height="8.8" fill="#c00"/>
<line x1="254.0" y1="130.0" x2="254.0" y2="152.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="249.5" y="137.2" width="9" height="8.8" fill="#c00"/>
<line x1="269.0" y1="134.0" x2="269.0" y2="152.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="264.5" y="141.2" width="9" height="4.8" fill="#188a3e"/>
<line x1="284.0" y1="134.0" x2="284.0" y2="157.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="279.5" y="141.2" width="9" height="9.6" fill="#c00"/>
<line x1="299.0" y1="143.6" x2="299.0" y2="166.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="294.5" y="150.8" width="9" height="9.6" fill="#c00"/>
<line x1="314.0" y1="148.4" x2="314.0" y2="166.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="309.5" y="155.6" width="9" height="4.8" fill="#188a3e"/>
<line x1="329.0" y1="148.4" x2="329.0" y2="173.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="324.5" y="155.6" width="9" height="11.2" fill="#c00"/>
<line x1="344.0" y1="159.6" x2="344.0" y2="182.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="339.5" y="166.8" width="9" height="9.6" fill="#c00"/>
<line x1="359.0" y1="164.4" x2="359.0" y2="182.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="354.5" y="171.6" width="9" height="4.8" fill="#188a3e"/>
<line x1="374.0" y1="164.4" x2="374.0" y2="187.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="369.5" y="171.6" width="9" height="9.6" fill="#c00"/>
<line x1="389.0" y1="174.0" x2="389.0" y2="195.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="384.5" y="181.2" width="9" height="8.0" fill="#c00"/>
<line x1="404.0" y1="177.2" x2="404.0" y2="195.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="399.5" y="184.4" width="9" height="4.8" fill="#188a3e"/>
<line x1="419.0" y1="177.2" x2="419.0" y2="202.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="414.5" y="184.4" width="9" height="11.2" fill="#c00"/>
<line x1="434.0" y1="188.4" x2="434.0" y2="211.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="429.5" y="195.6" width="9" height="9.6" fill="#c00"/>
<line x1="449.0" y1="198.0" x2="449.0" y2="221.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="444.5" y="205.2" width="9" height="9.6" fill="#c00"/>
<line x1="464.0" y1="207.6" x2="464.0" y2="230.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="459.5" y="214.8" width="9" height="9.6" fill="#c00"/>
<line x1="479.0" y1="216.4" x2="479.0" y2="244.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="474.5" y="224.4" width="9" height="11.2" fill="#c00"/>
<line x1="24" y1="340.4" x2="626" y2="340.4" stroke="#888"/>
<rect x="39.5" y="309.6" width="9" height="30.8" fill="#188a3e" opacity="0.55"/>
<rect x="54.5" y="311.7" width="9" height="28.7" fill="#188a3e" opacity="0.55"/>
<rect x="69.5" y="308.9" width="9" height="31.5" fill="#188a3e" opacity="0.55"/>
<rect x="84.5" y="305.4" width="9" height="35.0" fill="#188a3e" opacity="0.55"/>
<rect x="99.5" y="310.3" width="9" height="30.1" fill="#c00" opacity="0.55"/>
<rect x="114.5" y="302.6" width="9" height="37.8" fill="#188a3e" opacity="0.55"/>
<rect x="129.5" y="304.0" width="9" height="36.4" fill="#188a3e" opacity="0.55"/>
<rect x="144.5" y="298.4" width="9" height="42.0" fill="#188a3e" opacity="0.55"/>
<rect x="159.5" y="306.8" width="9" height="33.6" fill="#188a3e" opacity="0.55"/>
<rect x="174.5" y="305.4" width="9" height="35.0" fill="#188a3e" opacity="0.55"/>
<rect x="189.5" y="270.4" width="9" height="70.0" fill="#c00" opacity="0.55"/>
<rect x="204.5" y="294.9" width="9" height="45.5" fill="#c00" opacity="0.55"/>
<rect x="219.5" y="305.4" width="9" height="35.0" fill="#c00" opacity="0.55"/>
<rect x="234.5" y="287.9" width="9" height="52.5" fill="#c00" opacity="0.55"/>
<rect x="249.5" y="304.7" width="9" height="35.7" fill="#c00" opacity="0.55"/>
<rect x="264.5" y="309.6" width="9" height="30.8" fill="#188a3e" opacity="0.55"/>
<rect x="279.5" y="302.6" width="9" height="37.8" fill="#c00" opacity="0.55"/>
<rect x="294.5" y="306.8" width="9" height="33.6" fill="#c00" opacity="0.55"/>
<rect x="309.5" y="311.0" width="9" height="29.4" fill="#188a3e" opacity="0.55"/>
<rect x="324.5" y="305.4" width="9" height="35.0" fill="#c00" opacity="0.55"/>
<rect x="339.5" y="308.9" width="9" height="31.5" fill="#c00" opacity="0.55"/>
<rect x="354.5" y="313.1" width="9" height="27.3" fill="#188a3e" opacity="0.55"/>
<rect x="369.5" y="306.1" width="9" height="34.3" fill="#c00" opacity="0.55"/>
<rect x="384.5" y="310.3" width="9" height="30.1" fill="#c00" opacity="0.55"/>
<rect x="399.5" y="314.5" width="9" height="25.9" fill="#188a3e" opacity="0.55"/>
<rect x="414.5" y="308.2" width="9" height="32.2" fill="#c00" opacity="0.55"/>
<rect x="429.5" y="311.7" width="9" height="28.7" fill="#c00" opacity="0.55"/>
<rect x="444.5" y="304.0" width="9" height="36.4" fill="#c00" opacity="0.55"/>
<rect x="459.5" y="313.8" width="9" height="26.6" fill="#c00" opacity="0.55"/>
<rect x="474.5" y="309.6" width="9" height="30.8" fill="#c00" opacity="0.55"/>
<text x="24" y="264.4" fill="#555">volum</text>
<text x="194.0" y="86.4" fill="#333" text-anchor="middle" style="font-weight:bold">gap down, open 79.20</text>
<text x="224.0" y="106.4" fill="#c00" text-anchor="middle" style="font-weight:bold">sell doji close 78.60</text>
<text x="239.0" y="189.6" fill="#188a3e" text-anchor="middle" style="font-weight:bold">intrare short 78.10</text>
<text x="194.0" y="162.8" fill="#c00" text-anchor="middle" style="font-weight:bold">RVOL 200%</text>
<text x="24" y="370" fill="#555">RVOL 200% si simbolul sunt reale (04_MODUL_3/01:196-199). Toate</text>
<text x="24" y="387" fill="#555">nivelurile de preț (79.20 / 78.60 / 78.10 / 82.00 / 72.00) sunt</text>
<text x="24" y="404" fill="#555">construite in sumarul 04_MODUL_3/01:293-296, nu date de curs;</text>
<text x="24" y="421" fill="#555">structura barelor e construita, la scara.</text>
<svg viewBox="0 0 737 510" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif">
<text x="24" y="48" fill="#333" style="font-weight:bold">HIG — daily (Sell Doji + Bear Reversal, RVOL 200%)</text>
<rect x="281.8" y="121.6" width="64.0" height="52.0" fill="#c00" fill-opacity="0.08" stroke="#c00" stroke-width="1"/>
<text x="281.8" y="116.6" fill="#c00" style="font-weight:bold">ce l-a scos în față din cele 16 rezultate</text>
<line x1="24" y1="56.0" x2="723" y2="56.0" stroke="#777" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="709" y="50.0" fill="#777" text-anchor="end">rezistenta 84.50</text>
<line x1="24" y1="96.0" x2="723" y2="96.0" stroke="#c00" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="709" y="90.0" fill="#c00" text-anchor="end">SL 82.00</text>
<line x1="24" y1="158.4" x2="723" y2="158.4" stroke="#1a5fb4" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30" y="152.4" fill="#1a5fb4">intrare short 78.10</text>
<line x1="24" y1="256.0" x2="723" y2="256.0" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30" y="250.0" fill="#188a3e">TP 72.00</text>
<polyline points="426.3,129.0 441.3,132.5 456.3,136.3 471.3,141.0 486.3,146.7 501.3,151.8 516.3,158.1 531.3,165.4 546.3,173.7 561.3,182.8 576.3,192.7" fill="none" stroke="#b06000" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="582" y="187" fill="#b06000">SMA-20</text>
<line x1="141.3" y1="120.8" x2="141.3" y2="137.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="136.8" y="128.0" width="9" height="3.2" fill="#188a3e"/>
<line x1="156.3" y1="112.0" x2="156.3" y2="135.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="151.8" y="118.4" width="9" height="9.6" fill="#188a3e"/>
<line x1="171.3" y1="100.8" x2="171.3" y2="124.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="166.8" y="108.8" width="9" height="9.6" fill="#188a3e"/>
<line x1="186.3" y1="88.8" x2="186.3" y2="116.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="181.8" y="97.6" width="9" height="11.2" fill="#188a3e"/>
<line x1="201.3" y1="90.4" x2="201.3" y2="112.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="196.8" y="97.6" width="9" height="6.4" fill="#c00"/>
<line x1="216.3" y1="83.2" x2="216.3" y2="110.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="211.8" y="91.2" width="9" height="12.8" fill="#188a3e"/>
<line x1="231.3" y1="74.4" x2="231.3" y2="99.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="226.8" y="81.6" width="9" height="9.6" fill="#188a3e"/>
<line x1="246.3" y1="64.0" x2="246.3" y2="88.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="241.8" y="70.4" width="9" height="11.2" fill="#188a3e"/>
<line x1="261.3" y1="58.4" x2="261.3" y2="76.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="256.8" y="64.0" width="9" height="6.4" fill="#188a3e"/>
<line x1="276.3" y1="56.0" x2="276.3" y2="71.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="271.8" y="60.8" width="9" height="3.2" fill="#188a3e"/>
<line x1="291.3" y1="134.4" x2="291.3" y2="152.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="286.8" y="140.8" width="9" height="4.0" fill="#c00"/>
<line x1="306.3" y1="137.6" x2="306.3" y2="154.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="301.8" y="144.8" width="9" height="3.2" fill="#c00"/>
<line x1="321.3" y1="142.4" x2="321.3" y2="156.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="316.8" y="148.0" width="9" height="2.4" fill="#c00"/>
<line x1="336.3" y1="144.0" x2="336.3" y2="165.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="331.8" y="150.4" width="9" height="8.8" fill="#c00"/>
<line x1="351.3" y1="152.0" x2="351.3" y2="174.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="346.8" y="159.2" width="9" height="8.8" fill="#c00"/>
<line x1="366.3" y1="156.0" x2="366.3" y2="174.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="361.8" y="163.2" width="9" height="4.8" fill="#188a3e"/>
<line x1="381.3" y1="156.0" x2="381.3" y2="179.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="376.8" y="163.2" width="9" height="9.6" fill="#c00"/>
<line x1="396.3" y1="165.6" x2="396.3" y2="188.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="391.8" y="172.8" width="9" height="9.6" fill="#c00"/>
<line x1="411.3" y1="170.4" x2="411.3" y2="188.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="406.8" y="177.6" width="9" height="4.8" fill="#188a3e"/>
<line x1="426.3" y1="170.4" x2="426.3" y2="195.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="421.8" y="177.6" width="9" height="11.2" fill="#c00"/>
<line x1="441.3" y1="181.6" x2="441.3" y2="204.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="436.8" y="188.8" width="9" height="9.6" fill="#c00"/>
<line x1="456.3" y1="186.4" x2="456.3" y2="204.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="451.8" y="193.6" width="9" height="4.8" fill="#188a3e"/>
<line x1="471.3" y1="186.4" x2="471.3" y2="209.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="466.8" y="193.6" width="9" height="9.6" fill="#c00"/>
<line x1="486.3" y1="196.0" x2="486.3" y2="217.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="481.8" y="203.2" width="9" height="8.0" fill="#c00"/>
<line x1="501.3" y1="199.2" x2="501.3" y2="217.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="496.8" y="206.4" width="9" height="4.8" fill="#188a3e"/>
<line x1="516.3" y1="199.2" x2="516.3" y2="224.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="511.8" y="206.4" width="9" height="11.2" fill="#c00"/>
<line x1="531.3" y1="210.4" x2="531.3" y2="233.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="526.8" y="217.6" width="9" height="9.6" fill="#c00"/>
<line x1="546.3" y1="220.0" x2="546.3" y2="243.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="541.8" y="227.2" width="9" height="9.6" fill="#c00"/>
<line x1="561.3" y1="229.6" x2="561.3" y2="252.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="556.8" y="236.8" width="9" height="9.6" fill="#c00"/>
<line x1="576.3" y1="238.4" x2="576.3" y2="266.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="571.8" y="246.4" width="9" height="11.2" fill="#c00"/>
<line x1="24" y1="399.8" x2="723" y2="399.8" stroke="#888"/><line x1="24" y1="364.8" x2="723" y2="364.8" stroke="#777" stroke-width="1.2" stroke-dasharray="4 3"/><text x="721" y="360.8" fill="#777" text-anchor="end">media volumului pe serie</text><text x="92" y="324.8" fill="#c00" style="font-weight:bold">ziua gap-ului: de 2 ori media (RVOL 200 %) — se vinde dublu față de o zi normală</text>
<rect x="136.8" y="369.0" width="9" height="30.8" fill="#188a3e" opacity="0.55"/>
<rect x="151.8" y="371.1" width="9" height="28.7" fill="#188a3e" opacity="0.55"/>
<rect x="166.8" y="368.3" width="9" height="31.5" fill="#188a3e" opacity="0.55"/>
<rect x="181.8" y="364.8" width="9" height="35.0" fill="#188a3e" opacity="0.55"/>
<rect x="196.8" y="369.7" width="9" height="30.1" fill="#c00" opacity="0.55"/>
<rect x="211.8" y="362.0" width="9" height="37.8" fill="#188a3e" opacity="0.55"/>
<rect x="226.8" y="363.4" width="9" height="36.4" fill="#188a3e" opacity="0.55"/>
<rect x="241.8" y="357.8" width="9" height="42.0" fill="#188a3e" opacity="0.55"/>
<rect x="256.8" y="366.2" width="9" height="33.6" fill="#188a3e" opacity="0.55"/>
<rect x="271.8" y="364.8" width="9" height="35.0" fill="#188a3e" opacity="0.55"/>
<rect x="286.8" y="329.8" width="9" height="70.0" fill="#c00" opacity="0.55"/>
<rect x="301.8" y="354.3" width="9" height="45.5" fill="#c00" opacity="0.55"/>
<rect x="316.8" y="364.8" width="9" height="35.0" fill="#c00" opacity="0.55"/>
<rect x="331.8" y="347.3" width="9" height="52.5" fill="#c00" opacity="0.55"/>
<rect x="346.8" y="364.1" width="9" height="35.7" fill="#c00" opacity="0.55"/>
<rect x="361.8" y="369.0" width="9" height="30.8" fill="#188a3e" opacity="0.55"/>
<rect x="376.8" y="362.0" width="9" height="37.8" fill="#c00" opacity="0.55"/>
<rect x="391.8" y="366.2" width="9" height="33.6" fill="#c00" opacity="0.55"/>
<rect x="406.8" y="370.4" width="9" height="29.4" fill="#188a3e" opacity="0.55"/>
<rect x="421.8" y="364.8" width="9" height="35.0" fill="#c00" opacity="0.55"/>
<rect x="436.8" y="368.3" width="9" height="31.5" fill="#c00" opacity="0.55"/>
<rect x="451.8" y="372.5" width="9" height="27.3" fill="#188a3e" opacity="0.55"/>
<rect x="466.8" y="365.5" width="9" height="34.3" fill="#c00" opacity="0.55"/>
<rect x="481.8" y="369.7" width="9" height="30.1" fill="#c00" opacity="0.55"/>
<rect x="496.8" y="373.9" width="9" height="25.9" fill="#188a3e" opacity="0.55"/>
<rect x="511.8" y="367.6" width="9" height="32.2" fill="#c00" opacity="0.55"/>
<rect x="526.8" y="371.1" width="9" height="28.7" fill="#c00" opacity="0.55"/>
<rect x="541.8" y="363.4" width="9" height="36.4" fill="#c00" opacity="0.55"/>
<rect x="556.8" y="373.2" width="9" height="26.6" fill="#c00" opacity="0.55"/>
<rect x="571.8" y="369.0" width="9" height="30.8" fill="#c00" opacity="0.55"/>
<text x="24" y="323.8" fill="#555">volum</text>
<line x1="131.3" y1="88.0" x2="283.6" y2="128.4" stroke="#c00" stroke-width="1.8"/>
<polygon points="291.3,130.4 282.5,132.2 284.6,124.5" fill="#c00"/>
<text x="131.3" y="69.0" fill="#c00" text-anchor="middle" style="font-weight:bold">gap down: deschide la 79.20, mult sub</text>
<text x="131.3" y="83.0" fill="#c00" text-anchor="middle" style="font-weight:bold">închiderea de ieri — vânzare, nu pauză</text>
<line x1="201.3" y1="266.8" x2="315.1" y2="175.4" stroke="#333" stroke-width="1.8"/>
<polygon points="321.3,170.4 317.6,178.5 312.6,172.3" fill="#333"/>
<text x="201.3" y="280.8" fill="#333" text-anchor="middle" style="font-weight:bold">sell doji close 78.60: vânzătorii și cumpărătorii la egalitate,</text>
<text x="201.3" y="294.8" fill="#333" text-anchor="middle" style="font-weight:bold">încă nu e semnal</text>
<line x1="414.8" y1="268.4" x2="349.1" y2="165.1" stroke="#188a3e" stroke-width="1.8"/>
<polygon points="344.8,158.4 352.5,163.0 345.7,167.3" fill="#188a3e"/>
<text x="418.8" y="265.4" fill="#188a3e" text-anchor="start" style="font-weight:bold">aici ar intra strategia de intrare, nu selecția:</text>
<text x="418.8" y="279.4" fill="#188a3e" text-anchor="start" style="font-weight:bold">închidere sub low-ul doji-ului</text>
<text x="24" y="430" fill="#555">Ale cursului: simbolul HIG, semnalul Sell Doji + Bear Reversal și</text>
<text x="24" y="447" fill="#555">RVOL-ul de 200 %, cel mai mare din cele 16 rezultate ale scanerului.</text>
<text x="24" y="464" fill="#555">Nivelurile de preț (79.20 / 78.60 / 78.10 / 82.00 / 72.00) și</text>
<text x="24" y="481" fill="#555">structura barelor sunt construite, la scară: cursul nu dă cifre pentru</text>
<text x="24" y="498" fill="#555">HIG.</text>
</svg>

Before

Width:  |  Height:  |  Size: 9.1 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -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}"

View File

@@ -1,52 +1,43 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 700 1024" width="700" height="1024" font-family="system-ui, sans-serif" role="img" aria-label="Palnia de selectie: 8 trepte de filtrare de la scanner la lista scurta, fiecare cu pragul si sursa ei, plus note laterale despre suporturi si Radarscreen">
<rect x="0" y="0" width="700" height="1024" fill="#ffffff"/>
<path d="M 45.0 100.0 L 655.0 100.0 L 643.0 176.0 L 57.0 176.0 Z" fill="#eef3fb" stroke="#1a5fb4" stroke-width="1.2"/>
<path d="M 57.0 176.0 L 643.0 176.0 L 631.0 252.0 L 69.0 252.0 Z" fill="#e4edf9" stroke="#1a5fb4" stroke-width="1.2"/>
<path d="M 69.0 252.0 L 631.0 252.0 L 619.0 328.0 L 81.0 328.0 Z" fill="#eef3fb" stroke="#1a5fb4" stroke-width="1.2"/>
<path d="M 81.0 328.0 L 619.0 328.0 L 607.0 404.0 L 93.0 404.0 Z" fill="#e4edf9" stroke="#1a5fb4" stroke-width="1.2"/>
<path d="M 93.0 404.0 L 607.0 404.0 L 595.0 480.0 L 105.0 480.0 Z" fill="#eef3fb" stroke="#1a5fb4" stroke-width="1.2"/>
<path d="M 105.0 480.0 L 595.0 480.0 L 583.0 556.0 L 117.0 556.0 Z" fill="#e4edf9" stroke="#1a5fb4" stroke-width="1.2"/>
<path d="M 117.0 556.0 L 583.0 556.0 L 571.0 632.0 L 129.0 632.0 Z" fill="#eef3fb" stroke="#1a5fb4" stroke-width="1.2"/>
<path d="M 129.0 632.0 L 571.0 632.0 L 559.0 708.0 L 141.0 708.0 Z" fill="#e4edf9" stroke="#1a5fb4" stroke-width="1.2"/>
<rect x="145.0" y="722.0" width="410.0" height="62.0" fill="#eef7f0" stroke="#188a3e" stroke-width="1.8" rx="8"/>
<rect x="40.0" y="802.0" width="620.0" height="200.0" fill="#fdf0e0" stroke="#b06000" stroke-width="1.6" rx="8"/>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 700 840" width="700" height="840" font-family="system-ui, sans-serif" role="img" aria-label="Palnia de selectie: 6 trepte de filtrare de la scanner la lista scurta, fiecare cu pragul ei si cu motivul pentru care exista pragul, plus rafinarile de la nivelul 3">
<rect x="0" y="0" width="700" height="840" fill="#ffffff"/>
<path d="M 45.0 100.0 L 655.0 100.0 L 640.0 176.0 L 60.0 176.0 Z" fill="#eef3fb" stroke="#1a5fb4" stroke-width="1.2"/>
<path d="M 60.0 176.0 L 640.0 176.0 L 625.0 252.0 L 75.0 252.0 Z" fill="#e4edf9" stroke="#1a5fb4" stroke-width="1.2"/>
<path d="M 75.0 252.0 L 625.0 252.0 L 610.0 328.0 L 90.0 328.0 Z" fill="#eef3fb" stroke="#1a5fb4" stroke-width="1.2"/>
<path d="M 90.0 328.0 L 610.0 328.0 L 595.0 404.0 L 105.0 404.0 Z" fill="#e4edf9" stroke="#1a5fb4" stroke-width="1.2"/>
<path d="M 105.0 404.0 L 595.0 404.0 L 580.0 480.0 L 120.0 480.0 Z" fill="#eef3fb" stroke="#1a5fb4" stroke-width="1.2"/>
<path d="M 120.0 480.0 L 580.0 480.0 L 565.0 556.0 L 135.0 556.0 Z" fill="#e4edf9" stroke="#1a5fb4" stroke-width="1.2"/>
<rect x="145.0" y="566.0" width="410.0" height="62.0" fill="#eef7f0" stroke="#188a3e" stroke-width="1.8" rx="8"/>
<rect x="40.0" y="648.0" width="620.0" height="176.0" fill="#fdf0e0" stroke="#b06000" stroke-width="1.6" rx="8"/>
<text x="350.0" y="34.0" font-size="20" font-weight="bold" fill="#000000" text-anchor="middle">Fluxul de selecție — de la scanner la lista scurtă</text>
<text x="350.0" y="57.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="middle">selecția se face înainte de semnalul tehnic; ea nu spune CÂND intri</text>
<text x="350.0" y="79.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="middle">Palnia se îngustează de sus în jos: 8 filtre, apoi lista scurtă.</text>
<text x="350.0" y="125.0" font-size="14.5" font-weight="bold" fill="#000000" text-anchor="middle">1. Scanner — multe semnale</text>
<text x="350.0" y="145.0" font-size="13" font-weight="normal" fill="#000000" text-anchor="middle">zeci sau sute de semnale</text>
<text x="350.0" y="159.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="middle">08_ANALIZA_ZILNICA/11_selectia_simbolului.md:631-637</text>
<text x="350.0" y="201.0" font-size="14.5" font-weight="bold" fill="#000000" text-anchor="middle">2. Filtre de bază</text>
<text x="350.0" y="221.0" font-size="13" font-weight="normal" fill="#000000" text-anchor="middle">close &gt; 30-40 $; volum mediu 3 luni &gt; 1M (min 500k)</text>
<text x="350.0" y="235.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="middle">09_QA/28_2025-05-27.md:372-380;</text>
<text x="350.0" y="249.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="middle">03_MODUL_2/11_construire_scanere_sf_byd_sld.md:70-73</text>
<text x="350.0" y="277.0" font-size="14.5" font-weight="bold" fill="#000000" text-anchor="middle">3. Fundamental</text>
<text x="350.0" y="297.0" font-size="13" font-weight="normal" fill="#000000" text-anchor="middle">ATM score peste 7-8; 12-13 = spuma; F-score 6-9</text>
<text x="350.0" y="311.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="middle">08_ANALIZA_ZILNICA/11_selectia_simbolului.md:199-221</text>
<text x="350.0" y="353.0" font-size="14.5" font-weight="bold" fill="#000000" text-anchor="middle">4. Sectorul care domină</text>
<text x="350.0" y="373.0" font-size="13" font-weight="normal" fill="#000000" text-anchor="middle">cele 11 sectoare S&amp;P, sortate cadran 1 + valoarea RS</text>
<text x="350.0" y="387.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="middle">08_ANALIZA_ZILNICA/11_selectia_simbolului.md:639-717</text>
<text x="350.0" y="429.0" font-size="14.5" font-weight="bold" fill="#000000" text-anchor="middle">5. Doar suport / pivot, după downtrend</text>
<text x="350.0" y="449.0" font-size="13" font-weight="normal" fill="#000000" text-anchor="middle">suport monthly, quarterly, anual sau pivot; proximitate ≤ 3%</text>
<text x="350.0" y="463.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="middle">08_ANALIZA_ZILNICA/11_selectia_simbolului.md:719-728, 787-803</text>
<text x="350.0" y="505.0" font-size="14.5" font-weight="bold" fill="#000000" text-anchor="middle">6. Relative strength: cadran 1-2</text>
<text x="350.0" y="525.0" font-size="13" font-weight="normal" fill="#000000" text-anchor="middle">doar cadranele 1 și 2, RS pozitiv</text>
<text x="350.0" y="539.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="middle">08_ANALIZA_ZILNICA/11_selectia_simbolului.md:730-739</text>
<text x="350.0" y="581.0" font-size="14.5" font-weight="bold" fill="#000000" text-anchor="middle">7. Relative volume peste 100%</text>
<text x="350.0" y="601.0" font-size="13" font-weight="normal" fill="#000000" text-anchor="middle">candela de volum / media ultimelor 10 candele</text>
<text x="350.0" y="615.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="middle">08_ANALIZA_ZILNICA/11_selectia_simbolului.md:741-747</text>
<text x="350.0" y="657.0" font-size="14.5" font-weight="bold" fill="#000000" text-anchor="middle">8. Stele (Trinity)</text>
<text x="350.0" y="677.0" font-size="13" font-weight="normal" fill="#000000" text-anchor="middle">RS + Power + volum, cadran 1</text>
<text x="350.0" y="691.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="middle">08_ANALIZA_ZILNICA/11_selectia_simbolului.md:776-785</text>
<text x="350.0" y="746.0" font-size="16" font-weight="bold" fill="#188a3e" text-anchor="middle">Listă scurtă</text>
<text x="350.0" y="765.0" font-size="13" font-weight="normal" fill="#000000" text-anchor="middle">câteva idei pe care le urmărești</text>
<text x="350.0" y="779.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="middle">08_ANALIZA_ZILNICA/11_selectia_simbolului.md:42-50</text>
<text x="60.0" y="830.0" font-size="15" font-weight="bold" fill="#b06000" text-anchor="start">Note laterale</text>
<text x="60.0" y="858.0" font-size="13" font-weight="normal" fill="#000000" text-anchor="start">După corecție masivă: doji / hammer la suporturi mari</text>
<text x="60.0" y="877.0" font-size="13" font-weight="normal" fill="#000000" text-anchor="start">(monthly, quarterly, anual); scanner de apropiere de suport</text>
<text x="60.0" y="896.0" font-size="13" font-weight="normal" fill="#000000" text-anchor="start">până la 3% (4% e cam departe).</text>
<text x="60.0" y="917.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="start">08_ANALIZA_ZILNICA/11_selectia_simbolului.md:787-803</text>
<text x="60.0" y="952.0" font-size="13" font-weight="normal" fill="#000000" text-anchor="start">Radarscreen (max ~300 simboluri): repetă fluxul — sectoare top 10,</text>
<text x="60.0" y="971.0" font-size="13" font-weight="normal" fill="#000000" text-anchor="start">RS, apoi 3 stele.</text>
<text x="60.0" y="992.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="start">08_ANALIZA_ZILNICA/11_selectia_simbolului.md:815-825</text>
<text x="350.0" y="79.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="middle">Palnia se îngustează de sus în jos: 6 filtre, apoi lista scurtă.</text>
<text x="350.0" y="125.0" font-size="14.5" font-weight="bold" fill="#000000" text-anchor="middle">1. Universul și lichiditatea</text>
<text x="350.0" y="145.0" font-size="13" font-weight="normal" fill="#000000" text-anchor="middle">close peste 30-40 $; volum mediu ≥ 500.000 de acțiuni, ideal peste 1 milion</text>
<text x="350.0" y="160.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="middle">de ce: pe un simbol subțire, ordinul tău mută singur prețul</text>
<text x="350.0" y="201.0" font-size="14.5" font-weight="bold" fill="#000000" text-anchor="middle">2. Scorul fundamental</text>
<text x="350.0" y="221.0" font-size="13" font-weight="normal" fill="#000000" text-anchor="middle">ATM score peste 7-8 (12-13 = spuma); F-score 6-9</text>
<text x="350.0" y="236.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="middle">de ce: instituționalii cumpără bilanț, nu desen</text>
<text x="350.0" y="277.0" font-size="14.5" font-weight="bold" fill="#000000" text-anchor="middle">3. Sectorul care domină</text>
<text x="350.0" y="297.0" font-size="13" font-weight="normal" fill="#000000" text-anchor="middle">numeri din ce sector vin cele mai multe semnale</text>
<text x="350.0" y="312.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="middle">de ce: multe semnale în același sector = bani care intră acolo</text>
<text x="350.0" y="353.0" font-size="14.5" font-weight="bold" fill="#000000" text-anchor="middle">4. Suport sau pivot, după downtrend</text>
<text x="350.0" y="373.0" font-size="13" font-weight="normal" fill="#000000" text-anchor="middle">proximitate până la 3 % (4 % „e cam departe”)</text>
<text x="350.0" y="388.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="middle">de ce: la un nivel, cumpărătorii au motiv să apară</text>
<text x="350.0" y="429.0" font-size="14.5" font-weight="bold" fill="#000000" text-anchor="middle">5. Relative strength: cadranul 1 sau 2</text>
<text x="350.0" y="449.0" font-size="13" font-weight="normal" fill="#000000" text-anchor="middle">simbolul se mișcă mai bine decât indicele de referință</text>
<text x="350.0" y="464.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="middle">de ce: cumperi ce urcă mai tare decât piața</text>
<text x="350.0" y="505.0" font-size="14.5" font-weight="bold" fill="#000000" text-anchor="middle">6. Relative volume peste 100 %</text>
<text x="350.0" y="525.0" font-size="13" font-weight="normal" fill="#000000" text-anchor="middle">candela de volum / media ultimelor 10 candele</text>
<text x="350.0" y="540.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="middle">de ce: confirmă că azi chiar participă lumea, nu doar tu</text>
<text x="350.0" y="590.0" font-size="16" font-weight="bold" fill="#188a3e" text-anchor="middle">Listă scurtă</text>
<text x="350.0" y="609.0" font-size="13" font-weight="normal" fill="#000000" text-anchor="middle">câteva idei pe care le urmărești</text>
<text x="350.0" y="623.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="middle">nicio poziție deschisă: trigger-ul e al altui capitol</text>
<text x="60.0" y="674.0" font-size="15" font-weight="bold" fill="#b06000" text-anchor="start">Ce nu intră în cei șase pași (rafinări, nivelul 3)</text>
<text x="60.0" y="698.0" font-size="13" font-weight="normal" fill="#000000" text-anchor="start">Sortarea finală după 3 stele (Trinity: relative strength, Power și</text>
<text x="60.0" y="716.0" font-size="13" font-weight="normal" fill="#000000" text-anchor="start">volum, toate în cadranul 1) și departajarea între doi candidați</text>
<text x="60.0" y="734.0" font-size="13" font-weight="normal" fill="#000000" text-anchor="start">rămași: trend, apoi volum, apoi fundamental.</text>
<text x="60.0" y="752.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="start">un scor de 7 nu e motiv să-l iei, dacă ai altul mai bun</text>
<text x="60.0" y="778.0" font-size="13" font-weight="normal" fill="#000000" text-anchor="start">Radarscreen (maximum ~300 de simboluri: cele 11 sectoare × top 10):</text>
<text x="60.0" y="796.0" font-size="13" font-weight="normal" fill="#000000" text-anchor="start">același flux, rulat pe o listă fixă, nu pe tot scanerul.</text>
<text x="60.0" y="814.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="start">după o corecție mare, cauți doji sau hammer la suporturile mari</text>
</svg>

Before

Width:  |  Height:  |  Size: 7.1 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

@@ -0,0 +1,171 @@
"""Pasul 4 — cât de aproape de suport e prețul (TIP: PRET).
Pentru `summaries/17_STRATEGII/04_selectia.md`, pasul 4. Un singur grafic
daily, cu suportul monthly și cu banda de 3 % de deasupra lui, desenată ca
dreptunghi: înăuntru simbolul e „la nivel", în afară e „în aer". Două momente
din aceeași serie, unul în fiecare parte, ca să se vadă diferența pe care
ochiul n-o prinde.
Pragul de 3 % (cu 4 % „cam departe") e al cursului. Seria e construită, la
scară; toate procentele din etichete se calculează din ea, cu assert.
Atenție la diferența față de capitolul Buy Doji: acolo pragul de 1-2 % se
măsoară pentru low-ul doji-ului. Aici măsori închiderea simbolului față de
suport, ca filtru de selecție — două măsurători diferite, praguri diferite.
Rulează:
python3 gen/strategii/selectia_proximitate.py
"""
import re
import sys
from pathlib import Path
sys.path.insert(0, "/workspace/atm-curs-dl")
from svg_candles import Chart, Level, Arrow, Zone, MA, from_closes # noqa: E402
OUT = Path(__file__).resolve().parent / "selectia_proximitate.svg"
GRAY, RED, GREEN, BLUE, ORANGE = "#777", "#c00", "#188a3e", "#1a5fb4", "#b06000"
SUPORT = 48.00
PRAG = 0.03 # 3 % — pragul cursului
BANDA_SUS = SUPORT * (1 + PRAG) # 49.44
DEPARTE, APROAPE = 10, 30 # barele comentate
CLOSES = [
56.00, 55.60, 55.10, 54.70, 54.20, # 0-4
53.80, 53.30, 52.90, 52.40, 52.00, # 5-9
51.60, 51.20, 50.90, 50.50, 50.20, # 10-14
49.90, 50.30, 50.00, 49.70, 49.40, # 15-19
49.10, 49.50, 49.20, 48.90, 49.20, # 20-24
48.90, 48.70, 49.00, 48.70, 48.50, # 25-29
48.80, 49.10, # 30-31
]
assert len(CLOSES) == 32, len(CLOSES)
WICKS = [(0.22, 0.24)] * 32
WICKS[0] = (0.30, 0.30)
WICKS[29] = (0.20, 0.50) # low exact pe suport: 48.50 - 0.50 = 48.00
assert len(WICKS) == 32
VOLS = [46, 44, 48, 45, 43, 47, 44, 42, 45, 41,
40, 42, 39, 41, 38, 44, 36, 38, 35, 37,
34, 40, 33, 36, 32, 35, 31, 34, 33, 48,
44, 46]
assert len(VOLS) == 32
cds = from_closes(CLOSES, wicks=WICKS, vols=VOLS, start=56.30)
# ---------------------------------------------------------------- assert-uri de conținut
for a, b in zip(cds, cds[1:]):
assert abs(a.c - b.o) < 1e-9, "serie cu gol artificial între bare"
assert abs(min(c.l for c in cds) - SUPORT) < 1e-9, "suportul nu e atins de niciun low"
pct_departe = (cds[DEPARTE].c - SUPORT) / SUPORT * 100
pct_aproape = (cds[APROAPE].c - SUPORT) / SUPORT * 100
assert pct_departe > PRAG * 100, "bara «departe» trebuie să fie peste prag"
assert pct_aproape < PRAG * 100, "bara «aproape» trebuie să fie sub prag"
assert abs(pct_departe - 7.50) < 0.01, pct_departe
assert abs(pct_aproape - 1.67) < 0.01, pct_aproape
# banda acoperă exact ce trebuie: bara «aproape» înăuntru, bara «departe» afară
assert SUPORT <= cds[APROAPE].c <= BANDA_SUS, "bara «aproape» nu e în bandă"
assert cds[DEPARTE].c > BANDA_SUS, "bara «departe» nu e în afara benzii"
# numărul din textul zonei == numărul de bare pe care le acoperă
in_banda = [i for i, c in enumerate(cds) if SUPORT <= c.c <= BANDA_SUS]
assert in_banda and in_banda[0] == 19, in_banda[:3]
levels = [
Level(SUPORT, f"suport monthly {SUPORT:.2f}", BLUE, label_at="left"),
Level(BANDA_SUS, f"suport + 3 % = {BANDA_SUS:.2f}", BLUE, dash="5 3"),
]
zones = [
# eticheta benzii o pun manual, după randare: banda ține toată lățimea, iar
# eticheta automată ar urca deasupra primei candele, peste titlu
Zone(0, 31, "", BLUE, p_top=BANDA_SUS, p_bot=SUPORT),
]
arrows = [
Arrow(DEPARTE, f"close {cds[DEPARTE].c:.2f} = {pct_departe:.2f} % peste suport\n"
f"prea departe: până acolo prețul mai are de căzut,\n"
f"deci nivelul nu-l poate opri acum",
where="above", color=RED, dx=-60, dy=-4),
Arrow(APROAPE, f"close {cds[APROAPE].c:.2f} = {pct_aproape:.2f} % peste suport\n"
f"la nivel: dacă mai scade puțin, dă de ordinele\n"
f"de cumpărare care au mai întors prețul de acolo",
where="below", color=GREEN, dx=-320, dy=42),
]
caption = ("Pragul de 3 % (cu 4 % „cam departe”) e al cursului; seria și prețurile sunt construite, "
"la scară, iar procentele sunt calculate din serie. În capitolul Buy Doji, pragul de "
"1-2 % măsoară altceva: low-ul doji-ului față de nivel, nu închiderea simbolului.")
ch = Chart(
candles=cds, levels=levels, zones=zones, arrows=arrows,
mas=[MA(20, ORANGE, dash="4 3", text="SMA-20")],
scale=26.0, gap=15, body_w=9, left=44, width=660, vol_h=60,
vol_label="volum",
title="Cât de aproape de suport e prețul — daily, exemplu construit",
caption=caption,
)
svg = ch.render()
# eticheta benzii, pusă în interiorul ei, în stânga
m_band = re.findall(r'<line x1="24" y1="([\d.]+)"', svg)
y_banda_sus, y_suport = float(m_band[1]), float(m_band[0])
assert y_suport > y_banda_sus, "banda e desenată invers"
svg = svg.replace("</svg>",
f'<text x="230" y="{(y_banda_sus + y_suport) / 2 + 4:.1f}" fill="{BLUE}" '
f'style="font-weight:bold">banda de 3 %: înăuntru simbolul e „la nivel”</text>'
"</svg>")
# „SMA-20" cade peste eticheta nivelului de bandă: o ridic pe rândul liber
svg, n = re.subn(r'(<text x="\d+" y=")([\d.]+)(" fill="#b06000">SMA-20</text>)',
lambda mm: f'{mm.group(1)}{float(mm.group(2)) - 16:.1f}{mm.group(3)}', svg)
assert n == 1, f"eticheta SMA-20: {n} potriviri"
# liniile nu au voie să cadă pe marginea cadrului
m_sup = re.findall(r'<line x1="24" y1="([\d.]+)"', svg)
assert m_sup, "nu găsesc liniile de nivel"
y_sup = float(m_sup[0])
m_vb = re.search(r'viewBox="0 0 (\d+) (\d+)"', svg)
assert m_vb
h_svg = int(m_vb.group(2))
assert y_sup > 0.06 * h_svg, "linia suportului e lipită de marginea de sus"
# nicio etichetă nu numește un preț care nu e desenat
desenate = {f"{SUPORT:.2f}", f"{BANDA_SUS:.2f}", f"{cds[DEPARTE].c:.2f}", f"{cds[APROAPE].c:.2f}",
f"{pct_departe:.2f}", f"{pct_aproape:.2f}"}
for t in re.findall(r"<text[^>]*>([^<]*)</text>", svg):
for nr in re.findall(r"\d+\.\d\d", t):
assert nr in desenate, f"eticheta numește {nr}, care nu e desenat: {t!r}"
def _wrap(text: str, max_chars: int) -> list[str]:
lines, cur = [], ""
for w in text.split():
if cur and len(cur) + 1 + len(w) > max_chars:
lines.append(cur)
cur = w
else:
cur = f"{cur} {w}".strip()
if cur:
lines.append(cur)
return lines
cap_lines = _wrap(caption, 96)
m = re.search(r'<text x="24" y="(\d+)" fill="#555">' + re.escape(caption) + r"</text>", svg)
assert m, "caption-ul nu a fost găsit în SVG"
y0 = int(m.group(1))
wrapped = "\n ".join(f'<text x="24" y="{y0 + 17 * i}" fill="#555">{ln}</text>'
for i, ln in enumerate(cap_lines))
svg = svg[:m.start()] + wrapped + svg[m.end():]
svg = svg.replace(m_vb.group(0),
f'viewBox="0 0 {m_vb.group(1)} {h_svg + 17 * (len(cap_lines) - 1)}"', 1)
assert "<svg" in svg and "\n\n" not in svg, "linie goală în SVG"
OUT.write_text(svg)
print(f"scris {OUT.name}: 32 candele, suport {SUPORT:.2f}, banda până la {BANDA_SUS:.2f}, "
f"bara {DEPARTE} la {pct_departe:.2f} % (afară), bara {APROAPE} la {pct_aproape:.2f} % (înăuntru)")

View File

@@ -0,0 +1,121 @@
<svg viewBox="0 0 683 594" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif">
<text x="24" y="84" fill="#333" style="font-weight:bold">Cât de aproape de suport e prețul — daily, exemplu construit</text>
<rect x="58.4" y="278.2" width="484.0" height="37.4" fill="#1a5fb4" fill-opacity="0.08" stroke="#1a5fb4" stroke-width="1"/>
<line x1="24" y1="315.6" x2="669" y2="315.6" stroke="#1a5fb4" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30" y="309.6" fill="#1a5fb4">suport monthly 48.00</text>
<line x1="24" y1="278.2" x2="669" y2="278.2" stroke="#1a5fb4" stroke-width="1.5" stroke-dasharray="5 3"/>
<text x="655" y="272.2" fill="#1a5fb4" text-anchor="end">suport + 3 % = 49.44</text>
<polyline points="352.9,206.8 367.9,215.8 382.9,223.7 397.9,231.4 412.9,238.9 427.9,245.4 442.9,251.8 457.9,257.7 472.9,262.8 487.9,267.6 502.9,272.2 517.9,275.8 532.9,278.5" fill="none" stroke="#b06000" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="539" y="256.0" fill="#b06000">SMA-20</text>
<line x1="67.9" y1="92.0" x2="67.9" y2="115.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="63.4" y="99.8" width="9" height="7.8" fill="#c00"/>
<line x1="82.9" y1="101.9" x2="82.9" y2="124.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="78.4" y="107.6" width="9" height="10.4" fill="#c00"/>
<line x1="97.9" y1="112.3" x2="97.9" y2="137.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="93.4" y="118.0" width="9" height="13.0" fill="#c00"/>
<line x1="112.9" y1="125.3" x2="112.9" y2="147.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="108.4" y="131.0" width="9" height="10.4" fill="#c00"/>
<line x1="127.9" y1="135.7" x2="127.9" y2="160.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="123.4" y="141.4" width="9" height="13.0" fill="#c00"/>
<line x1="142.9" y1="148.7" x2="142.9" y2="171.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="138.4" y="154.4" width="9" height="10.4" fill="#c00"/>
<line x1="157.9" y1="159.1" x2="157.9" y2="184.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="153.4" y="164.8" width="9" height="13.0" fill="#c00"/>
<line x1="172.9" y1="172.1" x2="172.9" y2="194.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="168.4" y="177.8" width="9" height="10.4" fill="#c00"/>
<line x1="187.9" y1="182.5" x2="187.9" y2="207.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="183.4" y="188.2" width="9" height="13.0" fill="#c00"/>
<line x1="202.9" y1="195.5" x2="202.9" y2="217.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="198.4" y="201.2" width="9" height="10.4" fill="#c00"/>
<line x1="217.9" y1="205.9" x2="217.9" y2="228.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="213.4" y="211.6" width="9" height="10.4" fill="#c00"/>
<line x1="232.9" y1="216.3" x2="232.9" y2="238.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="228.4" y="222.0" width="9" height="10.4" fill="#c00"/>
<line x1="247.9" y1="226.7" x2="247.9" y2="246.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="243.4" y="232.4" width="9" height="7.8" fill="#c00"/>
<line x1="262.9" y1="234.5" x2="262.9" y2="256.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="258.4" y="240.2" width="9" height="10.4" fill="#c00"/>
<line x1="277.9" y1="244.9" x2="277.9" y2="264.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="273.4" y="250.6" width="9" height="7.8" fill="#c00"/>
<line x1="292.9" y1="252.7" x2="292.9" y2="272.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="288.4" y="258.4" width="9" height="7.8" fill="#c00"/>
<line x1="307.9" y1="250.1" x2="307.9" y2="272.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="303.4" y="255.8" width="9" height="10.4" fill="#188a3e"/>
<line x1="322.9" y1="250.1" x2="322.9" y2="269.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="318.4" y="255.8" width="9" height="7.8" fill="#c00"/>
<line x1="337.9" y1="257.9" x2="337.9" y2="277.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="333.4" y="263.6" width="9" height="7.8" fill="#c00"/>
<line x1="352.9" y1="265.7" x2="352.9" y2="285.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="348.4" y="271.4" width="9" height="7.8" fill="#c00"/>
<line x1="367.9" y1="273.5" x2="367.9" y2="293.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="363.4" y="279.2" width="9" height="7.8" fill="#c00"/>
<line x1="382.9" y1="270.9" x2="382.9" y2="293.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="378.4" y="276.6" width="9" height="10.4" fill="#188a3e"/>
<line x1="397.9" y1="270.9" x2="397.9" y2="290.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="393.4" y="276.6" width="9" height="7.8" fill="#c00"/>
<line x1="412.9" y1="278.7" x2="412.9" y2="298.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="408.4" y="284.4" width="9" height="7.8" fill="#c00"/>
<line x1="427.9" y1="278.7" x2="427.9" y2="298.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="423.4" y="284.4" width="9" height="7.8" fill="#188a3e"/>
<line x1="442.9" y1="278.7" x2="442.9" y2="298.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="438.4" y="284.4" width="9" height="7.8" fill="#c00"/>
<line x1="457.9" y1="286.5" x2="457.9" y2="303.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="453.4" y="292.2" width="9" height="5.2" fill="#c00"/>
<line x1="472.9" y1="283.9" x2="472.9" y2="303.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="468.4" y="289.6" width="9" height="7.8" fill="#188a3e"/>
<line x1="487.9" y1="283.9" x2="487.9" y2="303.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="483.4" y="289.6" width="9" height="7.8" fill="#c00"/>
<line x1="502.9" y1="292.2" x2="502.9" y2="315.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="498.4" y="297.4" width="9" height="5.2" fill="#c00"/>
<line x1="517.9" y1="289.1" x2="517.9" y2="308.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="513.4" y="294.8" width="9" height="7.8" fill="#188a3e"/>
<line x1="532.9" y1="281.3" x2="532.9" y2="301.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="528.4" y="287.0" width="9" height="7.8" fill="#188a3e"/>
<line x1="24" y1="517.8" x2="669" y2="517.8" stroke="#888"/>
<rect x="63.4" y="460.3" width="9" height="57.5" fill="#c00" opacity="0.55"/>
<rect x="78.4" y="462.8" width="9" height="55.0" fill="#c00" opacity="0.55"/>
<rect x="93.4" y="457.8" width="9" height="60.0" fill="#c00" opacity="0.55"/>
<rect x="108.4" y="461.6" width="9" height="56.2" fill="#c00" opacity="0.55"/>
<rect x="123.4" y="464.1" width="9" height="53.8" fill="#c00" opacity="0.55"/>
<rect x="138.4" y="459.1" width="9" height="58.8" fill="#c00" opacity="0.55"/>
<rect x="153.4" y="462.8" width="9" height="55.0" fill="#c00" opacity="0.55"/>
<rect x="168.4" y="465.3" width="9" height="52.5" fill="#c00" opacity="0.55"/>
<rect x="183.4" y="461.6" width="9" height="56.2" fill="#c00" opacity="0.55"/>
<rect x="198.4" y="466.6" width="9" height="51.2" fill="#c00" opacity="0.55"/>
<rect x="213.4" y="467.8" width="9" height="50.0" fill="#c00" opacity="0.55"/>
<rect x="228.4" y="465.3" width="9" height="52.5" fill="#c00" opacity="0.55"/>
<rect x="243.4" y="469.1" width="9" height="48.8" fill="#c00" opacity="0.55"/>
<rect x="258.4" y="466.6" width="9" height="51.2" fill="#c00" opacity="0.55"/>
<rect x="273.4" y="470.3" width="9" height="47.5" fill="#c00" opacity="0.55"/>
<rect x="288.4" y="462.8" width="9" height="55.0" fill="#c00" opacity="0.55"/>
<rect x="303.4" y="472.8" width="9" height="45.0" fill="#188a3e" opacity="0.55"/>
<rect x="318.4" y="470.3" width="9" height="47.5" fill="#c00" opacity="0.55"/>
<rect x="333.4" y="474.1" width="9" height="43.8" fill="#c00" opacity="0.55"/>
<rect x="348.4" y="471.6" width="9" height="46.2" fill="#c00" opacity="0.55"/>
<rect x="363.4" y="475.3" width="9" height="42.5" fill="#c00" opacity="0.55"/>
<rect x="378.4" y="467.8" width="9" height="50.0" fill="#188a3e" opacity="0.55"/>
<rect x="393.4" y="476.6" width="9" height="41.2" fill="#c00" opacity="0.55"/>
<rect x="408.4" y="472.8" width="9" height="45.0" fill="#c00" opacity="0.55"/>
<rect x="423.4" y="477.8" width="9" height="40.0" fill="#188a3e" opacity="0.55"/>
<rect x="438.4" y="474.1" width="9" height="43.8" fill="#c00" opacity="0.55"/>
<rect x="453.4" y="479.1" width="9" height="38.8" fill="#c00" opacity="0.55"/>
<rect x="468.4" y="475.3" width="9" height="42.5" fill="#188a3e" opacity="0.55"/>
<rect x="483.4" y="476.6" width="9" height="41.2" fill="#c00" opacity="0.55"/>
<rect x="498.4" y="457.8" width="9" height="60.0" fill="#c00" opacity="0.55"/>
<rect x="513.4" y="462.8" width="9" height="55.0" fill="#188a3e" opacity="0.55"/>
<rect x="528.4" y="460.3" width="9" height="57.5" fill="#188a3e" opacity="0.55"/>
<text x="24" y="451.8" fill="#555">volum</text>
<line x1="157.9" y1="80.0" x2="214.4" y2="194.7" stroke="#c00" stroke-width="1.8"/>
<polygon points="217.9,201.9 210.8,196.5 218.0,192.9" fill="#c00"/>
<text x="157.9" y="47.0" fill="#c00" text-anchor="middle" style="font-weight:bold">close 51.60 = 7.50 % peste suport</text>
<text x="157.9" y="61.0" fill="#c00" text-anchor="middle" style="font-weight:bold">prea departe: până acolo prețul mai are de căzut,</text>
<text x="157.9" y="75.0" fill="#c00" text-anchor="middle" style="font-weight:bold">deci nivelul nu-l poate opri acum</text>
<line x1="197.9" y1="380.8" x2="510.1" y2="314.5" stroke="#188a3e" stroke-width="1.8"/>
<polygon points="517.9,312.8 510.9,318.4 509.2,310.6" fill="#188a3e"/>
<text x="197.9" y="394.8" fill="#188a3e" text-anchor="middle" style="font-weight:bold">close 48.80 = 1.67 % peste suport</text>
<text x="197.9" y="408.8" fill="#188a3e" text-anchor="middle" style="font-weight:bold">la nivel: dacă mai scade puțin, dă de ordinele</text>
<text x="197.9" y="422.8" fill="#188a3e" text-anchor="middle" style="font-weight:bold">de cumpărare care au mai întors prețul de acolo</text>
<text x="24" y="548" fill="#555">Pragul de 3 % (cu 4 % „cam departe”) e al cursului; seria și prețurile sunt construite, la</text>
<text x="24" y="565" fill="#555">scară, iar procentele sunt calculate din serie. În capitolul Buy Doji, pragul de 1-2 % măsoară</text>
<text x="24" y="582" fill="#555">altceva: low-ul doji-ului față de nivel, nu închiderea simbolului.</text>
<text x="230" y="300.9" fill="#1a5fb4" style="font-weight:bold">banda de 3 %: înăuntru simbolul e „la nivel”</text></svg>

After

Width:  |  Height:  |  Size: 10 KiB

View File

@@ -18,7 +18,7 @@ Rulare: .venv/bin/python gen/strategii/selectia_scor.py
import html
from pathlib import Path
W, H = 700, 610
W, H = 700, 546
BLACK = "#000000"
GRAY = "#777777"
@@ -111,7 +111,8 @@ p.append(rect(X12, BAR_Y - 6, X13 - X12, BAR_H + 12, "spuma",
p.append(line(X7, BAR_Y - 10, X7, BAR_Y + BAR_H + 6, YELLOW, 2.4, "4 3"))
# în interiorul barei, numele componentelor
add((BAR_X0 + X_SPLIT) / 2, BAR_Y + BAR_H / 2 + 5, "F-score", 15, "bold", BLUE)
add((X_SPLIT + BAR_X1) / 2, BAR_Y + BAR_H / 2 + 5, "value-score", 15, "bold", ORANGE)
# eticheta stă în stânga casetei punctate 12-13, altfel se suprapune peste ea
add((X_SPLIT + X12) / 2, BAR_Y + BAR_H / 2 + 5, "value-score", 15, "bold", ORANGE)
# ---- scale: tick-uri + numere 0..14 sub bară
for i in range(15):
@@ -159,7 +160,7 @@ add(60, 430, "Scor -1 = date indisponibile în platformă, NU scor 0.",
14, "bold", BLACK, "start")
add(60, 450, "Scorul -1 nu se citește ca 0.", 13, "normal", GRAY, "start")
add(60, 470,
"16_ANALIZA_FUNDAMENTALA/09_implementare_f_score_tradestation.md:45-46, 268-269.",
"Îl vezi în coloana de scor a scanerului; dai refresh și îl recitești.",
13, "normal", GRAY, "start")
add(60, 498,
"„peste 7-8” e formularea exactă a cursului. Sub 7 NU e excludere:",
@@ -168,17 +169,6 @@ add(60, 518,
"la 4/14 și 6/14 continuă analiza; scorul departajează candidații.",
13, "normal", GRAY, "start")
# ---- surse
add(W / 2, 556,
"Surse: 08_ANALIZA_ZILNICA/11_selectia_simbolului.md:158-164, :199-204;",
13, "normal", GRAY)
add(W / 2, 574,
"16_ANALIZA_FUNDAMENTALA/08_piotrowski_f_score.md:70-72;",
13, "normal", GRAY)
add(W / 2, 592,
"16_ANALIZA_FUNDAMENTALA/09_implementare_f_score_tradestation.md:45-46, 268-269.",
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" '

View File

@@ -1,5 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 700 610" width="700" height="610" font-family="system-ui, sans-serif" role="img" aria-label="Scala ATM score 0-14: F-score 0-9 la care se adauga value-score 0-5; pragurile 7 (galben), 7-8 intrare in analiza, 12-13 spuma, 14 maxim">
<rect x="0" y="0" width="700" height="610" fill="#ffffff"/>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 700 546" width="700" height="546" font-family="system-ui, sans-serif" role="img" aria-label="Scala ATM score 0-14: F-score 0-9 la care se adauga value-score 0-5; pragurile 7 (galben), 7-8 intrare in analiza, 12-13 spuma, 14 maxim">
<rect x="0" y="0" width="700" height="546" fill="#ffffff"/>
<rect x="60.0" y="150.0" width="372.9" height="48.0" fill="#eef2fb" stroke="#1a5fb4" stroke-width="1.8"/>
<rect x="432.9" y="150.0" width="207.1" height="48.0" fill="#fdf0e0" stroke="#b06000" stroke-width="1.8"/>
<line x1="432.9" y1="150.0" x2="432.9" y2="198.0" stroke="#000000" stroke-width="1.2" stroke-dasharray="3 3"/>
@@ -35,7 +35,7 @@
<text x="536.4" y="112.0" font-size="15" font-weight="bold" fill="#b06000" text-anchor="middle">value-score 0-5</text>
<text x="536.4" y="131.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="middle">5/14 din bară</text>
<text x="246.4" y="179.0" font-size="15" font-weight="bold" fill="#1a5fb4" text-anchor="middle">F-score</text>
<text x="536.4" y="179.0" font-size="15" font-weight="bold" fill="#b06000" text-anchor="middle">value-score</text>
<text x="495.0" y="179.0" font-size="15" font-weight="bold" fill="#b06000" text-anchor="middle">value-score</text>
<text x="60.0" y="224.0" font-size="13" font-weight="normal" fill="#000000" text-anchor="middle">0</text>
<text x="101.4" y="224.0" font-size="13" font-weight="normal" fill="#000000" text-anchor="middle">1</text>
<text x="142.9" y="224.0" font-size="13" font-weight="normal" fill="#000000" text-anchor="middle">2</text>
@@ -68,10 +68,7 @@
<text x="391.4" y="376.0" font-size="13" font-weight="normal" fill="#000000" text-anchor="middle">puternic</text>
<text x="60.0" y="430.0" font-size="14" font-weight="bold" fill="#000000" text-anchor="start">Scor -1 = date indisponibile în platformă, NU scor 0.</text>
<text x="60.0" y="450.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="start">Scorul -1 nu se citește ca 0.</text>
<text x="60.0" y="470.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="start">16_ANALIZA_FUNDAMENTALA/09_implementare_f_score_tradestation.md:45-46, 268-269.</text>
<text x="60.0" y="470.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="start">Îl vezi în coloana de scor a scanerului; dai refresh și îl recitești.</text>
<text x="60.0" y="498.0" font-size="13" font-weight="normal" fill="#000000" text-anchor="start">„peste 7-8” e formularea exactă a cursului. Sub 7 NU e excludere:</text>
<text x="60.0" y="518.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="start">la 4/14 și 6/14 continuă analiza; scorul departajează candidații.</text>
<text x="350.0" y="556.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="middle">Surse: 08_ANALIZA_ZILNICA/11_selectia_simbolului.md:158-164, :199-204;</text>
<text x="350.0" y="574.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="middle">16_ANALIZA_FUNDAMENTALA/08_piotrowski_f_score.md:70-72;</text>
<text x="350.0" y="592.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="middle">16_ANALIZA_FUNDAMENTALA/09_implementare_f_score_tradestation.md:45-46, 268-269.</text>
</svg>

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 7.9 KiB

View File

@@ -0,0 +1,153 @@
#!/usr/bin/env python3
"""Pasul 3 — sectorul care domină: numeri semnalele pe sectoare.
Diagramă conceptuală (NU grafic de preț), pentru
`summaries/17_STRATEGII/04_selectia.md`, pasul 3. Cele 11 sectoare S&P, cu
câte semnale a dat scanerul în fiecare într-o singură zi; sectorul cu cele mai
multe e evidențiat, pentru că acolo intră banii.
Ce vine din material: cele 11 sectoare S&P și ETF-urile lor, regula „uită-te
ce predomină, în ce sectoare" și sortarea sectoarelor după cadranul 1 plus
valoarea relative strength. Ce e al meu: **numărul de semnale din fiecare
sector**. Cursul nu dă o zi cu cifre pe sectoare, așa că le-am construit; ele
ilustrează operațiunea (numărarea), nu o zi reală de piață. Scrie asta și în
desen, ca să nu fie luate drept date.
Nu folosește `svg_candles`: SVG-ul e construit ca string, doar stdlib.
Rulare: python3 gen/strategii/selectia_sectoare.py
"""
import html
from pathlib import Path
W, H = 700, 620
BLACK, GRAY, RED, GREEN, BLUE, ORANGE = "#000000", "#777777", "#c00", "#188a3e", "#1a5fb4", "#b06000"
BLUE_BG = "#eef3fb"
# (sector, ETF, semnale — numărul e construit de mine)
SECTOARE = [
("Sănătate", "XLV", 9),
("Energie", "XLE", 6),
("Financiar", "XLF", 5),
("Real estate", "XLRE", 4),
("Tehnologie", "XLK", 3),
("Industrial", "XLI", 3),
("Consum de bază", "XLP", 2),
("Consum discreționar", "XLY", 2),
("Utilități", "XLU", 1),
("Materiale", "XLB", 1),
("Comunicații", "XLC", 1),
]
X_NUME = 40.0
X0, X1 = 250.0, 600.0 # zona barelor
Y0, ROW = 132.0, 30.0
TEXTS = []
def add(x, y, s, size=13, weight="normal", fill=BLACK, anchor="middle"):
TEXTS.append((x, y, s, size, weight, fill, anchor))
def est_w(s, size, weight):
return len(s) * size * (0.62 if weight == "bold" else 0.56)
def txt(x, y, s, size, weight, fill, anchor):
return (f'<text x="{x:.1f}" y="{y:.1f}" font-size="{size}" font-weight="{weight}" '
f'fill="{fill}" text-anchor="{anchor}">{html.escape(s, quote=False)}</text>')
p = []
MAXS = max(s for *_, s in SECTOARE)
assert SECTOARE[0][2] == MAXS, "prima linie trebuie să fie sectorul dominant"
assert sum(1 for *_, s in SECTOARE if s == MAXS) == 1, "dominantul nu e unic"
assert len(SECTOARE) == 11, "S&P are 11 sectoare"
assert all(a[2] >= b[2] for a, b in zip(SECTOARE, SECTOARE[1:])), "lista nu e sortată descrescător"
add(W / 2, 34, "Pasul 3 — din ce sector vin cele mai multe semnale", 20, "bold")
add(W / 2, 58, "cele 11 sectoare S&P, cu semnalele scanerului dintr-o singură zi",
13, "normal", GRAY)
add(W / 2, 78, "de ce: mai multe semnale în același sector = cineva mută bani acolo",
13, "normal", GRAY)
add(X_NUME, 110, "sector (ETF)", 13, "bold", GRAY, "start")
add(X0, 110, "semnale în ziua asta", 13, "bold", GRAY, "start")
# dreptunghiul de evidențiere peste sectorul dominant
p.append(f'<rect x="{X_NUME - 8:.1f}" y="{Y0 - 20:.1f}" width="{X1 - X_NUME + 60:.1f}" '
f'height="{ROW:.1f}" fill="{BLUE_BG}" stroke="{BLUE}" stroke-width="1.6"/>')
for i, (nume, etf, n) in enumerate(SECTOARE):
y = Y0 + i * ROW
dominant = n == MAXS
col = BLUE if dominant else GRAY
add(X_NUME, y, f"{nume} ({etf})", 13, "bold" if dominant else "normal", col, "start")
w = n / MAXS * (X1 - X0)
p.append(f'<rect x="{X0:.1f}" y="{y - 12:.1f}" width="{w:.1f}" height="16" '
f'fill="{col}" fill-opacity="{0.85 if dominant else 0.35}"/>')
add(X0 + w + 8, y, str(n), 13, "bold" if dominant else "normal", col, "start")
# săgeata care spune de ce
Y_ARR = Y0 - 6
p.append(f'<path d="M {X1 + 46:.1f} {Y_ARR:.1f} L {X1 + 76:.1f} {Y_ARR - 26:.1f}" '
f'stroke="{BLUE}" stroke-width="2" fill="none"/>')
add(X1 + 80, Y_ARR - 30, "aici te uiți", 13, "bold", BLUE, "end")
Y_NOTE = Y0 + len(SECTOARE) * ROW + 26
p.append(f'<rect x="40" y="{Y_NOTE:.1f}" width="620" height="96" fill="#fdf0e0" '
f'stroke="{ORANGE}" stroke-width="1.6" rx="8"/>')
add(60, Y_NOTE + 26, "Ce faci cu asta", 15, "bold", ORANGE, "start")
add(60, Y_NOTE + 48, "Păstrezi simbolurile din sectorul dominant și le duci mai departe la pasul 4;",
13, "normal", BLACK, "start")
add(60, Y_NOTE + 66, "restul le lași pentru azi. Sectoarele se mai sortează și după cadranul 1 plus",
13, "normal", BLACK, "start")
add(60, Y_NOTE + 84, "valoarea relative strength — aceleași cadrane ca la pasul 5.",
13, "normal", BLACK, "start")
add(W / 2, H - 14, "Numărul de semnale pe sector e construit de mine: cursul dă regula, nu o zi cu cifre.",
13, "normal", GRAY)
head = (f'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 {W} {H}" width="{W}" '
f'height="{H}" font-family="system-ui, sans-serif" role="img" '
f'aria-label="Cele 11 sectoare S&P sortate dupa cate semnale a dat scanerul '
f'in fiecare, cu sectorul dominant evidentiat">')
body = [head, f'<rect x="0" y="0" width="{W}" height="{H}" fill="#ffffff"/>'] + p
body += [txt(*t) for t in TEXTS]
body.append("</svg>")
svg = "\n".join(body) + "\n"
# =============================================================== VERIFICARE
# lungimea barei e proporțională cu numărul din etichetă
for i, (nume, etf, n) in enumerate(SECTOARE):
w = n / MAXS * (X1 - X0)
assert abs(w / (X1 - X0) - n / MAXS) < 1e-9, f"{nume}: bara nu e la scară"
assert X0 + w <= X1 + 1e-9, f"{nume}: bara iese din zona ei"
# etichete în pânză, fără suprapuneri
boxes = []
for x, y, s, size, weight, fill, anchor in TEXTS:
assert size >= 13, f"font sub 13px: {s!r}"
w = est_w(s, size, weight)
left = x - w if anchor == "end" else (x - w / 2 if anchor == "middle" else x)
assert -2 <= left and left + w <= W + 2, f"text în afara pânzei: {s!r}"
assert 0 <= y - size * 0.78 and y + size * 0.22 <= H, f"text în afara pânzei: {s!r}"
boxes.append((left, left + w, y - size * 0.78, y + size * 0.22, s))
for i in range(len(boxes)):
for j in range(i + 1, len(boxes)):
l1, r1, t1, b1, s1 = boxes[i]
l2, r2, t2, b2, s2 = boxes[j]
if r1 > l2 + 2 and r2 > l1 + 2 and b1 > t2 + 2 and b2 > t1 + 2:
raise AssertionError(f"etichete suprapuse: {s1!r} / {s2!r}")
# numele de sector nu intră peste zona barelor
for x, y, s, size, weight, fill, anchor in TEXTS:
if anchor == "start" and x == X_NUME and y >= Y0:
assert x + est_w(s, size, weight) < X0 - 6, f"numele iese peste bare: {s!r}"
assert "\n\n" not in svg, "linie goală în SVG"
OUT = Path(__file__).with_suffix(".svg")
OUT.write_text(svg, encoding="utf-8")
print(f"scris {OUT.name} ({len(svg)} bytes, {len(TEXTS)} etichete, "
f"{len(SECTOARE)} sectoare, dominant {SECTOARE[0][0]} cu {MAXS}, {W}x{H}), verificare OK")

View File

@@ -0,0 +1,50 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 700 620" width="700" height="620" font-family="system-ui, sans-serif" role="img" aria-label="Cele 11 sectoare S&P sortate dupa cate semnale a dat scanerul in fiecare, cu sectorul dominant evidentiat">
<rect x="0" y="0" width="700" height="620" fill="#ffffff"/>
<rect x="32.0" y="112.0" width="620.0" height="30.0" fill="#eef3fb" stroke="#1a5fb4" stroke-width="1.6"/>
<rect x="250.0" y="120.0" width="350.0" height="16" fill="#1a5fb4" fill-opacity="0.85"/>
<rect x="250.0" y="150.0" width="233.3" height="16" fill="#777777" fill-opacity="0.35"/>
<rect x="250.0" y="180.0" width="194.4" height="16" fill="#777777" fill-opacity="0.35"/>
<rect x="250.0" y="210.0" width="155.6" height="16" fill="#777777" fill-opacity="0.35"/>
<rect x="250.0" y="240.0" width="116.7" height="16" fill="#777777" fill-opacity="0.35"/>
<rect x="250.0" y="270.0" width="116.7" height="16" fill="#777777" fill-opacity="0.35"/>
<rect x="250.0" y="300.0" width="77.8" height="16" fill="#777777" fill-opacity="0.35"/>
<rect x="250.0" y="330.0" width="77.8" height="16" fill="#777777" fill-opacity="0.35"/>
<rect x="250.0" y="360.0" width="38.9" height="16" fill="#777777" fill-opacity="0.35"/>
<rect x="250.0" y="390.0" width="38.9" height="16" fill="#777777" fill-opacity="0.35"/>
<rect x="250.0" y="420.0" width="38.9" height="16" fill="#777777" fill-opacity="0.35"/>
<path d="M 646.0 126.0 L 676.0 100.0" stroke="#1a5fb4" stroke-width="2" fill="none"/>
<rect x="40" y="488.0" width="620" height="96" fill="#fdf0e0" stroke="#b06000" stroke-width="1.6" rx="8"/>
<text x="350.0" y="34.0" font-size="20" font-weight="bold" fill="#000000" text-anchor="middle">Pasul 3 — din ce sector vin cele mai multe semnale</text>
<text x="350.0" y="58.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="middle">cele 11 sectoare S&amp;P, cu semnalele scanerului dintr-o singură zi</text>
<text x="350.0" y="78.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="middle">de ce: mai multe semnale în același sector = cineva mută bani acolo</text>
<text x="40.0" y="110.0" font-size="13" font-weight="bold" fill="#777777" text-anchor="start">sector (ETF)</text>
<text x="250.0" y="110.0" font-size="13" font-weight="bold" fill="#777777" text-anchor="start">semnale în ziua asta</text>
<text x="40.0" y="132.0" font-size="13" font-weight="bold" fill="#1a5fb4" text-anchor="start">Sănătate (XLV)</text>
<text x="608.0" y="132.0" font-size="13" font-weight="bold" fill="#1a5fb4" text-anchor="start">9</text>
<text x="40.0" y="162.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="start">Energie (XLE)</text>
<text x="491.3" y="162.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="start">6</text>
<text x="40.0" y="192.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="start">Financiar (XLF)</text>
<text x="452.4" y="192.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="start">5</text>
<text x="40.0" y="222.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="start">Real estate (XLRE)</text>
<text x="413.6" y="222.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="start">4</text>
<text x="40.0" y="252.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="start">Tehnologie (XLK)</text>
<text x="374.7" y="252.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="start">3</text>
<text x="40.0" y="282.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="start">Industrial (XLI)</text>
<text x="374.7" y="282.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="start">3</text>
<text x="40.0" y="312.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="start">Consum de bază (XLP)</text>
<text x="335.8" y="312.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="start">2</text>
<text x="40.0" y="342.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="start">Consum discreționar (XLY)</text>
<text x="335.8" y="342.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="start">2</text>
<text x="40.0" y="372.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="start">Utilități (XLU)</text>
<text x="296.9" y="372.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="start">1</text>
<text x="40.0" y="402.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="start">Materiale (XLB)</text>
<text x="296.9" y="402.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="start">1</text>
<text x="40.0" y="432.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="start">Comunicații (XLC)</text>
<text x="296.9" y="432.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="start">1</text>
<text x="680.0" y="96.0" font-size="13" font-weight="bold" fill="#1a5fb4" text-anchor="end">aici te uiți</text>
<text x="60.0" y="514.0" font-size="15" font-weight="bold" fill="#b06000" text-anchor="start">Ce faci cu asta</text>
<text x="60.0" y="536.0" font-size="13" font-weight="normal" fill="#000000" text-anchor="start">Păstrezi simbolurile din sectorul dominant și le duci mai departe la pasul 4;</text>
<text x="60.0" y="554.0" font-size="13" font-weight="normal" fill="#000000" text-anchor="start">restul le lași pentru azi. Sectoarele se mai sortează și după cadranul 1 plus</text>
<text x="60.0" y="572.0" font-size="13" font-weight="normal" fill="#000000" text-anchor="start">valoarea relative strength — aceleași cadrane ca la pasul 5.</text>
<text x="350.0" y="606.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="middle">Numărul de semnale pe sector e construit de mine: cursul dă regula, nu o zi cu cifre.</text>
</svg>

After

Width:  |  Height:  |  Size: 5.7 KiB

View File

@@ -0,0 +1,194 @@
#!/usr/bin/env python3
"""Pasul 1 — universul și lichiditatea: cele două praguri, desenate ca o zonă.
Diagramă conceptuală (NU grafic de preț), pentru
`summaries/17_STRATEGII/04_selectia.md`, pasul 1. Pe orizontală prețul de
închidere, pe verticală volumul mediu zilnic. Pragurile cursului (close peste
30-40 $, volum mediu de cel puțin 500.000 de acțiuni, ideal peste un milion)
taie planul în patru; dreptunghiul verde e singurul colț din care ai voie să
iei simboluri.
Cele trei simboluri sunt anonime (A, B, C) și cu cifre construite de mine:
cursul dă pragurile, nu exemple numerice. Le pun ca să se vadă că un simbol
poate pica pe oricare din cele două praguri, separat.
Nu folosește `svg_candles`: SVG-ul e construit ca string, doar stdlib.
Rulare: python3 gen/strategii/selectia_univers.py
"""
import html
from pathlib import Path
W, H = 700, 604
BLACK, GRAY, RED, GREEN, BLUE, ORANGE = "#000000", "#777777", "#c00", "#188a3e", "#1a5fb4", "#b06000"
GREEN_BG = "#eef7f0"
# ---------------------------------------------------------------- praguri (cursul)
PRET_MIN, PRET_IDEAL = 30.0, 40.0 # close peste 30-40 $
VOL_MIN, VOL_IDEAL = 0.5, 1.0 # milioane de acțiuni pe zi
# ---------------------------------------------------------------- simboluri (construite)
# (nume, preț, volum mediu în milioane, verdict)
SIMB = [
("A", 58.0, 2.4, "trece"),
("B", 24.0, 3.1, "cade pe preț"),
("C", 72.0, 0.18, "cade pe volum"),
]
# ---------------------------------------------------------------- geometrie
X0, X1 = 110.0, 630.0
Y0, Y1 = 130.0, 420.0
PMAX, VMAX = 100.0, 3.5
def px(p):
return X0 + p / PMAX * (X1 - X0)
def py(v):
return Y1 - v / VMAX * (Y1 - Y0)
TEXTS = []
def add(x, y, s, size=13, weight="normal", fill=BLACK, anchor="middle"):
TEXTS.append((x, y, s, size, weight, fill, anchor))
def est_w(s, size, weight):
return len(s) * size * (0.62 if weight == "bold" else 0.56)
def txt(x, y, s, size, weight, fill, anchor):
return (f'<text x="{x:.1f}" y="{y:.1f}" font-size="{size}" font-weight="{weight}" '
f'fill="{fill}" text-anchor="{anchor}">{html.escape(s, quote=False)}</text>')
def line(x1, y1, x2, y2, stroke=GRAY, w=1.0, dash=None):
d = f' stroke-dasharray="{dash}"' if dash else ""
return (f'<line x1="{x1:.1f}" y1="{y1:.1f}" x2="{x2:.1f}" y2="{y2:.1f}" '
f'stroke="{stroke}" stroke-width="{w}"{d}/>')
p = []
add(W / 2, 34, "Pasul 1 — cine intră în universul de scanare", 20, "bold")
add(W / 2, 58, "pe orizontală prețul de închidere, pe verticală volumul mediu zilnic",
13, "normal", GRAY)
add(W / 2, 78, "de ce pragurile: pe un simbol subțire, ordinul tău mută singur prețul",
13, "normal", GRAY)
# zona verde: singurul colț bun
p.append(f'<rect x="{px(PRET_MIN):.1f}" y="{Y0:.1f}" width="{X1 - px(PRET_MIN):.1f}" '
f'height="{py(VOL_MIN) - Y0:.1f}" fill="{GREEN_BG}" stroke="{GREEN}" stroke-width="1.8"/>')
add(px(PRET_MIN) + 10, Y0 + 22, "zona din care iei simboluri", 14, "bold", GREEN, "start")
# cadrul și axele
p.append(line(X0, Y0, X0, Y1, GRAY, 1.2))
p.append(line(X0, Y1, X1, Y1, GRAY, 1.2))
# pragurile
p.append(line(px(PRET_MIN), Y0, px(PRET_MIN), Y1, GREEN, 1.8))
p.append(line(px(PRET_IDEAL), Y0, px(PRET_IDEAL), Y1, GREEN, 1.2, "5 3"))
p.append(line(X0, py(VOL_MIN), X1, py(VOL_MIN), GREEN, 1.8))
p.append(line(X0, py(VOL_IDEAL), X1, py(VOL_IDEAL), GREEN, 1.2, "5 3"))
add(px(PRET_MIN), Y1 + 38, "30 $", 13, "bold", GREEN)
add(px(PRET_IDEAL), Y1 + 56, "40 $ (ideal)", 13, "normal", GREEN)
add(X0 - 10, py(VOL_MIN) + 4, "500.000", 13, "bold", GREEN, "end")
add(X0 - 10, py(VOL_IDEAL) + 4, "1 milion", 13, "normal", GREEN, "end")
# repere de axă
for v in (0, 1, 2, 3):
p.append(line(X0 - 5, py(v), X0, py(v), GRAY, 1.0))
add(X0 - 62, py(0) + 4, "0", 13, "normal", GRAY, "end")
add(X0 - 62, py(2) + 4, "2 mil.", 13, "normal", GRAY, "end")
add(X0 - 62, py(3) + 4, "3 mil.", 13, "normal", GRAY, "end")
for pr in (0, 50, 100):
p.append(line(px(pr), Y1, px(pr), Y1 + 5, GRAY, 1.0))
add(px(pr), Y1 + 20, f"{pr} $", 13, "normal", GRAY)
add(X1, Y1 + 56, "prețul de închidere", 13, "normal", GRAY, "end")
add(X0 - 48, Y0 - 12, "volum mediu zilnic", 13, "normal", GRAY, "start")
# cele trei simboluri
for nume, pret, vol, verdict in SIMB:
x, y = px(pret), py(vol)
col = GREEN if verdict == "trece" else RED
p.append(f'<circle cx="{x:.1f}" cy="{y:.1f}" r="7" fill="{col}"/>')
add(x, y - 14, f"Simbol {nume}", 13, "bold", col)
add(x, y + 26, f"{pret:.0f} $ · {vol:.2f} mil.", 13, "normal", BLACK)
add(x, y + 44, verdict, 13, "bold", col)
# caseta cu de ce
NOTE_Y = 504.0
p.append(f'<rect x="40" y="{NOTE_Y}" width="620" height="76" fill="#fdf0e0" '
f'stroke="{ORANGE}" stroke-width="1.6" rx="8"/>')
add(60, NOTE_Y + 26, "De ce contează amândouă, nu doar una", 15, "bold", ORANGE, "start")
add(60, NOTE_Y + 48,
"Simbolul B se tranzacționează mult, dar e prea ieftin; simbolul C e scump, dar",
13, "normal", BLACK, "start")
add(60, NOTE_Y + 66,
"aproape nimeni nu-l cumpără: acolo ordinul tău e cel care mișcă prețul.",
13, "normal", BLACK, "start")
head = (f'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 {W} {H}" width="{W}" '
f'height="{H}" font-family="system-ui, sans-serif" role="img" '
f'aria-label="Pragurile de pret si de volum ale universului de scanare, '
f'cu trei simboluri dintre care doar unul cade in zona buna">')
body = [head, f'<rect x="0" y="0" width="{W}" height="{H}" fill="#ffffff"/>'] + p
body += [txt(*t) for t in TEXTS]
body.append("</svg>")
svg = "\n".join(body) + "\n"
# =============================================================== VERIFICARE
# 1. verdictul fiecărui simbol iese din cifrele lui, nu e scris de mână
for nume, pret, vol, verdict in SIMB:
trece = pret >= PRET_MIN and vol >= VOL_MIN
assert trece == (verdict == "trece"), f"Simbol {nume}: verdictul nu iese din cifre"
if verdict == "cade pe preț":
assert pret < PRET_MIN and vol >= VOL_MIN, f"Simbol {nume} nu cade doar pe preț"
if verdict == "cade pe volum":
assert vol < VOL_MIN and pret >= PRET_MIN, f"Simbol {nume} nu cade doar pe volum"
assert sum(1 for *_, v in SIMB if v == "trece") == 1, "aștept exact un simbol care trece"
# 2. zona verde e exact colțul „peste ambele praguri"
assert px(PRET_MIN) > X0 and py(VOL_MIN) < Y1, "zona verde nu e un colț al planului"
for nume, pret, vol, verdict in SIMB:
inauntru = px(PRET_MIN) <= px(pret) <= X1 and Y0 <= py(vol) <= py(VOL_MIN)
assert inauntru == (verdict == "trece"), f"Simbol {nume}: punctul nu e desenat în zona lui"
# 3. toate punctele încap în cadru
for nume, pret, vol, _ in SIMB:
assert X0 < px(pret) < X1, f"Simbol {nume}: prețul iese din cadru"
assert Y0 < py(vol) < Y1, f"Simbol {nume}: volumul iese din cadru"
# 4. liniile de prag nu cad pe marginea cadrului
for x in (px(PRET_MIN), px(PRET_IDEAL)):
assert x - X0 > 20 and X1 - x > 20, "linie de prag lipită de marginea cadrului"
for y in (py(VOL_MIN), py(VOL_IDEAL)):
assert y - Y0 > 20 and Y1 - y > 20, "linie de prag lipită de marginea cadrului"
# 5. etichete în pânză și fără suprapuneri
boxes = []
for x, y, s, size, weight, fill, anchor in TEXTS:
assert size >= 13, f"font sub 13px: {s!r}"
w = est_w(s, size, weight)
left = x - w if anchor == "end" else (x - w / 2 if anchor == "middle" else x)
assert -2 <= left and left + w <= W + 2, f"text în afara pânzei: {s!r}"
assert 0 <= y - size * 0.78 and y + size * 0.22 <= H, f"text în afara pânzei: {s!r}"
boxes.append((left, left + w, y - size * 0.78, y + size * 0.22, s))
for i in range(len(boxes)):
for j in range(i + 1, len(boxes)):
l1, r1, t1, b1, s1 = boxes[i]
l2, r2, t2, b2, s2 = boxes[j]
if r1 > l2 + 2 and r2 > l1 + 2 and b1 > t2 + 2 and b2 > t1 + 2:
raise AssertionError(f"etichete suprapuse: {s1!r} / {s2!r}")
assert "\n\n" not in svg, "linie goală în SVG"
OUT = Path(__file__).with_suffix(".svg")
OUT.write_text(svg, encoding="utf-8")
print(f"scris {OUT.name} ({len(svg)} bytes, {len(TEXTS)} etichete, "
f"{len(SIMB)} simboluri, {W}x{H}), verificare OK")

View File

@@ -0,0 +1,49 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 700 604" width="700" height="604" font-family="system-ui, sans-serif" role="img" aria-label="Pragurile de pret si de volum ale universului de scanare, cu trei simboluri dintre care doar unul cade in zona buna">
<rect x="0" y="0" width="700" height="604" fill="#ffffff"/>
<rect x="266.0" y="130.0" width="364.0" height="248.6" fill="#eef7f0" stroke="#188a3e" stroke-width="1.8"/>
<line x1="110.0" y1="130.0" x2="110.0" y2="420.0" stroke="#777777" stroke-width="1.2"/>
<line x1="110.0" y1="420.0" x2="630.0" y2="420.0" stroke="#777777" stroke-width="1.2"/>
<line x1="266.0" y1="130.0" x2="266.0" y2="420.0" stroke="#188a3e" stroke-width="1.8"/>
<line x1="318.0" y1="130.0" x2="318.0" y2="420.0" stroke="#188a3e" stroke-width="1.2" stroke-dasharray="5 3"/>
<line x1="110.0" y1="378.6" x2="630.0" y2="378.6" stroke="#188a3e" stroke-width="1.8"/>
<line x1="110.0" y1="337.1" x2="630.0" y2="337.1" stroke="#188a3e" stroke-width="1.2" stroke-dasharray="5 3"/>
<line x1="105.0" y1="420.0" x2="110.0" y2="420.0" stroke="#777777" stroke-width="1.0"/>
<line x1="105.0" y1="337.1" x2="110.0" y2="337.1" stroke="#777777" stroke-width="1.0"/>
<line x1="105.0" y1="254.3" x2="110.0" y2="254.3" stroke="#777777" stroke-width="1.0"/>
<line x1="105.0" y1="171.4" x2="110.0" y2="171.4" stroke="#777777" stroke-width="1.0"/>
<line x1="110.0" y1="420.0" x2="110.0" y2="425.0" stroke="#777777" stroke-width="1.0"/>
<line x1="370.0" y1="420.0" x2="370.0" y2="425.0" stroke="#777777" stroke-width="1.0"/>
<line x1="630.0" y1="420.0" x2="630.0" y2="425.0" stroke="#777777" stroke-width="1.0"/>
<circle cx="411.6" cy="221.1" r="7" fill="#188a3e"/>
<circle cx="234.8" cy="163.1" r="7" fill="#c00"/>
<circle cx="484.4" cy="405.1" r="7" fill="#c00"/>
<rect x="40" y="504.0" width="620" height="76" fill="#fdf0e0" stroke="#b06000" stroke-width="1.6" rx="8"/>
<text x="350.0" y="34.0" font-size="20" font-weight="bold" fill="#000000" text-anchor="middle">Pasul 1 — cine intră în universul de scanare</text>
<text x="350.0" y="58.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="middle">pe orizontală prețul de închidere, pe verticală volumul mediu zilnic</text>
<text x="350.0" y="78.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="middle">de ce pragurile: pe un simbol subțire, ordinul tău mută singur prețul</text>
<text x="276.0" y="152.0" font-size="14" font-weight="bold" fill="#188a3e" text-anchor="start">zona din care iei simboluri</text>
<text x="266.0" y="458.0" font-size="13" font-weight="bold" fill="#188a3e" text-anchor="middle">30 $</text>
<text x="318.0" y="476.0" font-size="13" font-weight="normal" fill="#188a3e" text-anchor="middle">40 $ (ideal)</text>
<text x="100.0" y="382.6" font-size="13" font-weight="bold" fill="#188a3e" text-anchor="end">500.000</text>
<text x="100.0" y="341.1" font-size="13" font-weight="normal" fill="#188a3e" text-anchor="end">1 milion</text>
<text x="48.0" y="424.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="end">0</text>
<text x="48.0" y="258.3" font-size="13" font-weight="normal" fill="#777777" text-anchor="end">2 mil.</text>
<text x="48.0" y="175.4" font-size="13" font-weight="normal" fill="#777777" text-anchor="end">3 mil.</text>
<text x="110.0" y="440.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="middle">0 $</text>
<text x="370.0" y="440.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="middle">50 $</text>
<text x="630.0" y="440.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="middle">100 $</text>
<text x="630.0" y="476.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="end">prețul de închidere</text>
<text x="62.0" y="118.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="start">volum mediu zilnic</text>
<text x="411.6" y="207.1" font-size="13" font-weight="bold" fill="#188a3e" text-anchor="middle">Simbol A</text>
<text x="411.6" y="247.1" font-size="13" font-weight="normal" fill="#000000" text-anchor="middle">58 $ · 2.40 mil.</text>
<text x="411.6" y="265.1" font-size="13" font-weight="bold" fill="#188a3e" text-anchor="middle">trece</text>
<text x="234.8" y="149.1" font-size="13" font-weight="bold" fill="#c00" text-anchor="middle">Simbol B</text>
<text x="234.8" y="189.1" font-size="13" font-weight="normal" fill="#000000" text-anchor="middle">24 $ · 3.10 mil.</text>
<text x="234.8" y="207.1" font-size="13" font-weight="bold" fill="#c00" text-anchor="middle">cade pe preț</text>
<text x="484.4" y="391.1" font-size="13" font-weight="bold" fill="#c00" text-anchor="middle">Simbol C</text>
<text x="484.4" y="431.1" font-size="13" font-weight="normal" fill="#000000" text-anchor="middle">72 $ · 0.18 mil.</text>
<text x="484.4" y="449.1" font-size="13" font-weight="bold" fill="#c00" text-anchor="middle">cade pe volum</text>
<text x="60.0" y="530.0" font-size="15" font-weight="bold" fill="#b06000" text-anchor="start">De ce contează amândouă, nu doar una</text>
<text x="60.0" y="552.0" font-size="13" font-weight="normal" fill="#000000" text-anchor="start">Simbolul B se tranzacționează mult, dar e prea ieftin; simbolul C e scump, dar</text>
<text x="60.0" y="570.0" font-size="13" font-weight="normal" fill="#000000" text-anchor="start">aproape nimeni nu-l cumpără: acolo ordinul tău e cel care mișcă prețul.</text>
</svg>

After

Width:  |  Height:  |  Size: 5.3 KiB