Files
atm-curs-dl/gen/radarscreen_subst.py
Claude Agent be53a64003 MODUL 5, lectia 1: RadarScreen si tranzactiile de 5 stele
Transcrierile 1 si 2 (extract_audio + transcribe pe MODUL 5, 7/7 lectii).
Sumarizarea lectiei 1: 14 diagrame, audit curat, generatoarele in gen/.

De reparat la verificare: eticheta TP1 119.53 da ca preturi ale cursului o
valoare derivata; cursul rosteste pivotul la 119 (transcrierea 01, linia 221).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ThN7ixZrowca8aTGrK1MUJ
2026-10-01 21:10:52 +00:00

194 lines
10 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Substituie marcatorii <!--SVG:nume--> din capitolul de RadarScreen.
Diagramele de candele vin din gen/radarscreen_5_stele.py (output JSON);
cele schematice (fără candele) sunt scrise aici.
Rulează: .venv/bin/python gen/radarscreen_subst.py /cale/rs.json
"""
import json
import re
import sys
SRC = "/workspace/atm-curs-dl/gen/radarscreen_5_stele.md.in" # textul cu marcatori
MD = "/workspace/atm-curs-dl/summaries/06_MODUL_5/01_radarscreen_5_stele.md"
COLS = [("SIMBOL", "WBD"), ("INTERVAL", "60 min"), ("LAST", "—"),
("OFF HIGH", "—"), ("NET CHG", "—"), ("RANGE", "122%"),
("RVOL", "167%"), ("TRINITY", "—"), ("TRIGGER", "bull rev")]
def rand_radar() -> str:
w, x0, cw = 640, 14, 68
parts = [f'<svg viewBox="0 0 {w} 232" xmlns="http://www.w3.org/2000/svg"'
' style="width:100%;height:auto;font:12px sans-serif">',
'<text x="14" y="22" fill="#333" style="font-weight:bold">'
'Un rând de RadarScreen = un grafic întreg, scris ca numere</text>']
for k, (head, val) in enumerate(COLS):
x = x0 + k * cw
parts.append(f'<rect x="{x}" y="36" width="{cw}" height="24" fill="#eef2f7"'
' stroke="#9bb0c7" stroke-width="1"/>')
parts.append(f'<text x="{x + 4}" y="52" fill="#44576e" font-size="10">{head}</text>')
parts.append(f'<rect x="{x}" y="60" width="{cw}" height="26" fill="#fff"'
' stroke="#9bb0c7" stroke-width="1"/>')
col = "#188a3e" if val in ("122%", "167%", "bull rev") else "#555"
parts.append(f'<text x="{x + 4}" y="78" fill="{col}" font-size="10">{val}</text>')
parts += [
'<path d="M 320 92 L 320 112" stroke="#1a5fb4" stroke-width="1.5"/>',
'<path d="M 316 106 L 320 114 L 324 106 Z" fill="#1a5fb4"/>',
'<text x="14" y="134" fill="#1a5fb4">Fiecare celulă e un calcul pe exact'
' aceleași date pe care le-ai citi pe chart:</text>',
'<text x="14" y="152" fill="#555">RANGE = înălțimea candelei față de media'
' ultimelor trei; RVOL = volumul ultimei bare față de media a 10;</text>',
'<text x="14" y="170" fill="#555">TRINITY = verdictul celor trei indicatori'
' proprii; TRIGGER = reversal, doji sau momentum pe candela curentă.</text>',
'<text x="14" y="194" fill="#666" font-size="11">Celulele cu „—" nu sunt'
' rostite în lecție pentru WBD: din el avem range 122%, RVol 167% și</text>',
'<text x="14" y="210" fill="#666" font-size="11">bull reversal, pe 60 de'
' minute. Așa citești 500 de companii fără să deschizi niciun grafic.</text>',
'</svg>']
return "\n ".join(parts)
LADDER = [("Trinity: volum + relative strength + power, toți în aceeași direcție",
"3 stele", "#188a3e"),
("+ un trigger: bull reversal, buy doji sau buy momentum", "4", "#188a3e"),
("+ locul: suport, pivot sau rezistență sub pragul de proximitate",
"5 stele", "#188a3e"),
("+ o divergență bull pe unul din indicatori", "„aproape 7”", "#1a5fb4")]
def trinity_stele() -> str:
parts = [f'<svg viewBox="0 0 640 {60 + 44 * len(LADDER) + 62}"'
' xmlns="http://www.w3.org/2000/svg"'
' style="width:100%;height:auto;font:12px sans-serif">',
'<text x="14" y="22" fill="#333" style="font-weight:bold">'
'Cum se adună stelele (numărătoarea e cea din curs)</text>']
for k, (txt, star, col) in enumerate(LADDER):
y = 40 + 44 * k
parts.append(f'<rect x="14" y="{y}" width="470" height="32" fill="#f7f9fb"'
' stroke="#9bb0c7" stroke-width="1"/>')
parts.append(f'<text x="22" y="{y + 21}" fill="#333" font-size="11">{txt}</text>')
parts.append(f'<rect x="496" y="{y}" width="130" height="32" fill="{col}"'
' fill-opacity="0.12" stroke="' + col + '" stroke-width="1"/>')
parts.append(f'<text x="561" y="{y + 21}" fill="{col}" text-anchor="middle"'
f' style="font-weight:bold">{star}</text>')
y = 40 + 44 * len(LADDER) + 18
parts.append(f'<text x="14" y="{y}" fill="#666" font-size="11">Cursul nu dă un'
' barem fix: fiecare confirmare în plus, pe aceeași candelă și în'
' aceeași direcție,</text>')
parts.append(f'<text x="14" y="{y + 16}" fill="#666" font-size="11">crește'
' probabilitatea.</text>')
parts.append('</svg>')
return "\n ".join(parts)
ROWS = [("volum (indicatorul propriu)", "A+ / A− / D+ / D−",
"candele peste/sub 0", "1 (cel mai important)"),
("relative strength", "cadranul 1-4", "candele în cadran", "2"),
("power", "cadranul 1-4", "candele în cadran", "3 (reacționează primul)")]
READ = [("AAPL — 3 stele", "relative strength în cadranul 2 (se îmbunătățește)",
"power în cadranul 1", "volum A− (sub 0, dar în acumulare, 29 de candele)",
"#188a3e"),
("ABV — 3 stele cu minus", "relative strength în cadranul 3 (se înrăutățește)",
"power în cadranul 4", "volum D− (sub 0 și în distribuție)", "#c00")]
def trinity_stele_detaliu() -> str:
parts = ['<svg viewBox="0 0 640 348" xmlns="http://www.w3.org/2000/svg"'
' style="width:100%;height:auto;font:12px sans-serif">',
'<text x="14" y="22" fill="#333" style="font-weight:bold">Cele șase'
' coloane Trinity: pentru fiecare indicator, starea și vechimea'
' ei</text>',
'<text x="22" y="46" fill="#44576e" font-size="10">INDICATOR</text>',
'<text x="212" y="46" fill="#44576e" font-size="10">COLOANA 1 — starea</text>',
'<text x="332" y="46" fill="#44576e" font-size="10">COLOANA 2 — vechimea</text>',
'<text x="480" y="46" fill="#44576e" font-size="10">IMPORTANȚA</text>',
'<line x1="14" y1="52" x2="626" y2="52" stroke="#9bb0c7" stroke-width="1"/>']
for k, (name, c1, c2, imp) in enumerate(ROWS):
y = 74 + 30 * k
parts.append(f'<text x="22" y="{y}" fill="#333" font-size="11">{name}</text>')
parts.append(f'<text x="212" y="{y}" fill="#1a5fb4" font-size="11">{c1}</text>')
parts.append(f'<text x="332" y="{y}" fill="#555" font-size="10">{c2}</text>')
parts.append(f'<text x="480" y="{y}" fill="#b06000" font-size="10">{imp}</text>')
parts.append('<text x="14" y="186" fill="#333" style="font-weight:bold">'
'Cele două citiri din lecție</text>')
for k, (title, a, b, c, col) in enumerate(READ):
y = 200 + 66 * k
parts.append(f'<rect x="14" y="{y}" width="612" height="56" fill="{col}"'
f' fill-opacity="0.07" stroke="{col}" stroke-width="1"/>')
parts.append(f'<text x="24" y="{y + 18}" fill="{col}"'
f' style="font-weight:bold">{title}</text>')
parts.append(f'<text x="24" y="{y + 36}" fill="#333" font-size="11">{a}</text>')
parts.append(f'<text x="330" y="{y + 36}" fill="#333" font-size="11">{b}</text>')
parts.append(f'<text x="24" y="{y + 50}" fill="#333" font-size="11">{c}</text>')
parts.append('<text x="14" y="342" fill="#666" font-size="11">Trinity numără'
' direcția, nu semnul: la AAPL volumul e negativ, dar în urcare —'
' tot stea e.</text>')
parts.append('</svg>')
return "\n ".join(parts)
def pivot_culori() -> str:
"""Două panouri: preț deasupra pivotului (verde) și sub pivot (roșu)."""
parts = ['<svg viewBox="0 0 640 262" xmlns="http://www.w3.org/2000/svg"'
' style="width:100%;height:auto;font:12px sans-serif">',
'<text x="14" y="22" fill="#333" style="font-weight:bold">Ce spune'
' culoarea de pe coloana de pivot</text>']
for k, (lab, col, py, dy) in enumerate([("preț DEASUPRA pivotului", "#188a3e", 120, -50),
("preț SUB pivot", "#c00", 120, 34)]):
x = 20 + k * 312
parts.append(f'<rect x="{x}" y="40" width="288" height="150" fill="#f7f9fb"'
' stroke="#9bb0c7" stroke-width="1"/>')
parts.append(f'<text x="{x + 10}" y="60" fill="{col}"'
f' style="font-weight:bold">{lab}</text>')
parts.append(f'<rect x="{x + 10}" y="{py - 14}" width="268" height="28"'
' fill="#1a5fb4" fill-opacity="0.08"/>')
parts.append(f'<line x1="{x + 10}" y1="{py}" x2="{x + 278}" y2="{py}"'
' stroke="#1a5fb4" stroke-width="1.5" stroke-dasharray="4 3"/>')
parts.append(f'<text x="{x + 14}" y="{py - 22}" fill="#1a5fb4"'
' font-size="10">pivot + banda de proximitate</text>')
parts.append(f'<circle cx="{x + 60}" cy="{py + dy}" r="5" fill="{col}"/>')
parts.append(f'<text x="{x + 72}" y="{py + dy + 4}" fill="{col}"'
' font-size="11">ultimul preț</text>')
txt = ("coloana e verde: „destul de strong bull”" if k == 0
else "coloana e roșie: „cam strong bear”")
parts.append(f'<text x="{x + 10}" y="182" fill="#333" font-size="11">{txt}</text>')
parts += ['<text x="14" y="212" fill="#333">Banda de proximitate: 0,5%'
' intraday, 2% pe daily. Fond alb cu cifră colorată = ești în'
' bandă.</text>',
'<text x="14" y="232" fill="#666" font-size="11">Coloana RR spune,'
' separat, dacă stai lângă suport (valoare mare) sau lângă'
' rezistență (valoare mică).</text>',
'</svg>']
return "\n ".join(parts)
HAND = {"rand_radar": rand_radar, "trinity_stele": trinity_stele,
"trinity_stele_detaliu": trinity_stele_detaliu,
"pivot_culori": pivot_culori}
def main() -> None:
charts = json.load(open(sys.argv[1], encoding="utf-8"))
md = open(SRC, encoding="utf-8").read()
missing = []
def sub(m: re.Match) -> str:
name = m.group(1)
if name in charts:
return charts[name]
if name in HAND:
return HAND[name]()
missing.append(name)
return m.group(0)
out = re.sub(r"<!--SVG:([a-z_0-9]+)-->", sub, md)
assert not missing, f"marcatori fără diagramă: {missing}"
n_used = len(re.findall(r"<svg ", out))
open(MD, "w", encoding="utf-8").write(out)
print(f"{n_used} diagrame lipite în {MD}")
if __name__ == "__main__":
main()