Files
atm-curs-dl/gen/strategii/mdsrt_trigger.py
Claude Agent f8dd2f7bd0 07_mdsrt: capitol reconstruit dupa sablon
Nivelurile 1-2-3, cei 6 pasi cu diagrama fiecare, mini-glosar de 33 de
termeni, oglinda pe short cu diagrama ei, checklist. Sursele in
fise/07_mdsrt_surse.md.

Capitolul avea TREI reguli numerice diferite in acelasi loc: stop fix pe
low in ansamblu, 0.10 sub low in aplus si exemplu, plus doua reguli de
intrare. Acum mdsrt_ansamblu.py tine seria si regulile, iar picior,
trigger, stop, iesire si short le importa — nu mai pot diverge.

Noi: zona (daily -> 60 min ca descompunere reala, 2 candele daily = 14
bare, cu caseta, ghidaje si pivotul pe ambele panouri), picior, trigger,
stop, iesire, short (seria long rasturnata, deci fiecare cifra are
perechea ei).

Verificare numerica text-diagrama: trei nepotriviri reparate, inclusiv o
cifra din proza care nu exista pe niciun desen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ThN7ixZrowca8aTGrK1MUJ
2026-09-20 12:50:01 +00:00

115 lines
5.1 KiB
Python

"""MDSRT, Pasul 4 — trigger valid (DA) vs. trigger prematur (NU).
Aceeași formă de candelă, două locuri diferite. Sus: candela-trigger apare
după ce M e complet (prețul e în zona pivotului și divergența s-a format
acolo) — seria e cea canonică a capitolului, importată din `mdsrt_ansamblu`.
Jos: o candelă la fel de frumoasă, dar la 2.50 deasupra zonei; M nu e complet,
iar stopul pus sub ea e lovit de candela următoare.
Regula „forma candelei nu e trigger dacă M nu e complet" e a cursului
(`05_MODUL_4/02_strategia_5_mdsrt.md:249-311`); prețurile sunt construite, pe
scara exemplului din capitol.
Rulează: python3 gen/strategii/mdsrt_trigger.py
"""
import re
import sys
from pathlib import Path
sys.path.insert(0, "/workspace/atm-curs-dl")
sys.path.insert(0, str(Path(__file__).parent))
from svg_candles import Chart, Level, Zone, Arrow, from_closes # noqa: E402
from mdsrt_ansamblu import serie, SUPORT, TRIG, CONF, ENTRY, SL, MARJA # noqa: E402
OUT = Path(__file__).with_suffix(".svg")
GREEN, RED, BLUE, GRAY, ORANGE = "#188a3e", "#c00", "#1a5fb4", "#555", "#b06000"
W, VGAP = 700, 16
S = 8 # prima bară arătată din seria canonică
# ---------------------------------------------------------------- panoul DA
da = serie()[S:CONF + 4]
t, cf = TRIG - S, CONF - S
assert da[t].l == 589.50 < SUPORT, da[t].l
assert da[cf].c == ENTRY > da[t].h, (ENTRY, da[t].h)
# ---------------------------------------------------------------- panoul NU
NU_CLOSES = [595.80, 595.20, 594.60, 594.00, 593.40, 592.90, 592.55,
592.50, # 7 = doji frumos, dar sus
592.10, 591.60, 591.20, 590.80, 590.50, 590.20, 589.90, 589.60]
NU_WICKS = [(0.25, 0.30)] * len(NU_CLOSES)
NU_WICKS[7] = (0.35, 0.35)
nu = from_closes(NU_CLOSES, wicks=NU_WICKS, start=596.20)
D = 7
NU_SL = round(nu[D].l - MARJA, 2)
# doji: corp de cel mult 10 % din înălțimea candelei, fitile în ambele părți
body = abs(nu[D].o - nu[D].c)
rng = nu[D].h - nu[D].l
assert body <= 0.10 * rng, (body, rng)
assert nu[D].h > max(nu[D].o, nu[D].c) and nu[D].l < min(nu[D].o, nu[D].c)
# e la 2.50 deasupra zonei — asta e tot ce-l deosebește de cel de sus
assert round(nu[D].c - SUPORT, 2) == 2.50, nu[D].c - SUPORT
# stopul pus sub el e lovit chiar de candela următoare
lovit = next(i for i in range(D + 1, len(nu)) if nu[i].l <= NU_SL)
assert lovit == D + 1, lovit
# prețul chiar ajunge, mai târziu, în zona în care trigger-ul ar fi contat
assert min(c.l for c in nu) < SUPORT
print(f"trigger: DA la {da[t].l:.2f} (sub {SUPORT:.2f}), intrare {ENTRY:.2f}, SL {SL:.2f}; "
f"NU la {nu[D].c:.2f} (+2.50), stop {NU_SL:.2f} lovit la bara {lovit}")
common: dict = dict(scale=40.0, gap=20, body_w=10, left=170, width=W)
sus = Chart(
candles=da,
levels=[Level(SUPORT, f"pivot daily {SUPORT:.2f}", BLUE, label_at="left"),
Level(ENTRY, f"intrare {ENTRY:.2f}", GREEN, "6 3"),
Level(SL, f"SL {SL:.2f}", RED, "4 3")],
zones=[Zone(t, cf, "M complet: preț în zonă + divergență acolo", GREEN)],
arrows=[Arrow(t, "DA — aceeași formă, dar în zonă:\ntrigger-ul contează",
where="below", price=da[t].l, color=GREEN, dx=140, dy=30)],
title="DA — trigger valid: candela apare după ce M e complet",
**common,
)
jos = Chart(
candles=nu,
levels=[Level(SUPORT, f"pivot daily {SUPORT:.2f} — zona e abia aici", BLUE, label_at="left"),
Level(NU_SL, f"stopul pus sub doji: {NU_SL:.2f}", RED, "4 3")],
zones=[Zone(D, D, "doji corect ca formă", ORANGE)],
arrows=[
Arrow(D, f"NU — doji la {nu[D].c:.2f}, cu 2.50 deasupra zonei:\n"
f"M nu e complet, deci nu e trigger",
where="above", color=RED, dx=60, dy=-18),
Arrow(D + 1, f"stopul de sub el, {NU_SL:.2f}, e lovit\nchiar de candela următoare",
where="below", price=NU_SL, color=RED, dx=170, dy=30),
],
title="NU — trigger prematur: aceeași candelă, dar deasupra zonei",
caption="Ce deosebește cele două candele nu e forma, ci unde stă prețul când apar.",
**common,
)
def panou(ch, sus_de=0.0):
ch.top += sus_de
svg = ch.render()
h = float(re.search(r'viewBox="0 0 [\d.]+ ([\d.]+)"', svg).group(1))
off = float(re.search(r'<line x1="24" y1="([\d.]+)"', svg).group(1)) - ch._y(ch.levels[0].price)
assert abs(off) < 40, off
return svg[svg.index(">") + 1:svg.rindex("</svg>")].strip(), h
body_sus, h_sus = panou(sus)
body_jos, h_jos = panou(jos, h_sus + VGAP)
H = h_jos + 8
svg = "\n ".join([
f'<svg viewBox="0 0 {W} {H:.0f}" xmlns="http://www.w3.org/2000/svg" '
f'style="width:100%;height:auto;font:12px sans-serif">',
body_sus,
f'<line x1="24" y1="{h_sus + VGAP / 2:.0f}" x2="{W - 14}" y2="{h_sus + VGAP / 2:.0f}" stroke="#ddd"/>',
body_jos,
]) + "\n</svg>"
assert "\n\n" not in svg, "linie goală în SVG"
for x, y in re.findall(r'<text x="([-\d.]+)" y="([-\d.]+)"', svg):
assert 0 <= float(x) <= W and 0 <= float(y) <= H, f"text în afara pânzei la ({x}, {y})"
OUT.write_text(svg, encoding="utf-8")
print(f"scris {OUT.name} ({W}x{H:.0f})")