Files
atm-curs-dl/gen/strategii/mdsrt_short.py
Claude Agent 70f5c19574 17_STRATEGII/07_mdsrt: patru restante aplicate, doua erau deja facute
Raportul verificatorului e din 21.09, iar primele doua probleme fusesera
reparate intre timp in 424ecf2 - in text. Ramasesera insa in generatoare:
docstring-ul lui mdsrt_stop si comentariul STOP_BARS din mdsrt_ansamblu inca
spuneau ca N nu e dat de curs. Un capitol poate fi corect si sa-si contrazica
generatorul.

Reparate acum: tabelul A+ descria "coborare fara nivel dedesubt" pentru un
panou in care pivotul 94.00 chiar e trasat si doar nu tine; layout-ul lui
mdsrt_aplus, unde "picior 1: 94.55" era tiparita sub linia de 94.00 (deci se
citea ca ~93.5) si "close 92.00" statea la inaltimea lui 90.80; doua etichete
taiate de linii in stop si short; si retestul din glosar, 590.05 nu 590.00.

Panourile A+ sunt acum stivuite, 700 px in loc de 1080, deci textul nu se mai
scaleaza la 0,67x. Assert nou: y-ul etichetei "picior 1" trebuie sa cada la
±8 px de unde cade pretul ei fata de linia pivotului - exact regresia
raportata.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ThN7ixZrowca8aTGrK1MUJ
2026-10-02 05:18:02 +00:00

115 lines
5.8 KiB
Python
Raw 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.

