Files
atm-curs-dl/gen/strategii/m2d_stop.py
Claude Agent 0ed607134d m2d: diagramele refacute; ansamblul primeste corespondenta de TF
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
2026-09-20 12:45:14 +00:00

137 lines
6.7 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""M2D, pasul 4 — stopul: extrema ultimelor 4 bare, și alternativa 2 × ATR(10).
Pentru `summaries/17_STRATEGII/03_m2d.md`, marcajul `<!-- DIAGRAMA: stop -->`.
Sus: exemplul construit din tot capitolul (3 min). Numeri 4 bare înapoi de la
bara de trigger, iei cel mai jos low și acolo stă stopul — fix pe el, fără
marjă; asta e regula folosită în TOATE diagramele capitolului.
Jos: exemplul SPY din curs, singurul loc din material unde apar cifre
absolute pentru stop. Reale din curs: close-ul de trigger 517.78, ATR(10)
2.88, stopul 2×ATR 512.02 și low-ul metodei pe 4 candele 512.87. Restul
seriei e construit ca să scoată exact acel low.
Rulare: python3 gen/strategii/m2d_stop.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 # noqa: E402
import m2d_duo as duo # noqa: E402
OUT = Path(__file__).with_suffix(".svg")
W = 680
GREEN, RED, BLUE, ORANGE, GREY = "#188a3e", "#c00", "#1a5fb4", "#b06000", "#555"
STOP_BARS = 4
# --- panoul 1: exemplul construit, 3 min (aceleași bare ca în ansamblu) ----
MIC = [(100.60, 100.70, 100.40, 100.45), (100.45, 100.50, 100.25, 100.30),
(100.30, 100.35, 100.15, 100.20), (100.20, 100.25, 100.05, 100.10),
(100.10, 100.15, 100.00, 100.05), (100.05, 100.10, 99.95, 100.00),
(100.00, 100.05, 99.92, 99.95), (99.95, 100.00, 99.90, 99.98),
(99.98, 100.08, 99.94, 100.02),
(100.02, 100.45, 100.00, 100.40), # 9: trigger
(100.40, 100.60, 100.35, 100.55), (100.55, 100.75, 100.50, 100.70)]
TRIG_M = 9
# --- panoul 2: SPY, 15 min. Reale: 517.78, 2.88, 512.02, 512.87 -----------
SPY_CLOSE_TRIG = 517.78
SPY_ATR = 2.88
SPY_ATR_STOP = 512.02
SPY_LOW4 = 512.87
SPY = [(521.40, 521.80, 520.10, 520.50), (520.50, 520.90, 519.20, 519.60),
(519.60, 519.80, 518.10, 518.40), (518.40, 518.70, 516.90, 517.20),
(517.20, 517.40, 515.70, 516.10), (516.10, 516.40, 514.90, 515.30),
(515.30, 515.60, 513.40, 514.60),
(514.60, 514.90, 513.40, 514.00), # 7
(514.00, 514.30, SPY_LOW4, 513.50), # 8: cel mai jos low din 4
(513.50, 514.20, 513.20, 513.90), # 9
(513.90, 518.10, 513.80, SPY_CLOSE_TRIG)] # 10: trigger
TRIG_S = 10
# ---------------------------------------------------------------- verificări
for nume, bars in (("mic", MIC), ("SPY", SPY)):
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"
ENTRY_M = MIC[TRIG_M][3]
SL_M = min(b[2] for b in MIC[TRIG_M - STOP_BARS + 1:TRIG_M + 1])
RISK_M = round(ENTRY_M - SL_M, 2)
assert (ENTRY_M, SL_M, RISK_M) == (100.40, 99.90, 0.50), (ENTRY_M, SL_M, RISK_M)
# stopul nu e „undeva pe-aproape": e minimul celor 4 bare, și e minimul întregii serii
assert abs(SL_M - min(b[2] for b in MIC)) < 1e-9, "stopul nu e minimul seriei mici"
# a cincea bară înapoi are un low mai mare — deci numărul 4 chiar contează
assert MIC[TRIG_M - STOP_BARS][2] > SL_M, "a 5-a bară strică demonstrația celor 4"
PCT_M = RISK_M / ENTRY_M * 100
SL_S = min(b[2] for b in SPY[TRIG_S - STOP_BARS + 1:TRIG_S + 1])
assert abs(SL_S - SPY_LOW4) < 1e-9, f"low-ul pe 4 bare iese {SL_S}, nu {SPY_LOW4}"
assert abs(SPY[TRIG_S][3] - SPY_CLOSE_TRIG) < 1e-9
assert abs((SPY_CLOSE_TRIG - 2 * SPY_ATR) - SPY_ATR_STOP) < 1e-9, \
"2×ATR nu dă stopul din curs"
MARJA = round(SPY_LOW4 - SPY_ATR_STOP, 2)
assert MARJA == 0.85, MARJA
RISK_S4 = round(SPY_CLOSE_TRIG - SPY_LOW4, 2)
RISK_SA = round(SPY_CLOSE_TRIG - SPY_ATR_STOP, 2)
assert (RISK_S4, RISK_SA) == (4.91, 5.76), (RISK_S4, RISK_SA)
assert SPY_ATR_STOP < SPY_LOW4, "ATR ar trebui să dea un stop mai larg"
def chart(bars, scale, gap, left, body_w, arrows, top=64):
return Chart(candles=[Candle(*b) for b in bars], arrows=arrows, scale=scale,
gap=gap, body_w=body_w, left=left, width=W, top=top)
ch_m = chart(MIC, 150.0, 34, 62, 13, [
Arrow(TRIG_M, "bara de trigger: de la ea numeri înapoi",
where="above", color=GREEN, dx=-30, dy=-6),
Arrow(TRIG_M - STOP_BARS + 2, "cel mai jos low dintre cele 4 bare: 99.90.\n"
"Stopul stă FIX acolo, fără marjă",
where="below", color=RED, dx=-40, dy=40)])
ch_s = chart(SPY, 17.0, 34, 62, 13, [
Arrow(TRIG_S, "close-ul barei de trigger 517.78",
where="above", color=GREEN, dx=-60, dy=-4),
Arrow(8, "2 × ATR(10) = 5.76 sub close:\n"
"stop 512.02, cu 0.85 sub low-ul celor 4 bare",
where="below", color=ORANGE, dx=-20, dy=52)])
body_m, h_m = duo.panel(ch_m, W)
body_s, h_s = duo.panel(ch_s, W)
extra_m = (duo.titlu("Metoda de bază — cele 4 bare", color=RED)
+ duo.zone(ch_m, TRIG_M - STOP_BARS + 1, TRIG_M,
f"{STOP_BARS} bare, numărate de la trigger înapoi", RED,
pad=13, lift=30)
+ duo.level(ch_m, ENTRY_M, ["intrare 100.40"], GREEN, W, at_left=False)
+ duo.level(ch_m, SL_M, ["stop 99.90 — risc 0.50 pe acțiune (0,50 %)"],
RED, W, below=True))
extra_s = (duo.titlu("Alternativa din curs — 2 × ATR(10), pe SPY", color=ORANGE)
+ duo.zone(ch_s, TRIG_S - STOP_BARS + 1, TRIG_S, "", RED, pad=13)
+ duo.level(ch_s, SPY_CLOSE_TRIG, ["intrare 517.78"], GREEN, W, at_left=False)
+ duo.level(ch_s, SPY_LOW4, ["stop pe 4 bare 512.87 — risc 4.91"],
RED, W, below=False)
+ duo.level(ch_s, SPY_ATR_STOP, ["stop 2×ATR 512.02 — risc 5.76"],
ORANGE, W, below=True, dash="2 3"))
svg, H, n = duo.build(
[("mic", body_m, h_m, extra_m), ("SPY", body_s, h_s, extra_s)],
["Sus: serie construită, aceleași cifre ca în restul capitolului.",
"Jos: din curs sunt reale doar 517.78, ATR(10) = 2.88, 512.02 și 512.87; "
"restul barelor sunt construite.",
"ATR-ul dă un stop mai larg, deci un risc mai mare pe acțiune — și, la același",
"risc în dolari, mai puține acțiuni."],
W)
duo.fara_preturi_straine(svg, [ENTRY_M, SL_M, RISK_M, SPY_CLOSE_TRIG, SPY_LOW4,
SPY_ATR_STOP, SPY_ATR, RISK_S4, RISK_SA, MARJA,
2 * SPY_ATR, PCT_M])
OUT.write_text(svg, encoding="utf-8")
print(f"scris {OUT} ({W}x{H:.0f}), {n} etichete | mic: intrare {ENTRY_M:.2f} stop {SL_M:.2f} "
f"risc {RISK_M:.2f} ({PCT_M:.2f} %) | SPY: intrare {SPY_CLOSE_TRIG:.2f}, 4 bare "
f"{SPY_LOW4:.2f} (risc {RISK_S4:.2f}), 2×ATR {SPY_ATR_STOP:.2f} (risc {RISK_SA:.2f}), "
f"diferență {MARJA:.2f}")