Files
atm-curs-dl/gen/strategii/intrarea_retest_ratat.py
Claude Agent 20b4b96e1a strategii: verificarea anexei A3 si reparatiile ei
Un verificator separat de graficieni. Cinci probleme, toate reale; citatele
de la 1, 2 si 4 verificate de mine, cuvant cu cuvant, in transcrieri.

1. „1 pe 3" nu mai e o intrebare deschisa. Inseamna amandoua lucrurile
   deodata: o treime din pozitie la close, apoi cate o treime la nivelul de
   1/3 si la cel de 1/2 din candela (`19_08092025.txt:1067-1073`). Asta
   atenueaza si contradictia cu sumarul QA — la close intri partial.
2. La buy doji cu transe stopul e rostit: sub low-ul doji-ului, nu low-ul a
   4 candele (`90_13042026.txt:182`). Punctul 5 din neconfirmate se ingusteaza.
3. Fereastra de 3 candele e doar a lui buy doji; M2D n-are doji.
4. Cifrele XLE erau atribuite peste sursa: „de la low" nu e rostit, si nu
   reiese care cifra, 3,16 sau 2,98, merge cu care masuratoare. Iar `:192`
   sustinea o idee pe care n-o spune.
5. Eticheta „+1.7R" presupunea ca tii toata pozitia, desi acelasi document
   da TP1 la 1:1 cu transe. Reparata in generator, nu in SVG.

