buy_doji: refacut ca tutorial pe 3 niveluri, cu diagrame adnotate

Userul a respins mostra de format tutorial: prea lunga, prea multe
trimiteri in text, termeni tehnici nedefiniti, prea multe cifre fara
desen. Cerintele lui sunt acum contract in STYLE.md (FORMAT TUTORIAL v2).

Textul: 8430 -> 4190 de cuvinte. Nivel 1 (din avion, cu mini-glosar) ->
nivel 2 (6 pasi mecanici, o diagrama fiecare) -> oglinda short -> nivel 3
(rafinari). Trimiterile fisier:linie ies din corp si se aduna la final,
cu legenda de prescurtari. Doua tabele in tot documentul.

Toate cele 14 diagrame refacute: zone dreptunghiulare de evidentiere si
sageti care spun si de ce, nu doar ce. svg_candles primeste Zone si
Arrow; render() nu mai muta obiectul la iesire.

Trei corecturi de continut:
- un singur trade prin toata procedura (doji 50.10/49.25, intrare 50.40,
  stop 49.20, 1R 1.20, TP1 51.60); seria e acum o functie comuna,
  importata de stop/transe/iesire
- short: stopul urca la 100.15, ca sa fie deasupra maximului cum cere
  regula oglindita; cifra cursului ramane in text ca observatie
- LABU: trei minime dar doua atingeri ale pivotului 86.00, ceea ce
  impaca "triple bottom" cu "al doilea test", ambele din transcriere

Reparat si bug-ul vechi din buy_doji_sell.svg: titlul peste eticheta
dojiului.

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-19 21:09:31 +00:00
parent aff03870e8
commit 8b7b5f6b44
50 changed files with 7011 additions and 6921 deletions

View File

@@ -27,24 +27,21 @@ WIDTHS = [300, 280, 260, 240, 220, 200]
# (linii în cutie, [(tip, text)]); tip: "n" = notă gri, "c" = capcană
BOXES = [
(["Univers:", "All Stocks (~13.000)", "S&P 500 · Russell 3000"],
[("n", "mai mare = găsește mai mult, durează mai mult")]),
[("n", "mai mare = mai mulți candidați, scanare mai lentă")]),
(["Trigger: jbtgrshdATM", "BDATM = 0", "(Sell Doji: SDATM = 0)"],
[("c", "Interval = TF-ul scanerului, setat manual"),
("c", "0 = ultima candelă închisă; 1 = cu o zi în urmă")]),
[("c", "intervalul nu se aliniază singur cu TF-ul: îl pui de mână"),
("c", "vede doar candela închisă: daily rulat la prânz arată ieri")]),
(["Nivel: RSV1ATM", "% of PP ≤ 0.5 (60 min)", "% of PP ≤ 2 (daily)"],
[("n", "Pivot Interval: 2 = weekly (pe 60 min), 3 = monthly (pe daily)"),
("c", "RS/SR = 1 la filtrare; cu 100, pragul se scrie ×100")]),
("c", "RS/SR: 1 la filtrare, 100 doar la afișare")]),
(["Lichiditate: Volume Colors", "Average Volume ≥ 500.000",
"Average Length = 10"],
[("n", "volum daily, indiferent de TF-ul scanerului")]),
(["Opțional:", "Since Bear ≥ 8", "Bull Reversal = 1", "RVOL doar Display"],
[("c", "Bear Reversal e selectat implicit — comută pe Bull"),
("c", "în zile extreme, pragurile rigide golesc lista")]),
[("c", "pornește pe Bear Reversal: comută pe Bull")]),
(["Lista de candidați", "→ o verifici pe grafic", "(pașii 2-6).",
"Scanerul nu e undă verde."], []),
]
FOOT = ("Delay: scanerul vede candela închisă — daily rulat la 12:00 "
"arată triggerul de ieri.")
def est_w(s, fs, bold=False):
@@ -94,10 +91,18 @@ for i, (lines, notes) in enumerate(BOXES):
assert x0 >= x + 6 and x1 <= x + w - 6, f"textul nu încape în cutia {i}: {ln!r}"
if note_lines:
assert x + w + 24 <= NOTE_X, f"cutia {i} prea aproape de note"
svg.append(f'<line x1="{x + w + 4:g}" y1="{y + h / 2:g}" x2="{NOTE_X - 8}" '
f'y2="{y + h / 2:g}" stroke="#bbbbbb" stroke-dasharray="3 3"/>')
ny = y + (h - n_note * LH) / 2 + 12
for group in note_lines:
kind0 = group[0][0]
cy = ny - 4
# capcana arată spre filtrul pe care îl strică (vârful pe cutie)
col = RED if kind0 == "c" else "#bbbbbb"
dash = '' if kind0 == "c" else ' stroke-dasharray="3 3"'
svg.append(f'<line x1="{NOTE_X - 10}" y1="{cy:g}" x2="{x + w + 12:g}" y2="{cy:g}" '
f'stroke="{col}" stroke-width="{1.6 if kind0 == "c" else 1}"{dash}/>')
if kind0 == "c":
svg.append(f'<path d="M {x + w + 4:g} {cy:g} L {x + w + 13:g} {cy - 4:g} '
f'L {x + w + 13:g} {cy + 4:g} Z" fill="{RED}"/>')
for kind, ln in group:
put(NOTE_X, ny, ln, NOTE_FS, RED if kind == "c" else GRAY)
ny += LH
@@ -108,10 +113,7 @@ for i, (lines, notes) in enumerate(BOXES):
f'L {BOX_CX} {y + 14:g} Z" fill="{BLUE}"/>')
y += 18
y += 30
for j, ln in enumerate(textwrap.wrap(FOOT, 88)):
put(20, y + j * LH, ln, 12.5, BLACK)
H = int(y + LH + 20)
H = int(y + 20)
# ------------------------------------------------------------------ verificare
assert all(a > b for a, b in zip(WIDTHS, WIDTHS[1:])), "lățimile nu scad strict"
@@ -133,6 +135,7 @@ out = "\n".join([
f'ordinea filtrelor și capcanele">',
f'<rect x="0" y="0" width="{W}" height="{H}" fill="#ffffff"/>',
*svg, "</svg>"]) + "\n"
assert ".md:" not in out and "Surse" not in out, "trimiteri la surse în SVG"
assert "\n\n" not in out and not any(not ln.strip() for ln in out.splitlines()), "linie goală"
OUT.write_text(out, encoding="utf-8")
print(f"scris {OUT} ({W}x{H}), verificare OK")