"""MDSRT pe short — oglinda completă a trade-ului long.
Seria e exact seria canonică a capitolului, răsturnată în jurul unui preț
(p' = 690 − p): fiecare candelă verde devine roșie, fiecare low devine high.
Așa, orice regulă verificată pe long e verificată și aici, cu semnul schimbat
— și se vede că nu e „doar invers", ci un trade întreg.
ATENȚIE: varianta short a MDSRT NU e explicată în curs — transcrierea se
întrerupe înainte. Regulile de aici sunt reconstruite prin oglindire de
autorul sumarului, marcate ca atare, și se tratează ca ipoteză de testat.
Rulează: python3 gen/strategii/mdsrt_short.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 Candle, Chart, Level, Mark, Zone, Arrow # noqa: E402
sys.path.insert(0, "/workspace/atm-curs-dl/gen")
from eticheta_libera import eticheta_libera # noqa: E402
from mdsrt_ansamblu import (serie, SUPORT, LEG1, TRIG, CONF, EXIT_I, # noqa: E402
ENTRY, SL, R, TP1, MARJA, STOP_BARS)
OUT = Path(__file__).with_suffix(".svg")
GREEN, RED, BLUE, GRAY, ORANGE = "#188a3e", "#c00", "#1a5fb4", "#555", "#b06000"
W, K = 700, 690.0 # K = prețul în jurul căruia se răstoarnă seria
S = 6
def m(p):
return round(K - p, 2)
cds = [Candle(m(c.o), m(c.l), m(c.h), m(c.c), vol=c.vol) for c in serie()]
REZ = m(SUPORT) # rezistența / pivotul, sus
l1, l2, cf, ex = LEG1, TRIG, CONF, EXIT_I
leg1_h, leg2_h = cds[l1].h, cds[l2].h
entry = cds[cf].c
sl = round(leg2_h + MARJA, 2)
risk = round(sl - entry, 2)
tp1 = round(entry - risk, 2)
# ----------------------------------------------------------------- assert-uri
for i, c in enumerate(cds):
assert c.h >= max(c.o, c.c) and c.l <= min(c.o, c.c), i
if i:
assert abs(c.o - cds[i - 1].c) < 1e-9, f"open[{i}] != close[{i-1}]"
# 1. oglinda e exactă: fiecare cifră a trade-ului long are perechea ei
assert (REZ, leg1_h, leg2_h, entry, sl, tp1) == (100.00, 99.90, 100.50, 99.80, 100.60, 99.00), \
(REZ, leg1_h, leg2_h, entry, sl, tp1)
assert risk == R == 0.80
# 2. povestea: piciorul 1 nu trece de nivel, piciorul 2 îl rupe în sus și recade
assert leg1_h < REZ < leg2_h
assert cds[l2].c > REZ, "candela-trigger ar trebui să se închidă tot deasupra nivelului"
assert cds[cf].c < REZ, "candela de intrare nu se închide înapoi sub nivel"
# 3. intrarea rupe low-ul candelei-trigger, stopul e cu marja peste maximul ei
assert entry < cds[l2].l, (entry, cds[l2].l)
high4 = max(c.h for c in cds[cf - STOP_BARS + 1:cf + 1])
assert high4 == leg2_h and round(high4 + MARJA, 2) == sl
# 4. ținta e simetrică, atinsă la aceeași bară ca pe long
assert abs((sl - entry) - (entry - tp1)) < 1e-9
assert next(i for i in range(cf + 1, len(cds)) if cds[i].l <= tp1 + 1e-9) == 22
# 5. ieșirea pe bear trail, tot la 2.75R
r_exit = round((entry - cds[ex].c) / risk, 2)
assert r_exit == 2.75, r_exit
# 6. divergența, în oglindă: higher high pe preț, lower high pe indicator/volum
assert cds[l2].h > cds[l1].h and cds[l2].vol > cds[l1].vol
print(f"short: rezistență {REZ:.2f}, picior 1 {leg1_h:.2f}, picior 2 {leg2_h:.2f}, "
f"intrare {entry:.2f}, SL {sl:.2f} (risc {risk:.2f}), TP1 {tp1:.2f}, ieșire {r_exit:.2f}R")
ch = Chart(
candles=cds[S:ex + 1],
levels=[
Level(REZ, f"pivot daily {REZ:.2f} — zona, sus", BLUE, label_at="left"),
Level(sl, f"SL {sl:.2f} = {MARJA:.2f} peste piciorul 2", RED, "4 3"),
# eticheta coboară sub propria linie, în stânga: la dreapta, pe
# înălțimea ei, o tăia linia pivotului de 100.00 (0.20 mai sus)
Level(entry, f"intrare short {entry:.2f}", GREEN, "6 3",
label_at="left", label_dy=18),
Level(tp1, f"TP1 {tp1:.2f} = 1:1", GREEN, "2 2", label_at="left"),
],
marks=[Mark(ex - S, f"ieșire pe trail {cds[ex].c:.2f} = {r_exit:.2f}R", GREEN, "below")],
zones=[Zone(l2 - S, cf - S, "", RED)],
arrows=[
Arrow(l1 - S, f"piciorul 1: high {leg1_h:.2f}\nrezistența ține",
where="above", price=leg1_h, color=GRAY, dx=-30, dy=-30),
Arrow(l2 - S, f"piciorul 2: high {leg2_h:.2f} — rupe nivelul în sus\n"
f"și mătură stopurile celor intrați pe short,\ndar nu poate ține acolo",
where="above", price=leg2_h, color=RED, dx=60, dy=-16),
Arrow(cf - S, f"intri short la {entry:.2f}: close sub nivel și sub low-ul candelei-trigger\n"
f"cei prinși long vând ca să iasă — coborârea e bruscă",
where="below", color=GREEN, dx=20, dy=30),
],
scale=58.0, gap=18, body_w=10, left=176, width=W, top=64, vol_h=60,
vol_label="volum: la piciorul 2 volumul crește, prețul nu mai are cumpărători = divergență",
title="Oglinda pe short (serie construită prin răsturnarea exemplului long)",
caption="Varianta short nu e explicată în curs: e reconstruită prin oglindire.",
)
svg = ch.render()
assert "\n\n" not in svg, "linie goală în SVG"
H = float(re.search(r'viewBox="0 0 [\d.]+ ([\d.]+)"', svg).group(1))
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})"
# etichetele de nivel, verificate pe linii străine (min_px=2: fiecare stă la
# 6 px peste linia ei prin construcție)
eticheta_libera(svg, "short",
{f"pivot daily {REZ:.2f} — zona, sus",
f"SL {sl:.2f} = {MARJA:.2f} peste piciorul 2",
f"intrare short {entry:.2f}", f"TP1 {tp1:.2f} = 1:1"},
min_px=2.0, rects=True)
OUT.write_text(svg, encoding="utf-8")
print(f"scris {OUT.name} ({W}x{H:.0f})")