"""Diagramele pentru summaries/06_MODUL_5/01_radarscreen_5_stele.md. Rulează: .venv/bin/python gen/radarscreen_5_stele.py out.json Scrie un dict nume -> SVG, care se substituie în markdown peste marcatorii ``. Vezi STYLE.md, „Cum trebuie să arate un grafic de preț". """ import json import sys sys.path.insert(0, "/workspace/atm-curs-dl") from svg_candles import MA, Arrow, Chart, Level, Mark, Zone, from_closes CH = {} COMMON = dict(gap=16, body_w=10, width=640, left=44) # ---------------------------------------------------------------- bull reversal # scădere de 27 de candele, apoi o candelă care închide peste high-ul precedentei BR = [100.0, 99.4, 98.7, 99.1, 98.2, 97.5, 96.9, 97.2, 96.3, 95.6, 95.9, 95.0, 94.4, 94.8, 93.9, 93.2, 92.8, 93.1, 92.4, 91.8, 91.5, 92.0, 91.3, 90.9, 91.4, 90.8, 91.1] BRW = [(0.30, 0.30)] * 27 BRV = [44, 41, 38, 35, 46, 42, 39, 34, 43, 40, 36, 45, 41, 36, 47, 43, 38, 35, 44, 48, 42, 37, 45, 41, 36, 43, 39] cds = from_closes(BR + [92.60], wicks=BRW + [(0.25, 0.20)], vols=BRV + [78], start=100.6) prev, last = cds[-2], cds[-1] assert last.c > prev.h, (last.c, prev.h) # definiția bull reversal-ului assert abs(prev.h - 91.40) < 0.001, prev.h CH["bull_rev_da"] = Chart( candles=cds, levels=[Level(prev.h, f"high-ul candelei precedente {prev.h:.2f}", "#b06000", label_at="left")], arrows=[Arrow(27, f"DA — close {last.c:.2f}, peste {prev.h:.2f}:\n" "RadarScreen aprinde Bull Reversal", color="#188a3e", where="above", dx=-104)], mas=[MA(20, "#b06000", dash="4 3", text="SMA-20")], **COMMON, scale=26, vol_h=70, vol_label="volum", title="Exemplu construit (fără ticker) — 60 de minute", caption="Bull reversal = prima candelă care închide peste high-ul precedentei." " Serie construită de mine.").render() cds = from_closes(BR + [91.30], wicks=BRW + [(0.25, 0.20)], vols=BRV + [40], start=100.6) prev, last = cds[-2], cds[-1] assert prev.c < last.c < prev.h, (prev.c, last.c, prev.h) CH["bull_rev_nu"] = Chart( candles=cds, levels=[Level(prev.h, f"high-ul candelei precedente {prev.h:.2f}", "#b06000", label_at="left")], arrows=[Arrow(27, f"NU — close {last.c:.2f}, verde,\ndar sub {prev.h:.2f}:" " coloana rămâne stinsă", color="#c00", where="below", dx=-96)], mas=[MA(20, "#b06000", dash="4 3", text="SMA-20")], **COMMON, scale=26, vol_h=70, vol_label="volum", title="Exemplu construit (fără ticker) — 60 de minute", caption="Aceeași serie, alt close: o candelă verde sub high-ul precedent nu e" " bull reversal.").render() # ---------------------------------------------------------------- bear reversal UP = [100.0, 100.6, 101.3, 100.9, 101.8, 102.5, 103.1, 102.8, 103.7, 104.4, 104.1, 105.0, 105.6, 105.2, 106.1, 106.8, 107.2, 106.9, 107.6, 108.2, 108.5, 108.0, 108.7, 109.1, 108.6, 109.2, 108.9] UPW = [(0.30, 0.30)] * 27 UPV = [40, 43, 46, 36, 44, 47, 42, 35, 45, 48, 38, 46, 43, 36, 47, 44, 39, 35, 43, 46, 41, 37, 44, 42, 36, 41, 38] cds = from_closes(UP + [108.30], wicks=UPW + [(0.20, 0.25)], vols=UPV + [80], start=99.4) prev, last = cds[-2], cds[-1] assert last.c < prev.l, (last.c, prev.l) assert abs(prev.l - 108.60) < 0.001, prev.l CH["bear_rev"] = Chart( candles=cds, levels=[Level(prev.l, f"low-ul candelei precedente {prev.l:.2f}", "#b06000", label_at="left")], arrows=[Arrow(27, f"DA — close {last.c:.2f}, sub {prev.l:.2f}:\n" "RadarScreen aprinde Bear Reversal", color="#c00", where="below", dx=-104)], mas=[MA(20, "#b06000", dash="4 3", text="SMA-20")], **COMMON, scale=26, vol_h=70, vol_label="volum", title="Exemplu construit (fără ticker) — 60 de minute", caption="Bear reversal = prima închidere sub low-ul precedentei. Serie" " construită de mine.").render() # -------------------------------------------------------------------- buy doji DJ = [104.0, 103.4, 102.7, 103.1, 102.2, 101.5, 100.9, 101.2, 100.3, 99.6, 99.9, 99.0, 98.4, 98.8, 97.9, 97.2, 96.8, 97.1, 96.4, 95.8, 95.5, 96.0, 95.3, 95.35] # 95.30 -> 95.35 = doji DJW = [(0.30, 0.30)] * 23 + [(0.35, 0.55)] DJV = [44, 41, 38, 35, 46, 42, 39, 34, 43, 40, 36, 45, 41, 36, 47, 43, 38, 35, 44, 48, 42, 37, 45, 52] cds = from_closes(DJ + [96.40, 96.90], wicks=DJW + [(0.25, 0.25), (0.25, 0.25)], vols=DJV + [71, 64], start=104.6) doji, trig = cds[23], cds[24] assert abs(doji.c - doji.o) <= 0.10 * (doji.h - doji.l), (doji.o, doji.c) assert trig.c > doji.h, (trig.c, doji.h) assert abs(doji.h - 95.70) < 0.001, doji.h CH["buy_doji"] = Chart( candles=cds, levels=[Level(95.00, "suport 95.00", "#1a5fb4", label_at="left"), Level(doji.h, f"high-ul doji-ului {doji.h:.2f}", "#b06000")], arrows=[Arrow(23, "buy doji: open ≈ close, pe suport —\n" "aici se aprinde coloana HDTR", color="#188a3e", where="below", dx=-96), Arrow(24, f"confirmarea: close {trig.c:.2f},\npeste high-ul doji-ului", color="#188a3e", where="above", dx=-74)], mas=[MA(20, "#b06000", dash="4 3", text="SMA-20")], **COMMON, scale=24, vol_h=70, vol_label="volum", title="Exemplu construit (fără ticker) — 60 de minute", caption="Coloana HDTR se aprinde pe doji; intrarea cere încă o candelă. Serie" " construită de mine.").render() # ------------------------------------------------------------------- sell doji SD = [96.0, 96.6, 97.3, 96.9, 97.8, 98.5, 99.1, 98.8, 99.7, 100.4, 100.1, 101.0, 101.6, 101.2, 102.1, 102.8, 103.2, 102.9, 103.6, 104.2, 104.5, 104.0, 104.7, 104.65] # 104.70 -> 104.65 = doji SDW = [(0.30, 0.30)] * 23 + [(0.55, 0.35)] cds = from_closes(SD + [103.60, 103.10], wicks=SDW + [(0.25, 0.25), (0.25, 0.25)], vols=DJV + [74, 66], start=95.4) doji, trig = cds[23], cds[24] assert abs(doji.c - doji.o) <= 0.10 * (doji.h - doji.l), (doji.o, doji.c) assert trig.c < doji.l, (trig.c, doji.l) assert abs(doji.l - 104.30) < 0.001, doji.l CH["sell_doji"] = Chart( candles=cds, levels=[Level(105.00, "rezistență 105.00", "#1a5fb4"), Level(doji.l, f"low-ul doji-ului {doji.l:.2f}", "#b06000")], arrows=[Arrow(23, "sell doji: open ≈ close, sub rezistență —\n" "coloana HDTR se aprinde roșu", color="#c00", where="above", dx=-110), Arrow(24, f"confirmarea: close {trig.c:.2f},\nsub low-ul doji-ului", color="#c00", where="below", dx=-30)], mas=[MA(20, "#b06000", dash="4 3", text="SMA-20")], **COMMON, scale=24, vol_h=70, vol_label="volum", title="Exemplu construit (fără ticker) — 60 de minute", caption="Oglinda pe short: trigger pe închiderea sub low-ul doji-ului. Serie" " construită de mine.").render() # ------------------------------------------------------- buy / sell momentum MM = [98.0, 97.4, 96.8, 97.1, 96.2, 95.6, 95.9, 95.1, 94.6, 94.9, 94.2, 93.7, 94.0, 93.4, 93.8, 93.2, 93.6, 94.1, 94.0, 94.6, 96.30, 96.9, 97.6, 97.4, 98.3, 99.0, 99.6, 100.4] MMW = [(0.30, 0.30)] * 20 + [(0.30, 0.25)] + [(0.30, 0.30)] * 7 MMV = [42, 39, 36, 33, 44, 40, 35, 43, 38, 34, 41, 37, 33, 42, 38, 34, 40, 44, 39, 46, 92, 74, 68, 55, 62, 58, 54, 60] cds = from_closes(MM, wicks=MMW, vols=MMV, start=98.6) brk = cds[20] assert brk.c > 95.90, brk.c # trece peste nivelul vechi assert min(c.l for c in cds[10:20]) < 93.00 CH["buy_momentum"] = Chart( candles=cds, levels=[Level(95.90, "nivel vechi 95.90", "#1a5fb4")], zones=[Zone(20, 27, "trend ascendent: 8 candele (coloana Trend numără)", "#188a3e")], arrows=[Arrow(20, f"buy momentum (săgeată verde):\nclose {brk.c:.2f}, cu forță" " peste 95.90", color="#188a3e", where="below", dx=22)], mas=[MA(10, "#b06000", dash="4 3", text="SMA-10")], **COMMON, scale=22, vol_h=70, vol_label="volum", title="Exemplu construit (fără ticker) — 60 de minute", caption="Pe candela de buy momentum clipocesc trei coloane: MTGR, Trend și" " numărul de candele.").render() SM = [100.0, 100.6, 101.2, 100.9, 101.8, 102.4, 102.1, 102.9, 103.4, 103.1, 103.8, 104.3, 104.0, 104.6, 104.2, 104.8, 104.4, 103.9, 104.0, 103.4, 101.70, 101.1, 100.4, 100.6, 99.7, 99.0, 98.4, 97.6] cds = from_closes(SM, wicks=[(0.30, 0.30)] * 20 + [(0.25, 0.30)] + [(0.30, 0.30)] * 7, vols=MMV, start=99.4) brk = cds[20] assert brk.c < 102.10, brk.c CH["sell_momentum"] = Chart( candles=cds, levels=[Level(102.10, "nivel vechi 102.10", "#1a5fb4")], zones=[Zone(20, 27, "trend descendent: 8 candele", "#c00")], arrows=[Arrow(20, f"sell momentum (săgeată galbenă):\nclose {brk.c:.2f}, rupe" " 102.10 în jos", color="#c00", where="above", dx=26)], mas=[MA(10, "#b06000", dash="4 3", text="SMA-10")], **COMMON, scale=22, vol_h=70, vol_label="volum", title="Exemplu construit (fără ticker) — 60 de minute", caption="Oglinda: săgeată galbenă pe MTGR, trend-ul trece în descendent. Serie" " a mea.").render() # ------------------------------------------------------------- range + RVol RG = [60.0, 59.4, 58.7, 59.2, 58.3, 57.6, 58.1, 57.2, 56.6, 57.0, 56.2, 55.6, 56.0, 55.2, 55.7, 54.9, 54.3, 54.8, 54.0, 54.5, 53.8, 54.3, 53.6, 54.1, 53.9, 54.4, 53.3] RGW = [(0.22, 0.22)] * 24 + [(0.45, 0.45), (0.45, 0.45), (0.05, 0.45)] RGV = [31, 29, 27, 25, 33, 30, 28, 24, 32, 29, 26, 33, 30, 25, 34, 31, 27, 25, 32, 35, 30, 26, 33, 29, 25, 31, 28] cds = from_closes(RG + [54.67], wicks=RGW + [(0.15, 0.15)], vols=RGV + [49], start=60.6) last = cds[-1] rng3 = sum(c.h - c.l for c in cds[-4:-1]) / 3 pct = (last.h - last.l) / rng3 * 100 avg10 = sum(c.vol for c in cds[-11:-1]) / 10 rvol = last.vol / avg10 * 100 assert 121 <= pct <= 123, pct # cifra cursului: 122% assert 160 <= rvol <= 174, rvol # textul spune ~167% assert last.c > cds[-2].h, (last.c, cds[-2].h) CH["range_rvol"] = Chart( candles=cds, arrows=[Arrow(27, f"range {pct:.0f}% din media ultimelor 3 candele\n" f"+ bull reversal (close {last.c:.2f} peste {cds[-2].h:.2f})", color="#188a3e", where="above", dx=-128)], marks=[Mark(27, f"RVol {rvol:.0f}%", "#1a5fb4", "below")], mas=[MA(20, "#b06000", dash="4 3", text="SMA-20")], **COMMON, scale=40, vol_h=70, vol_label="volum (ultima bară vs. media a 10)", title="Exemplu construit (fără ticker) — 60 de minute", caption="Cifrele cursului pentru WBD: range 122%, RVol 167%. Seria care le" " produce e a mea.").render() # ------------------------------------------------- 5 stele, long (XOM, real) XOM = [120.8, 120.1, 119.4, 119.8, 118.9, 118.2, 117.6, 117.9, 117.0, 116.4, 116.8, 115.9, 115.3, 115.6, 114.7, 114.1, 113.8, 114.2, 113.5, 113.9, 113.2, 113.6, 113.25, 113.30, 115.02] XW = [(0.30, 0.30)] * 22 + [(0.25, 0.28), (0.25, 0.30), (0.20, 0.25)] XV = [38, 36, 34, 31, 39, 36, 33, 30, 38, 35, 32, 40, 36, 32, 41, 38, 34, 31, 39, 43, 37, 33, 40, 44, 76] cds = from_closes(XOM, wicks=XW, vols=XV, start=121.4) entry, sl, s1, piv = 115.02, 112.20, 113.03, 119.00 # piv: cifra rostită în curs last, doji = cds[-1], cds[-2] assert abs(last.c - entry) < 0.001, last.c assert abs((entry / s1 - 1) * 100 - 1.76) < 0.02 # cifra din curs: 1,76% assert piv == 119.00, piv # doar prețuri rostite pe etichete assert last.c > doji.h, (last.c, doji.h) # bull reversal assert sl < min(c.l for c in cds[-4:]), (sl, min(c.l for c in cds[-4:])) R = (piv - entry) / (entry - sl) print(f"XOM: risc {entry - sl:.2f}, câștig {piv - entry:.2f} = {R:.2f}R") CH["stele_long"] = Chart( candles=cds, levels=[Level(s1, f"suport monthly S1 {s1:.2f}", "#1a5fb4", label_at="left"), Level(sl, f"SL {sl:.2f}", "#c00", label_at="left"), Level(entry, f"intrare {entry:.2f} (close)", "#188a3e"), Level(piv, f"TP1 {piv:.2f} = pivot monthly ({R:.2f}R)", "#1a5fb4")], arrows=[Arrow(24, "bull reversal pe suport, cu volum —\nintri la close, nu în" " timpul candelei", color="#188a3e", where="above", dx=-118)], mas=[MA(20, "#b06000", dash="4 3", text="SMA-20")], **COMMON, scale=30, vol_h=70, vol_label="volum", title="XOM — daily, pivoți monthly", caption="Ale cursului: 115.02, S1 113.03, 1,76%, pivot 119 (coloana arăta 3,92%)." " SL-ul si trigger-ul sunt ale mele.").render() # ------------------------------------------------- 5 stele, short (construit) SH = [78.0, 78.5, 79.1, 78.8, 79.6, 80.2, 79.9, 80.7, 81.2, 80.9, 81.6, 82.1, 81.8, 82.5, 82.2, 82.9, 83.4, 83.1, 83.8, 84.2, 84.6, 84.3, 84.9, 84.85, 83.10] SHW = [(0.30, 0.30)] * 22 + [(0.28, 0.25), (0.45, 0.25), (0.25, 0.20)] cds = from_closes(SH, wicks=SHW, vols=XV, start=77.4) entry_s, sl_s, rez, piv_s = 83.10, 85.60, 85.00, 79.40 last, doji = cds[-1], cds[-2] assert abs(last.c - entry_s) < 0.001 assert last.c < doji.l, (last.c, doji.l) assert sl_s > max(c.h for c in cds[-4:]), (sl_s, max(c.h for c in cds[-4:])) Rs = (entry_s - piv_s) / (sl_s - entry_s) print(f"short: risc {sl_s - entry_s:.2f}, câștig {entry_s - piv_s:.2f} = {Rs:.2f}R") CH["stele_short"] = Chart( candles=cds, levels=[Level(rez, f"rezistență monthly {rez:.2f}", "#1a5fb4", label_at="left"), Level(sl_s, f"SL {sl_s:.2f}", "#c00"), Level(entry_s, f"intrare {entry_s:.2f} (close)", "#c00", label_at="left"), Level(piv_s, f"TP1 {piv_s:.2f} = pivot monthly ({Rs:.2f}R)", "#1a5fb4")], arrows=[Arrow(24, "bear reversal + sell doji confirmat + sell momentum", color="#c00", where="below", dx=-96)], mas=[MA(20, "#b06000", dash="4 3", text="SMA-20")], **COMMON, scale=48, vol_h=70, vol_label="volum", title="Exemplu construit (fără ticker) — daily, pivoți monthly", caption="Cifre construite de mine, pe modelul MDT din curs: trei trigger-e pe" " aceeași candelă.").render() if __name__ == "__main__": out = sys.argv[1] if len(sys.argv) > 1 else "/tmp/radarscreen.json" with open(out, "w", encoding="utf-8") as f: json.dump(CH, f, ensure_ascii=False) print(f"{len(CH)} diagrame -> {out}")