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
115 lines
5.1 KiB
Python
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})")
|