Randul din tabelul 1.4 („intri la close") ramasese orfan dupa 1; l-am
completat eu.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ThN7ixZrowca8aTGrK1MUJ
2026-09-19 17:35:56 +00:00

132 lines
6.3 KiB
Python

"""Diagrama din `gen/strategii/intrarea_retest_ratat.spec.txt` (TIP: PRET).
Pereche pentru `intrarea_doua_variante`: aceeași serie până la candela de
semnal inclusiv (0-15), apoi prețul nu mai coboară în corpul ei. Ordinele de
la 1/2 și 1/3 rămân neumplute, varianta A merge la +1.7R (dacă ții toată poziția), varianta B n-are
poziție. Seria e construită (fără ticker), nu un trade din curs.
"""
import re
import sys
from pathlib import Path
sys.path.insert(0, "/workspace/atm-curs-dl")
from svg_candles import Chart, Level, Mark, from_closes # noqa: E402
OUT = Path(__file__).resolve().parent / "intrarea_retest_ratat.svg"
GREEN, RED, ORANGE, GREY = "#188a3e", "#c00", "#b06000", "#777"
# ── 0-15: copiate din intrarea_doua_variante.spec.txt (aceeași serie) ───────
CLOSES_0_15 = [103.60, 103.35, 103.45, 103.10, 102.80, 102.90, 102.50, 102.20,
101.85, 101.95, 101.50, 101.10, # downtrend spre suport
100.60, 100.40, 100.35, # la suport
102.15] # candela de semnal
WICKS_0_15 = [(0.15, 0.15)] * 16
# 12-14 la suport: aceleași fitiluri ca în intrarea_doua_variante.py
WICKS_0_15[12] = (0.10, 0.15)
WICKS_0_15[13] = (0.10, 0.50) # low 99.90 (wick sub suportul de 100.00)
WICKS_0_15[14] = (0.10, 0.15)
WICKS_0_15[15] = (0.15, 0.10) # semnal: high 102.30, low 100.25
START = 103.80 # open-ul candelei 0
# ── 16-31: plecare fără pullback adânc ──────────────────────────────────────
CLOSES_16_31 = [102.40, 102.70, 102.55, 102.95, 103.30, 103.20, 103.60, 104.00,
103.85, 104.30, 104.70, 104.60, 105.10, 105.40, 105.30, 106.00]
WICKS_16_31 = [(0.15, 0.15)] * 16
WICKS_16_31[0] = (0.15, 0.25) # low-ul candelei 16 = 101.90
cds = from_closes(CLOSES_0_15 + CLOSES_16_31, wicks=WICKS_0_15 + WICKS_16_31,
start=START)
SL, SIG = 99.90, 15
sig = cds[SIG]
half = (sig.o + sig.c) / 2
third = sig.c - (sig.c - sig.o) / 3
entry_a = sig.c
low_after = min(c.l for c in cds[SIG + 1:])
r_a = (cds[31].c - entry_a) / (entry_a - SL)
# ── assert-urile din specificație ───────────────────────────────────────────
assert len(cds) == 32
# 1. open == close-ul barei anterioare
assert all(abs(cds[i].o - cds[i - 1].c) < 1e-9 for i in range(1, len(cds)))
# 2. 0-15 identice cu intrarea_doua_variante (lista e copiată din spec-ul ei)
assert abs(sig.o - 100.35) < 1e-9 and abs(sig.c - 102.15) < 1e-9
assert abs(sig.h - 102.30) < 1e-9 and abs(sig.l - 100.25) < 1e-9
assert abs(cds[13].l - 99.90) < 1e-9
assert abs(min(c.l for c in cds[11:15]) - SL) < 1e-9 and sig.l > SL
assert all(c.l > SL for i, c in enumerate(cds[11:15], 11) if i != 13)
assert abs(half - 101.25) < 1e-9 and abs(third - 101.55) < 1e-9
# 3. niciun ordin nu se umple
assert low_after > 101.55, low_after
assert abs(cds[16].l - 101.90) < 1e-9 and low_after >= 101.80
assert abs(low_after - 101.90) < 1e-9 # „cel mai jos după semnal" e chiar candela 16
# 4. finalul și R-ul
assert abs(cds[31].c - 106.00) < 1e-9
assert round(r_a, 2) == 1.71, r_a
R_TEXT = f"+{r_a:.1f}R"
assert R_TEXT == "+1.7R"
# 5. candela 23 și niciun „suport" inventat în 17-23
assert abs(cds[23].c - 104.00) < 1e-9
MARKED = [SL, half, third, entry_a]
assert not any(abs(c.l - p) < 1e-6 for c in cds[17:24] for p in MARKED)
levels = [
Level(SL, "SL 99.90", RED, dash=""),
Level(third, f"ordin 1/3 {third:.2f} — neumplut", ORANGE),
Level(half, f"ordin 1/2 {half:.2f} — neumplut", ORANGE),
Level(entry_a, f"A: close {entry_a:.2f}", GREEN),
]
marks = [
Mark(SIG, "semnal", GREEN, "above"),
# dy=-16: textul stă chiar la înălțimea low-ului, între eticheta 1/3 și linia A
Mark(16, f"cel mai jos după semnal: {low_after:.2f}", GREY, "below", dy=-16),
Mark(23, "NU muți ordinul aici: sub 104.00 nu e niciun nivel", RED, "above"),
Mark(31, f"A: {R_TEXT} dacă ții toată poziția · B: 0 (fără poziție)", GREY, "above"),
]
CAPTION = ["Exemplu construit, fără ticker. «Poate să nu mai facă, poate nu mai face niciodată.»",
"Ai ratat trade-ul; aștepți următoarea structură."]
ch = Chart(
candles=cds, levels=levels, marks=marks,
scale=80.0, width=660, gap=16, body_w=9, left=40,
title="Exemplu construit (fără ticker) — 15 min", caption=CAPTION[0],
)
svg = ch.render()
def reanchor(svg, text, anchor, dx):
"""Mark-urile ies centrate; unele trebuie să curgă într-o parte, unde e loc
liber (stânga lui 15: candelele 13-14 sunt jos; dreapta lui 16: toate low-urile
>= 102.25; stânga lui 23: toate high-urile < 104.00)."""
pat = re.compile(r'<text x="([\d.]+)"( y="[\d.]+" fill="[^"]+") text-anchor="middle"'
r'( style="font-weight:bold">' + re.escape(text) + '</text>)')
svg, n = pat.subn(lambda m: f'<text x="{float(m[1]) + dx:.1f}"{m[2]} '
f'text-anchor="{anchor}"{m[3]}', svg)
assert n == 1, text
return svg
svg = reanchor(svg, marks[0].text, "end", 5)
svg = reanchor(svg, marks[1].text, "start", 8)
svg = reanchor(svg, marks[2].text, "end", 6)
# eticheta lui 31 e prea lungă pe un rând: ar trece peste titlu. O rupem în
# două, al doilea rând la locul mark-ului, primul cu 15 px mai sus.
svg = reanchor(svg, marks[3].text, "end", 6)
m = re.search(r'<text x="([\d.]+)" y="([\d.]+)"([^>]*)>' + re.escape(marks[3].text) + '</text>', svg)
assert m
r1, r2 = marks[3].text.split(" · ")
svg = svg.replace(m[0], f'<text x="{m[1]}" y="{float(m[2]) - 15:.1f}"{m[3]}>{r1}</text>\n'
f' <text x="{m[1]}" y="{m[2]}"{m[3]}>{r2}</text>')
# legenda pe două rânduri: pe unul singur trece de lățimea de 660
m = re.search(r'<text x="24" y="([\d.]+)" fill="#555">' + re.escape(CAPTION[0]) + '</text>', svg)
assert m
y2 = float(m[1]) + 17
svg = svg.replace(m[0], m[0] + f'\n <text x="24" y="{y2:.0f}" fill="#555">{CAPTION[1]}</text>')
vb = re.search(r'viewBox="0 0 660 ([\d.]+)"', svg)
assert vb
svg = svg.replace(vb[0], f'viewBox="0 0 660 {float(vb[1]) + 17:.0f}"')
assert svg.count("\n\n") == 0, "linie goală în SVG — rupe markdown-ul"
OUT.write_text(svg)
print(f"low după semnal {low_after:.2f} | A {R_TEXT} ({r_a:.4f}) | scris {OUT}")