#!/usr/bin/env python3 """Buy hammer — unde stă stopul și câte acțiuni cumperi (același trade XYZ). Zoom pe barele 14-27 din seria diagramei de ansamblu (importată, ca să nu existe două variante ale aceluiași trade). Arată: SL 62.05, cu 5 cenți sub low-ul hammer-ului, paranteza de risc 1.30 $/acțiune și, sub grafic, calculul de mărime al lecției: 2 % dintr-un cont de 10.000 $ = 200 $; 200 / 1.30 = 153 de acțiuni. Rulare: python3 gen/strategii/hammer_mbt10_bh_stop.py """ import re import sys; sys.path.insert(0, "/workspace/atm-curs-dl") sys.path.insert(0, "/workspace/atm-curs-dl/gen/strategii") from pathlib import Path from hammer_mbt10_bh_ansamblu import serie from svg_candles import Arrow, Chart, Level, Zone OUT = Path(__file__).with_suffix(".svg") GREEN, RED, BLUE, ORANGE, GREY = "#188a3e", "#c00", "#1a5fb4", "#b06000", "#555" I0, I1 = 14, 27 # fereastra desenată din seria completă cds_all, hammer, conf = serie() cds = cds_all[I0:I1 + 1] HAM, CONF = 19 - I0, 20 - I0 # indicii hammer / confirmare în fereastră INTRARE, SL = 63.35, 62.05 RISC = round(INTRARE - SL, 2) CONT, PROCENT = 10_000, 0.02 RISC_LEI = CONT * PROCENT ACTIUNI = int(RISC_LEI // RISC) # --- verificări ------------------------------------------------------------- assert cds[HAM] is hammer and cds[CONF] is conf, "fereastra nu prinde hammer-ul și confirmarea" assert round(SL, 2) == round(hammer.l - 0.05, 2), "SL nu e la 5 cenți sub low-ul hammer-ului" assert round(conf.c, 2) == INTRARE and conf.c > hammer.h, "intrarea nu e close-ul confirmării" assert RISC == 1.30, RISC assert RISC_LEI == 200 and ACTIUNI == 153, (RISC_LEI, ACTIUNI) assert min(c.l for c in cds) == hammer.l, "în fereastră, cel mai jos low nu e al hammer-ului" assert SL < min(c.l for c in cds), "linia stopului trebuie să stea sub toate fitilele" # pierderea maximă planificată încape în regula de 2 % assert ACTIUNI * RISC <= RISC_LEI, "pierderea planificată depășește 2 % din cont" ch = Chart( candles=cds, levels=[Level(INTRARE, "intrare 63.35 (close-ul confirmării)", GREEN, label_at="left"), Level(SL, "SL 62.05", RED, label_at="left")], zones=[Zone(HAM, CONF, "cele două bare care dau stopul", ORANGE)], arrows=[ Arrow(HAM, "low-ul hammer-ului: 62.10\nsub el, cererea care a făcut\nfitilul nu mai există", where="below", price=hammer.l, color=BLUE, dx=-176, dy=26), Arrow(CONF, "riscul e distanța intrare - SL:\n63.35 - 62.05 = 1.30 $ pe acțiune", where="above", color=GREY, dx=250, dy=2), ], scale=44.0, gap=26, body_w=13, left=64, width=680, vol_h=0, title="Buy hammer — stopul și mărimea poziției (daily, ticker ilustrativ XYZ)", ) svg = ch.render() m = re.search(r'viewBox="0 0 (\d+) (\d+)"', svg) W, H = int(m.group(1)), int(m.group(2)) # paranteza de risc, desenată de mână: stop -> intrare, cu textul în dreapta OFF = (float(re.search(r'' f'1R = 1.30 $') linii = [ ("Mărimea poziției, cu cifrele lecției: 2 % dintr-un cont de 10.000 $ = 200 $ de risc.", "#333"), (f"200 $ / 1.30 $ pe acțiune = {200 / RISC:.1f} → {ACTIUNI} de acțiuni (rotunjit în jos); " f"pierderea maximă {ACTIUNI * RISC:.2f} $.", "#333"), ("Cei 5 cenți de sub low sunt marja folosită în tot capitolul pe exemplele construite de mine;", GREY), ("unde cifra vine din material, e spusă acolo.", GREY), ] extra = 16 * len(linii) + 10 svg = svg.replace(f'viewBox="0 0 {W} {H}"', f'viewBox="0 0 {W} {H + extra}"') svg = svg.replace("", brk + "".join( f'{t}' for i, (t, c) in enumerate(linii)) + "") assert "\n\n" not in svg, "linie goală în SVG" OUT.write_text(svg, encoding="utf-8") print(f"scris {OUT.name} ({W}x{H + extra}); risc {RISC}, {ACTIUNI} acțiuni")