etichete: doua defecte vechi la mdsrt, trei la mp2, si verdictul pe restul

La mdsrt_aplus eticheta spunea "primul low 94.60" pentru o bara al carei low
era 94.50. Reparatia a mutat low-ul, nu eticheta: regula capitolului numara
piciorul dupa low, iar specul spune tot 94.60 - doar umbra de 0.10 o
contrazicea. Nicio cifra tiparita nu se schimba, iar nivelul isi ia acum
eticheta din date, cu assert, ca sa nu mai poata minti.

Cele trei de la mp2 aveau toate aceeasi cauza fizica: text colorat peste un
corp de candela de aceeasi culoare. Acolo caracterele nu se incaleca, dispar -
"intrare 577.00" se citea "intrare 577. 0", "crossing" se citea "crossi g".

VERDICT pe restul de ~94: nu merita un lot. Din 20 de suprapuneri vazute
efectiv pe ecran, doar 3 schimbau ce citesti, si toate trei din cauza aia.
Celelalte 17 - text peste fitil, peste linie de nivel, peste chenar, peste
coada de sageata - raman lizibile, fiindca fundalul e o linie subtire, nu o
suprafata plina. Filtrul util nu e tiparul geometric, ci: eticheta cu cifra,
peste un <rect> de aceeasi culoare.

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-10-02 06:00:45 +00:00
parent 29dc93dfad
commit 602419c93a
14 changed files with 194 additions and 164 deletions

View File

