selectia_rvol: 'sub jumatate fata de normal' pentru 0,61 -> '61 % dintr-o zi normala'. mdsrt_exemplu: legenda spunea ca nivelurile SPY sunt 'reale, din curs'; sunt reconstruite dupa ilustratia unui sumar Q&A. mbt_iesire: 2.04R -> 2,0R, cifra sursei, prin rotunjire la afisare, fara sa se atinga nicio serie; assert-ul verifica acum textul din SVG-ul randat, nu doar valoarea bruta. atmi_exemplu: '13 luni mai tarziu' era citit ca fapt al materialului - acum spune ca 13 e cifra desenului, materialul da 'aproximativ un an'; si cele patru marcaje de completare din desenele atmi sunt uniformizate. Plus cei trei agenti opencode scrisi pentru rundele astea: verif_strat, corector_strat, reparator_grafic. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ThN7ixZrowca8aTGrK1MUJ
134 lines
6.1 KiB
Python
134 lines
6.1 KiB
Python
"""Diagrama din `gen/strategii/atmi_exemplu.spec.txt` (TIP: PRET).
|
|
|
|
Exemplul real din curs (ATMI / SPY weekly): corecție de context ≥4 %,
|
|
intrare pe 27.01.2005 la 117.43 după BIM + candelă verde, fără stop-loss
|
|
standard, urcare lentă până la TP1 +10 % = 129.17, atins ~1 an mai târziu
|
|
(data exactă nesigură în ASR).
|
|
|
|
Serie continuă de 38 de candele weekly (from_closes), panou de volum,
|
|
niveluri reale (intrare / TP1) și marcaje ancorate. Toate cifrele vin din
|
|
`summaries/04_MODUL_3/03_strategia_2_atmi.md` (liniile citate în spec);
|
|
singura completare proprie e swing high-ul ~123.00, care trebuie să
|
|
conțină corecția de context.
|
|
"""
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
sys.path.insert(0, "/workspace/atm-curs-dl")
|
|
from svg_candles import Chart, Level, Mark, MA, from_closes # noqa: E402
|
|
|
|
OUT = Path(__file__).resolve().parent / "atmi_exemplu.svg"
|
|
|
|
# ── cifrele din material ────────────────────────────────────────────────────
|
|
ENTRY = 117.43 # 04_MODUL_3/03_strategia_2_atmi.md:358-363
|
|
TP = 129.17 # TP1 = +10 % pe 117.43 → 129.17 (":170-171, 358-363")
|
|
SWING_HIGH = 123.00 # completare proprie, ca să conțină corecția ≥4 %
|
|
ENTRY_I = 17 # candela de intrare (verde, precedată de BIM)
|
|
TP_I = 30 # ultima candelă: TP1 atins
|
|
BIM_I = ENTRY_I - 1 # BIM (bară de inversare bearish) înaintea candelei verzi
|
|
|
|
# ── structura seriei: 12 sus → 5 corecție → intrare → 13 luni spre TP ─────
|
|
closes = [
|
|
# ~12 candele de urcare spre swing high ~123.00
|
|
115.80, 116.50, 117.20, 117.90, 117.60, 118.30,
|
|
119.00, 119.70, 120.40, 121.00, 121.70, 122.70,
|
|
# ~6 candele de corecție, de la 123.00 în zona de intrare
|
|
122.00, 121.10, 120.10, 119.00, 117.00,
|
|
117.43, # candela de intrare (verde)
|
|
# 13 candele lunare de urcare de la 117.43 spre 129.17 — „aproximativ un an"
|
|
118.20, 119.10, 119.90, 120.60, 121.50, 122.40, 123.30,
|
|
124.20, 125.30, 126.40, 127.40, 128.30, 129.17,
|
|
]
|
|
assert len(closes) == 31, len(closes)
|
|
|
|
wicks = [(0.25, 0.30)] * len(closes)
|
|
wicks[0] = (0.35, 0.35)
|
|
wicks[11] = (0.30, 0.25) # high = 122.70 + 0.30 = 123.00 (swing high exact)
|
|
wicks[BIM_I] = (0.15, 0.45)
|
|
wicks[ENTRY_I] = (0.20, 0.40)
|
|
wicks[TP_I] = (0.00, 0.30) # high = 129.17 exact, ca TP să fie max(high)
|
|
|
|
vols = [42, 40, 44, 47, 39, 45, 48, 52, 50, 55, 58, 62,
|
|
57, 61, 66, 72, 84,
|
|
70,
|
|
58, 55, 53, 57, 54, 56, 59, 62, 64, 68, 72, 78, 88]
|
|
assert len(vols) == len(closes), (len(vols), len(closes))
|
|
|
|
cds = from_closes(closes, wicks=wicks, vols=vols, start=115.30)
|
|
|
|
# ── assert-urile din specificație ───────────────────────────────────────────
|
|
entry = cds[ENTRY_I].c
|
|
tp = cds[TP_I].c
|
|
swing_high = max(c.h for c in cds[:ENTRY_I])
|
|
|
|
assert abs(entry - 117.43) < 0.05, entry
|
|
assert abs(tp - 129.17) < 0.05, tp
|
|
assert abs(tp / entry - 1.10) < 0.005, tp / entry
|
|
assert (swing_high - entry) / swing_high >= 0.04, (swing_high, entry)
|
|
assert abs(entry - cds[ENTRY_I].c) < 0.05
|
|
assert abs(max(c.h for c in cds[-13:]) - tp) < 0.05, max(c.h for c in cds[-13:])
|
|
|
|
# structura care susține afirmațiile din text
|
|
assert abs(swing_high - SWING_HIGH) < 0.05, swing_high
|
|
assert cds[ENTRY_I].c > cds[ENTRY_I].o, "candela de intrare trebuie să fie verde"
|
|
assert cds[BIM_I].c < cds[BIM_I].o, "BIM-ul dinaintea intrării trebuie să fie bearish"
|
|
assert any(c.vol is not None for c in cds), "lipsește panoul de volum"
|
|
|
|
LUNI = TP_I - ENTRY_I # câte candele lunare de la intrare la TP1
|
|
assert 12 <= LUNI <= 14, LUNI # „aproximativ un an" din material
|
|
assert LUNI == 13, f"desenul are {LUNI} candele lunare de la intrare la TP1"
|
|
|
|
# 13 e cifra desenului, „aproximativ un an" e a materialului: eticheta
|
|
# trebuie să spună explicit care e care, altfel 13 se citește ca fapt al cursului.
|
|
TP_LABEL = (f"TP1: {LUNI} candele lunare în desen; materialul spune "
|
|
"„aproximativ un an\" (ziua exactă e neclară în transcriere)")
|
|
assert f"{LUNI} candele lunare" in TP_LABEL, TP_LABEL
|
|
assert "materialul spune" in TP_LABEL, TP_LABEL
|
|
assert "aproximativ un an" in TP_LABEL, TP_LABEL
|
|
assert "13 luni" not in TP_LABEL, "13 e cifra desenului, nu o lună a materialului"
|
|
|
|
levels = [
|
|
Level(ENTRY, "intrare 117.43", "#188a3e", label_at="right"),
|
|
Level(TP, "TP1 129.17 (+10 %)", "#1a5fb4"),
|
|
]
|
|
|
|
marks = [
|
|
Mark(11, f"swing high ~{SWING_HIGH:.2f}", "#c00", "above"),
|
|
Mark(BIM_I, "BIM", "#777", "above"),
|
|
Mark(ENTRY_I, "27.01.2005", "#188a3e", "below"),
|
|
Mark(TP_I, "TP1", "#1a5fb4", "below"),
|
|
]
|
|
|
|
# nu există nicio linie de stop-loss în desen
|
|
assert not any("stop" in t.lower() for t in
|
|
[lv.text for lv in levels] + [mk.text for mk in marks])
|
|
assert len(levels) == 2, "doar intrare și TP; strategic nu există stop standard"
|
|
|
|
# etichetele lungi merg ca linii de text sub grafic, ca să nu se bată cu
|
|
# candelele din dreapta-sus (unde urcarea spre TP nu lasă loc liber)
|
|
cds[TP_I - 2].note = ("trigger-ul (BIM + candela verde daily) se petrece în interiorul "
|
|
"lunii de intrare — vezi diagrama pasului 4")
|
|
cds[TP_I - 1].note = "după TP: capital + profit → cash până la următorul trigger valid"
|
|
cds[TP_I].note = TP_LABEL
|
|
|
|
ch = Chart(
|
|
candles=cds,
|
|
levels=levels,
|
|
marks=marks,
|
|
mas=[MA(20, "#b06000", dash="4 3")],
|
|
scale=9.5, width=660, gap=15, body_w=9, left=40, vol_h=70,
|
|
vol_label="volum", title="SPY — monthly: intrare ianuarie 2005 la 117.43 → TP1 +10 % = 129.17",
|
|
caption="Grafic lunar, ca să încapă orizontul poziției. Completare proprie: "
|
|
"swing high-ul; restul e din material.",
|
|
)
|
|
|
|
svg = ch.render()
|
|
assert svg.count("\n\n") == 0, "linie goală în SVG — rupe markdown-ul"
|
|
OUT.write_text(svg)
|
|
|
|
print(f"serie {len(cds)} candele lunare | entry {entry:.2f} @ {ENTRY_I} | "
|
|
f"tp {tp:.2f} @ {TP_I} | swing high {swing_high:.2f} "
|
|
f"(corecție {(swing_high - entry) / swing_high * 100:.2f} %) | "
|
|
f"entry→TP {LUNI} luni")
|
|
print(f"scris {OUT}")
|