Ansamblul arata acum 15 min si 3 min ca descompunere reala (k=5, cu assert), cu caseta punctata, ghidaje si nivelul comun legat prin conector — sablonul din buy_doji_perechi_tf. Noi, pentru pasii care nu aveau diagrama: directie (15 min ramane in Buy vs. se inchide Sell), trigger (bara inchisa peste capat vs. atinsa doar cu fitilul, plus al doilea semnal marcat "nu mai intri"), stop (cele 4 bare si alternativa 2xATR, cu cifrele SPY din curs), iesire (TP1 plus bull trail, long si short, oglinda calculata nu desenata din ochi). Secventa era din polilinii desenate de mana — rescrisa pe serie. Stopul e fix pe extrema celor 4 bare, fara marja: asa spune cursul aici, spre deosebire de 01_buy_doji. Diferenta trebuie spusa in text. Textul capitolului e neatins — agentul a atins pragul de context. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ThN7ixZrowca8aTGrK1MUJ
115 lines
5.6 KiB
Python
115 lines
5.6 KiB
Python
#!/usr/bin/env python3
|
|
"""M2D, pasul 1 — direcția o dă TF-ul mare: DA (rămâne în Buy) vs. NU (se închide Sell).
|
|
|
|
Pentru `summaries/17_STRATEGII/03_m2d.md`, marcajul `<!-- DIAGRAMA: directie -->`.
|
|
|
|
Ambele panouri sunt graficul de 15 minute al aceluiași exemplu construit ca în
|
|
diagrama de ansamblu — primele 6 candele sunt identice, deci cifrele din
|
|
capitol nu se bat cap în cap de la o diagramă la alta.
|
|
|
|
Sus: pullback-ul de pe 3 min lasă pe 15 min o candelă roșie, dar indicatorul
|
|
nu dă Sell și candela nu se închide sub nivelul semnalului — setup-ul long
|
|
trăiește. Jos: candela de 15 min se ÎNCHIDE Sell — setup-ul long e anulat.
|
|
|
|
Rulare: python3 gen/strategii/m2d_directie.py
|
|
"""
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
sys.path.insert(0, "/workspace/atm-curs-dl")
|
|
sys.path.insert(0, str(Path(__file__).resolve().parent))
|
|
from svg_candles import Arrow, Candle, Chart, Mark # noqa: E402
|
|
import m2d_duo as duo # noqa: E402
|
|
|
|
OUT = Path(__file__).with_suffix(".svg")
|
|
W, SCALE, GAP, LEFT = 680, 46.0, 46, 74
|
|
GREEN, RED, BLUE, CYAN, GREY = "#188a3e", "#c00", "#1a5fb4", "#0891b2", "#555"
|
|
|
|
# --- aceleași candele de 15 min ca în diagrama de ansamblu -----------------
|
|
BASE = [(98.00, 98.35, 97.85, 98.25), (98.25, 98.70, 98.15, 98.60),
|
|
(98.60, 99.10, 98.50, 99.00), (99.00, 99.45, 98.90, 99.30),
|
|
(99.30, 99.95, 99.20, 99.85),
|
|
(99.85, 100.75, 99.80, 100.60)] # 5: Buy Momentum pe 15 min
|
|
DA = BASE + [(100.60, 100.70, 100.00, 100.05), # 6: roșie, dar nu Sell
|
|
(100.05, 100.45, 99.90, 100.40), # 7: aici cade trigger-ul de pe 3 min
|
|
(100.40, 101.15, 100.35, 101.00)]
|
|
NU = BASE + [(100.60, 100.70, 100.00, 100.05),
|
|
(100.05, 100.10, 99.20, 99.30), # 7: se ÎNCHIDE Sell — setup anulat
|
|
(99.30, 99.40, 98.60, 98.75)]
|
|
SIG = 5
|
|
|
|
# ---------------------------------------------------------------- verificări
|
|
for nume, bars in (("DA", DA), ("NU", NU)):
|
|
for i, (o, h, l, c) in enumerate(bars):
|
|
assert h >= max(o, c) and l <= min(o, c), f"{nume}[{i}]: high/low incoerent"
|
|
if i:
|
|
assert abs(o - bars[i - 1][3]) < 1e-9, f"{nume}[{i}]: open != close precedent"
|
|
assert DA[:SIG + 2] == NU[:SIG + 2], "panourile nu pornesc din aceeași serie"
|
|
|
|
SEMNAL = BASE[SIG][3] # 100.60 — același nivel ca în diagrama de ansamblu
|
|
REF_LOW = BASE[SIG][2] # 99.80 — minimul din care a pornit mișcarea
|
|
assert BASE[SIG][3] > BASE[SIG][0], "candela de semnal nu e verde"
|
|
|
|
# DA: nicio candelă de după semnal nu se închide sub minimul de referință
|
|
assert all(b[3] > REF_LOW for b in DA[SIG + 1:]), "DA: o candelă închide sub referință"
|
|
assert DA[6][3] < DA[6][0], "DA: candela 6 ar trebui să fie roșie (pullback pe 3 min)"
|
|
assert DA[6][3] > REF_LOW, "DA: candela roșie rupe deja referința"
|
|
# NU: exact una rupe — a șaptea, care se închide sub minimul de referință
|
|
rupe = [i for i, b in enumerate(NU) if i > SIG and b[3] < REF_LOW]
|
|
assert rupe == [7, 8], rupe
|
|
assert NU[7][3] < NU[7][0] and NU[7][3] < REF_LOW, "NU: candela 7 nu se închide Sell"
|
|
|
|
|
|
def chart(bars, marks, arrows, extra_h=0.0):
|
|
return Chart(candles=[Candle(*b) for b in bars], marks=marks, arrows=arrows,
|
|
scale=SCALE, gap=GAP, body_w=15, left=LEFT, width=W, top=64,
|
|
label_gap=34 + extra_h)
|
|
|
|
|
|
TITLU_DA = "DA — 15 min e încă în Buy când vine trigger-ul de pe 3 min"
|
|
TITLU_NU = "NU — 15 min s-a închis Sell: setup-ul long e anulat"
|
|
|
|
ch_da = chart(
|
|
DA,
|
|
[],
|
|
[Arrow(SIG, "Buy Momentum pe 15 min:\nde aici ai voie doar long",
|
|
where="below", color=CYAN, dx=-60, dy=54),
|
|
Arrow(6, "candelă roșie pe 15 min, dar close-ul\nrămâne peste 99.80: pullback, nu întoarcere",
|
|
where="below", color=GREY, dx=-30, dy=26),
|
|
Arrow(7, "aici cade trigger-ul de pe 3 min",
|
|
where="above", color=GREEN, dx=-24, dy=18)])
|
|
ch_nu = chart(
|
|
NU,
|
|
[],
|
|
[Arrow(SIG, "Buy Momentum pe 15 min:\nde aici ai voie doar long",
|
|
where="below", color=CYAN, dx=-60, dy=54),
|
|
Arrow(7, "close 99.30, sub 99.80: direcția mare\ns-a răsucit — nu mai intri long",
|
|
where="below", color=RED, dx=-40, dy=20),
|
|
Arrow(8, "de aici cauți short, nu long", where="below", color=RED, dx=-120, dy=82)])
|
|
|
|
body_da, h_da = duo.panel(ch_da, W)
|
|
body_nu, h_nu = duo.panel(ch_nu, W)
|
|
|
|
extra_da = (duo.titlu(TITLU_DA, color=GREEN)
|
|
+ duo.zone(ch_da, SIG, 7, "zona în care ai voie long", GREEN, pad=20, lift=26)
|
|
+ duo.level(ch_da, SEMNAL, ["close-ul candelei de semnal 100.60"], CYAN, W,
|
|
below=False, at_left=False)
|
|
+ duo.level(ch_da, REF_LOW, ["minimul din care a pornit mișcarea 99.80"],
|
|
GREY, W, below=True, dash="2 3"))
|
|
extra_nu = (duo.titlu(TITLU_NU, color=RED)
|
|
+ duo.zone(ch_nu, 7, 8, "setup anulat", RED, pad=20)
|
|
+ duo.level(ch_nu, SEMNAL, ["close-ul candelei de semnal 100.60"], CYAN, W,
|
|
below=False, at_left=False)
|
|
+ duo.level(ch_nu, REF_LOW, ["minimul din care a pornit mișcarea 99.80"],
|
|
GREY, W, below=True, dash="2 3"))
|
|
|
|
svg, H, n = duo.build(
|
|
[("DA", body_da, h_da, extra_da), ("NU", body_nu, h_nu, extra_nu)],
|
|
["Același grafic de 15 minute ca în diagrama de ansamblu; serie construită, fără ticker.",
|
|
"Pe 15 min se citește DIRECȚIA, nu intrarea. Intrarea vine de pe 3 min (pasul 3)."],
|
|
W)
|
|
duo.fara_preturi_straine(svg, [SEMNAL, REF_LOW, NU[7][3]])
|
|
OUT.write_text(svg, encoding="utf-8")
|
|
print(f"scris {OUT} ({W}x{H:.0f}), {n} etichete | semnal {SEMNAL:.2f}, referință {REF_LOW:.2f} | "
|
|
f"DA: ultima închidere {DA[-1][3]:.2f} | NU: candela 7 închide {NU[7][3]:.2f}")
|