@@ -80,6 +80,10 @@ CLOSES_N = [
assert len(CLOSES_N) == 29, len(CLOSES_N)
WICKS_N = [(0.10, 0.10)] * 29
# bara 18 e „primul low 94.60" al panoului: fără umbră de jos, ca low-ul ei
# să fie chiar 94.60. Cu umbra implicită de 0.10 low-ul era 94.50, iar
# nivelul desenat la 94.60 numea de fapt close-ul (raportat pe 02.10.2026).
WICKS_N[18] = (0.10, 0.00)
WICKS_N[25] = (0.05, 0.40) # high 92.45, low 92.00 - 0.40 = 91.60
VOLS_N = [
@@ -122,6 +126,8 @@ assert VOLS_A[24] > VOLS_A[18]
# (9) NU: close sub pivot ȘI sub primul low
assert abs(cds_n[25].c - 92.00) < 1e-9, cds_n[25].c
assert cds_n[25].c < SUPORT and cds_n[25].c < 94.60
# nivelul „primul low 94.60" numește low-ul barei 18, nu close-ul ei
assert abs(cds_n[18].l - 94.60) < 1e-9, cds_n[18].l
# (10) NU: coborâre fără trigger
assert cds_n[25].c < cds_n[24].c < cds_n[23].c
# (11) NU: fără divergență (lower low pe preț și pe volum, conform assert-ului)
@@ -168,7 +174,7 @@ ch_a = Chart(
ch_n = Chart(
candles=cds_n,
levels=[Level(SUPORT, "pivot monthly 94.00", ORANGE, label_at="left"),
Level(94.60, "primul low 94.60", GRAY, i0=18),
Level(cds_n[18].l, f"primul low {cds_n[18].l:.2f}", GRAY, i0=18),
Level(92.00, "close 92.00", RED, i0=25),
Level(90.80, "spre 90.80", RED, label_at="left")],
marks=[Mark(18, "primul low", ORANGE, "above", dy=-2)],

View File

@@ -150,7 +150,7 @@
<rect x="386.0" y="704.0" width="8" height="4.0" fill="#c00"/>
<line x1="405.0" y1="698.0" x2="405.0" y2="710.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="401.0" y="700.0" width="8" height="8.0" fill="#188a3e"/>
<line x1="420.0" y1="698.0" x2="420.0" y2="702.0" stroke="#1a1a1a" stroke-width="1.2"/>
<line x1="420.0" y1="698.0" x2="420.0" y2="700.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="416.0" y="700.0" width="8" height="1.6" fill="#188a3e"/>
<line x1="435.0" y1="698.0" x2="435.0" y2="712.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="431.0" y="700.0" width="8" height="10.0" fill="#c00"/>

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -95,8 +95,11 @@ ch = Chart(
],
scale=58.0, gap=18, body_w=10, left=176, width=W, top=64, vol_h=60,
vol_label="volum: la piciorul 2 volumul crește, prețul nu mai are cumpărători = divergență",
title="Oglinda pe short (serie construită prin răsturnarea exemplului long)",
caption="Varianta short nu e explicată în curs: e reconstruită prin oglindire.",
# titlul e scurt pe un singur rând: cu paranteza („serie construită prin
# răsturnarea exemplului long") se întindea până sub coada săgeții
# „piciorul 1", care îl traversa. Explicația a trecut în caption.
title="Oglinda pe short",
caption="Serie răsturnată din exemplul long; varianta short nu e explicată în curs.",
)
svg = ch.render()
assert "\n\n" not in svg, "linie goală în SVG"

View File

@@ -1,5 +1,5 @@
<svg viewBox="0 0 700 552" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif">
<text x="24" y="112" fill="#333" style="font-weight:bold">Oglinda pe short (serie construită prin răsturnarea exemplului long)</text>
<text x="24" y="112" fill="#333" style="font-weight:bold">Oglinda pe short</text>
<rect x="382.0" y="118.0" width="38.0" height="62.4" fill="#c00" fill-opacity="0.08" stroke="#c00" stroke-width="1"/>
<line x1="24.0" y1="155.0" x2="686" y2="155.0" stroke="#1a5fb4" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30.0" y="149.0" fill="#1a5fb4">pivot daily 100.00 — zona, sus</text>
@@ -106,5 +106,5 @@
<polygon points="410.0,176.4 414.7,184.0 406.8,184.7" fill="#188a3e"/>
<text x="430.0" y="401.3" fill="#188a3e" text-anchor="middle" style="font-weight:bold">intri short la 99.80: close sub nivel și sub low-ul candelei-trigger</text>
<text x="430.0" y="415.3" fill="#188a3e" text-anchor="middle" style="font-weight:bold">cei prinși long vând ca să iasă — coborârea e bruscă</text>
<text x="24" y="540" fill="#555">Varianta short nu e explicată în curs: e reconstruită prin oglindire.</text>
<text x="24" y="540" fill="#555">Serie răsturnată din exemplul long; varianta short nu e explicată în curs.</text>
</svg>

Before

Width:  |  Height:  |  Size: 9.3 KiB

After

Width:  |  Height:  |  Size: 9.2 KiB

View File

@@ -25,6 +25,8 @@ from pathlib import Path
sys.path.insert(0, "/workspace/atm-curs-dl")
from svg_candles import Candle, Chart, Level, Mark, from_closes # noqa: E402
sys.path.insert(0, "/workspace/atm-curs-dl/gen")
from eticheta_libera import eticheta_libera # noqa: E402
OUT = Path(__file__).resolve().parent / "mp2_aplus.svg"
@@ -133,13 +135,19 @@ ch_a = Chart(
candles=cds_a,
levels=[Level(SUP_A, f"suport quarterly {SUP_A:.2f}", GRAY, label_at="left"),
Level(SL_A, f"SL {SL_A:.2f} (peste suport)", RED, label_at="right"),
Level(entry_a, f"intrare {entry_a:.2f}", GREEN, label_at="left"),
# label_dy: intrarea 577.00 și neckline-ul 578.00 sunt la 1.00
# (7.5 px) una de alta, iar linia portocalie trecea exact prin
# zecimala etichetei verzi; eticheta coboară sub linia ei
Level(entry_a, f"intrare {entry_a:.2f}", GREEN, label_at="left",
label_dy=18),
Level(NECK_A, f"neckline {NECK_A:.2f}", ORANGE, label_at="right"),
Level(TP1_A, f"TP1 {TP1_A:.2f} = 1:1", BLUE, label_at="right")],
marks=[Mark(LS_A, f"umăr stâng {ls_a:.0f}", GRAY, "above", dy=-4),
Mark(HEAD_A, f"head {head_a:.0f} / double bottom", RED, "below", dy=8),
Mark(RS_A, f"umăr drept {rs_a:.0f}", GRAY, "above", dy=-4),
Mark(ENTRY_A, "crossing", GREEN, "above", dy=-6)],
# dx: pe candela ei, eticheta cădea peste corpul verde de
# alături și se citea „crossi g" (verde pe verde, 02.10.2026)
Mark(ENTRY_A, "crossing", GREEN, "above", dy=-6, dx=-32)],
scale=7.5, gap=15, body_w=9, left=44, width=PW, vol_h=64,
vol_label="volum", title="A+ — crossing la confluență (SPY, aprilie)",
trend="down",
@@ -152,7 +160,9 @@ ch_m = Chart(
Level(SL_M, f"SL {SL_M:.2f}", RED, label_at="right"),
Level(entry_m, f"intrare {entry_m:.2f}", GREEN, label_at="right"),
Level(TP1_M, f"TP1 {TP1_M:.2f}", BLUE, label_at="right")],
marks=[Mark(ENTRY_M, "crossing (mijloc)", GREEN, "above", dy=-4)],
# idem: „(mijloc)" intra sub corpul verde următor; mai sus nu e loc,
# candelele urcă, deci eticheta pleacă lateral
marks=[Mark(ENTRY_M, "crossing (mijloc)", GREEN, "above", dy=-4, dx=-50)],
scale=34.0, gap=15, body_w=9, left=44, width=PW, vol_h=64,
vol_label="volum", title="Mediocru — crossing în mijlocul range-ului (construit)",
caption="exemplu construit, nu date reale — SL nu stă pe niciun pivot",
@@ -268,6 +278,11 @@ for cheie in ("suport quarterly 554.00", f"SL {SL_A:.2f} (peste suport)", "intra
"crossing (mijloc)", "exemplu construit, nu date reale"):
assert cheie in wrapper, f"lipsește din desen: {cheie!r}"
# cele două etichete mutate pe 02.10.2026: verificarea rămâne pornită ca
# o mutare viitoare să nu le bage înapoi sub corpurile verzi
eticheta_libera(wrapper, "aplus-crossing", {"crossing", "crossing (mijloc)"},
rects=True)
OUT.write_text(wrapper, encoding="utf-8")
print(f"scris {OUT.name}: {TOTAL_W}x{TOTAL_H:.0f}, "
f"{len(all_txt)} etichete, verificare OK")

View File

@@ -1,14 +1,14 @@
<svg viewBox="0 0 1160 694" width="1160" height="694" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif"><text x="580" y="20" fill="#333" text-anchor="middle" style="font-weight:bold">MP² crossing long — setup A+ vs. setup mediocru (aceeași strategie)</text><g transform="translate(8,38)">
<text x="24" y="48" fill="#333" style="font-weight:bold">A+ — crossing la confluență (SPY, aprilie)</text>
<line x1="24" y1="454.0" x2="546" y2="454.0" stroke="#777" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30" y="448.0" fill="#777">suport quarterly 554.00</text>
<line x1="24" y1="451.0" x2="546" y2="451.0" stroke="#c00" stroke-width="1.5" stroke-dasharray="4 3"/>
<line x1="24.0" y1="454.0" x2="546" y2="454.0" stroke="#777" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30.0" y="448.0" fill="#777">suport quarterly 554.00</text>
<line x1="24.0" y1="451.0" x2="546" y2="451.0" stroke="#c00" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="532" y="445.0" fill="#c00" text-anchor="end">SL 554.40 (peste suport)</text>
<line x1="24" y1="281.5" x2="546" y2="281.5" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30" y="275.5" fill="#188a3e">intrare 577.00</text>
<line x1="24" y1="274.0" x2="546" y2="274.0" stroke="#b06000" stroke-width="1.5" stroke-dasharray="4 3"/>
<line x1="24.0" y1="281.5" x2="546" y2="281.5" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30.0" y="293.5" fill="#188a3e">intrare 577.00</text>
<line x1="24.0" y1="274.0" x2="546" y2="274.0" stroke="#b06000" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="532" y="268.0" fill="#b06000" text-anchor="end">neckline 578.00</text>
<line x1="24" y1="112.0" x2="546" y2="112.0" stroke="#1a5fb4" stroke-width="1.5" stroke-dasharray="4 3"/>
<line x1="24.0" y1="112.0" x2="546" y2="112.0" stroke="#1a5fb4" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="532" y="106.0" fill="#1a5fb4" text-anchor="end">TP1 599.60 = 1:1</text>
<polyline points="24,75.8 36,121.8" fill="none" stroke="#999" stroke-width="2"/>
<text x="24" y="63.8" fill="#999">downtrend anterior</text>
@@ -116,19 +116,19 @@
<text x="254.0" y="350.0" fill="#777" text-anchor="middle" style="font-weight:bold">umăr stâng 566</text>
<text x="299.0" y="468.0" fill="#c00" text-anchor="middle" style="font-weight:bold">head 555 / double bottom</text>
<text x="344.0" y="335.0" fill="#777" text-anchor="middle" style="font-weight:bold">umăr drept 568</text>
<text x="374.0" y="263.6" fill="#188a3e" text-anchor="middle" style="font-weight:bold">crossing</text>
<text x="342.0" y="263.6" fill="#188a3e" text-anchor="middle" style="font-weight:bold">crossing</text>
<text x="24" y="574" fill="#555">Confluență: 554.00 + double bottom + neckline 578.00 · 1R 22.60</text>
</g><g transform="translate(592,38)">
<text x="24" y="48" fill="#333" style="font-weight:bold">Mediocru — crossing în mijlocul range-ului (construit)</text>
<line x1="24" y1="56.0" x2="546" y2="56.0" stroke="#777" stroke-width="1.5" stroke-dasharray="4 3"/>
<line x1="24.0" y1="56.0" x2="546" y2="56.0" stroke="#777" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="532" y="50.0" fill="#777" text-anchor="end">range 110.00</text>
<line x1="24" y1="396.0" x2="546" y2="396.0" stroke="#777" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30" y="390.0" fill="#777">range 100.00</text>
<line x1="24" y1="294.0" x2="546" y2="294.0" stroke="#c00" stroke-width="1.5" stroke-dasharray="4 3"/>
<line x1="24.0" y1="396.0" x2="546" y2="396.0" stroke="#777" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30.0" y="390.0" fill="#777">range 100.00</text>
<line x1="24.0" y1="294.0" x2="546" y2="294.0" stroke="#c00" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="532" y="288.0" fill="#c00" text-anchor="end">SL 103.00</text>
<line x1="24" y1="226.0" x2="546" y2="226.0" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="4 3"/>
<line x1="24.0" y1="226.0" x2="546" y2="226.0" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="532" y="220.0" fill="#188a3e" text-anchor="end">intrare 105.00</text>
<line x1="24" y1="158.0" x2="546" y2="158.0" stroke="#1a5fb4" stroke-width="1.5" stroke-dasharray="4 3"/>
<line x1="24.0" y1="158.0" x2="546" y2="158.0" stroke="#1a5fb4" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="532" y="152.0" fill="#1a5fb4" text-anchor="end">TP1 107.00</text>
<line x1="44.0" y1="368.8" x2="44.0" y2="389.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="39.5" y="379.0" width="9" height="1.6" fill="#188a3e"/>
@@ -216,6 +216,6 @@
<rect x="429.5" y="440.7" width="9" height="45.3" fill="#188a3e" opacity="0.55"/>
<rect x="444.5" y="438.0" width="9" height="48.0" fill="#188a3e" opacity="0.55"/>
<text x="24" y="416.0" fill="#555">volum</text>
<text x="149.0" y="201.8" fill="#188a3e" text-anchor="middle" style="font-weight:bold">crossing (mijloc)</text>
<text x="99.0" y="201.8" fill="#188a3e" text-anchor="middle" style="font-weight:bold">crossing (mijloc)</text>
<text x="24" y="516" fill="#555">exemplu construit, nu date reale — SL nu stă pe niciun pivot</text>
</g><text x="580" y="650" fill="#555" text-anchor="middle">Legendă: ce separă cele două sunt nivelurile independente dedesubte (suport quarterly + double bottom + neckline),</text><text x="580" y="668" fill="#555" text-anchor="middle">nu un filtru pus în scaner. Panoul din dreapta e exemplu construit, nu date reale.</text><text x="580" y="686" fill="#555" text-anchor="middle">Cifrele A+ sunt din material; trimiterile stau în fișa de surse a capitolului.</text></svg>

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

@@ -15,6 +15,8 @@ from pathlib import Path
sys.path.insert(0, "/workspace/atm-curs-dl")
from svg_candles import Chart, Level, Mark, MA, from_closes # noqa: E402
sys.path.insert(0, "/workspace/atm-curs-dl/gen")
from eticheta_libera import eticheta_libera # noqa: E402
OUT = Path(__file__).resolve().parent / "mp2_exemplu.svg"
@@ -121,7 +123,9 @@ marks = [
Mark(SHL_I, "umăr stâng 566", "#1a1a1a", "below"),
Mark(HEAD_I, "head 555", "#1a1a1a", "below"),
Mark(SHR_I, "umăr drept 568", "#1a1a1a", "below"),
Mark(ENTRY_I, "intrare 577.00", "#188a3e", "above", dy=-10),
# dy/dx: la dy=-10 corpul verde de peste două candele mânca primul
# zecimal — pe ecran scria „intrare 577. 0" (02.10.2026)
Mark(ENTRY_I, "intrare 577.00", "#188a3e", "above", dy=-32, dx=-10),
]
ch = Chart(
@@ -137,6 +141,8 @@ ch = Chart(
svg = ch.render()
assert svg.count("\n\n") == 0, "linie goală în SVG — rupe markdown-ul"
# eticheta intrării poartă cifra: să nu mai ajungă peste un corp de candelă
eticheta_libera(svg, "exemplu", {"intrare 577.00"}, rects=True)
OUT.write_text(svg)
print(f"serie {len(cds)} candele | intrare {entry:.2f} @ {ENTRY_I} | "

View File

@@ -1,17 +1,17 @@
<svg viewBox="0 0 720 623" 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">SPY — daily</text>
<line x1="24" y1="56.0" x2="706" y2="56.0" stroke="#555" stroke-width="1.5" stroke-dasharray="4 3"/>
<line x1="24.0" y1="56.0" x2="706" y2="56.0" stroke="#555" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="692" y="50.0" fill="#555" text-anchor="end">ținta 4R era 667.00 (+16%)</text>
<line x1="24" y1="135.8" x2="706" y2="135.8" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30" y="129.8" fill="#188a3e">646.00 — +12% efectiv (~3R)</text>
<line x1="24" y1="312.1" x2="706" y2="312.1" stroke="#1a5fb4" stroke-width="1.5" stroke-dasharray="4 3"/>
<line x1="24.0" y1="135.8" x2="706" y2="135.8" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30.0" y="129.8" fill="#188a3e">646.00 — +12% efectiv (~3R)</text>
<line x1="24.0" y1="312.1" x2="706" y2="312.1" stroke="#1a5fb4" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="692" y="306.1" fill="#1a5fb4" text-anchor="end">TP1 599.60</text>
<line x1="24" y1="394.2" x2="706" y2="394.2" stroke="#1a5fb4" stroke-width="1.5" stroke-dasharray="4 3"/>
<line x1="24.0" y1="394.2" x2="706" y2="394.2" stroke="#1a5fb4" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="692" y="388.2" fill="#1a5fb4" text-anchor="end">neckline 578.00</text>
<line x1="24" y1="483.9" x2="706" y2="483.9" stroke="#c00" stroke-width="1.5" stroke-dasharray="4 3"/>
<line x1="24.0" y1="483.9" x2="706" y2="483.9" stroke="#c00" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="692" y="477.9" fill="#c00" text-anchor="end">SL 554.40</text>
<line x1="24" y1="485.4" x2="706" y2="485.4" stroke="#777" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30" y="479.4" fill="#777">suport quarterly 554.00</text>
<line x1="24.0" y1="485.4" x2="706" y2="485.4" stroke="#777" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30.0" y="479.4" fill="#777">suport quarterly 554.00</text>
<polyline points="329.0,389.7 344.0,397.1 359.0,402.6 374.0,405.6 389.0,410.1 404.0,414.4 419.0,416.4 434.0,418.1 449.0,417.9 464.0,416.1 479.0,415.6 494.0,412.8 509.0,408.1 524.0,401.4 539.0,393.2 554.0,384.6 569.0,375.9 584.0,363.9 599.0,348.9" fill="none" stroke="#b06000" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="605" y="343" fill="#b06000">SMA-20</text>
<line x1="44.0" y1="301.5" x2="44.0" y2="312.1" stroke="#1a1a1a" stroke-width="1.2"/>
@@ -133,6 +133,6 @@
<text x="239.0" y="461.7" fill="#1a1a1a" text-anchor="middle" style="font-weight:bold">umăr stâng 566</text>
<text x="329.0" y="499.4" fill="#1a1a1a" text-anchor="middle" style="font-weight:bold">head 555</text>
<text x="404.0" y="454.1" fill="#1a1a1a" text-anchor="middle" style="font-weight:bold">umăr drept 568</text>
<text x="419.0" y="375.3" fill="#188a3e" text-anchor="middle" style="font-weight:bold">intrare 577.00</text>
<text x="409.0" y="353.3" fill="#188a3e" text-anchor="middle" style="font-weight:bold">intrare 577.00</text>
<text x="24" y="611" fill="#555">Intrare 577.00 = prima verde după umărul drept (MP² long). 1R = 22.60; 646.00 ~3R, într-o lună.</text>
</svg>

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB