buy_doji: refacut ca tutorial pe 3 niveluri, cu diagrame adnotate

Userul a respins mostra de format tutorial: prea lunga, prea multe
trimiteri in text, termeni tehnici nedefiniti, prea multe cifre fara
desen. Cerintele lui sunt acum contract in STYLE.md (FORMAT TUTORIAL v2).

Textul: 8430 -> 4190 de cuvinte. Nivel 1 (din avion, cu mini-glosar) ->
nivel 2 (6 pasi mecanici, o diagrama fiecare) -> oglinda short -> nivel 3
(rafinari). Trimiterile fisier:linie ies din corp si se aduna la final,
cu legenda de prescurtari. Doua tabele in tot documentul.

Toate cele 14 diagrame refacute: zone dreptunghiulare de evidentiere si
sageti care spun si de ce, nu doar ce. svg_candles primeste Zone si
Arrow; render() nu mai muta obiectul la iesire.

Trei corecturi de continut:
- un singur trade prin toata procedura (doji 50.10/49.25, intrare 50.40,
  stop 49.20, 1R 1.20, TP1 51.60); seria e acum o functie comuna,
  importata de stop/transe/iesire
- short: stopul urca la 100.15, ca sa fie deasupra maximului cum cere
  regula oglindita; cifra cursului ramane in text ca observatie
- LABU: trei minime dar doua atingeri ale pivotului 86.00, ceea ce
  impaca "triple bottom" cu "al doilea test", ambele din transcriere

Reparat si bug-ul vechi din buy_doji_sell.svg: titlul peste eticheta
dojiului.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ThN7ixZrowca8aTGrK1MUJ
This commit is contained in:
Claude Agent
2026-09-19 21:09:31 +00:00
parent aff03870e8
commit 8b7b5f6b44
50 changed files with 7011 additions and 6921 deletions

View File

@@ -3,11 +3,12 @@
Citește specificația `gen/strategii/buy_doji_sell.spec.txt`. Seria de 31 de
candele e construită din lista de close-uri dată, cu open-ul fiecărei bare =
close-ul precedentului; wick-urile sunt fixate ca nivelurile (doji 99.20 /
100.10, intrare short 99.00, SL 100.10, TP 97.90, trail 96.45, ieșire la 96.60)
100.10, intrare short 99.00, SL 100.15 = 5 cenți peste high-ul de 4 candele,
TP 97.85 = 1R de 1.15, trail 96.45, ieșire la 96.60)
să iasă exact din serie, nu doar din etichetă.
"""
import sys; sys.path.insert(0, "/workspace/atm-curs-dl")
from svg_candles import Chart, Level, Mark, from_closes
from svg_candles import Arrow, Chart, Level, Zone, from_closes
# --- seria: 31 de close-uri, exact ca în specificație -----------------------
closes = [
@@ -46,17 +47,16 @@ assert vols[14] > media_vol and vols[16] > media_vol, "volum peste medie pe doji
cds = from_closes(closes, wicks=wicks, vols=vols, start=closes[0])
# adnotările pe bara +1 și pe confirmare, ca linii sub grafic (fără suprapunere)
cds[15].color = "#777" # bara de așteptare: neutră, nu confirmă
cds[15].note = "bara 15: close 99.40 peste low-ul dojiului 99.20 — NU confirmă"
cds[16].note = "bara 16: close 99.00 sub 99.20 — confirmare (intrare short)"
doji, wait, conf = cds[14], cds[15], cds[16]
entry, sl, tp = 99.00, 100.10, 97.90
# stopul 5 cenți DEASUPRA high-ului, oglinda pasului 5 (51.60 -> 51.55 pe long);
# cifrele vechi (SL 100.10, TP 97.90) puneau stopul exact pe high
entry, sl, tp = 99.00, 100.15, 97.85
# --- cele 9 assert-uri cerute de specificație ------------------------------
# 1. SL-ul e exact high-ul ultimelor 4 candele
# 1. SL-ul e 5 cenți peste high-ul ultimelor 4 candele (100.10)
assert abs(max(cd.h for cd in cds[13:17]) - 100.10) < 1e-9, "max high[13:17] != 100.10"
assert abs(sl - 100.10 - 0.05) < 1e-9, "SL nu e 5 cenți peste high"
# 2. intrarea e close-ul barei 16
assert abs(conf.c - entry) < 1e-9, f"close[16]={conf.c} != 99.00"
# 3. confirmarea închide sub low-ul dojiului
@@ -64,11 +64,11 @@ assert abs(doji.l - 99.20) < 1e-9 and conf.c < doji.l, "close[16] nu e sub low[1
# 4. bara +1 NU confirmă
assert wait.c >= doji.l, "bara 15 ar confirma, fereastra n-ar avea sens"
# 5. 1:1 exact
assert abs(abs(sl - entry) - abs(entry - tp)) < 1e-9 and abs((entry - tp) - 1.10) < 1e-9, \
assert abs(abs(sl - entry) - abs(entry - tp)) < 1e-9 and abs((entry - tp) - 1.15) < 1e-9, \
"risc != recompensă (nu e 1:1 exact)"
# 6. primul low <= TP după intrare e bara 19
primul_tp = next(i for i in range(17, len(cds)) if cds[i].l <= tp)
assert primul_tp == 19, f"TP 97.90 atins întâi la bara {primul_tp}, nu 19"
assert primul_tp == 19, f"TP 97.85 atins întâi la bara {primul_tp}, nu 19"
assert abs(cds[18].l - 98.05) < 1e-9 and abs(cds[19].l - 97.55) < 1e-9, "low-urile 18/19 nu ies"
# 7. trailing = high[25] = 96.45; primul close peste el e bara 27; ieșirea e pe profit
trail = cds[25].h
@@ -85,26 +85,43 @@ print(f"doji {doji.l:.2f}/{doji.h:.2f} intrare short {conf.c:.2f} "
f"SL {sl:.2f} TP {tp:.2f} trail {trail:.2f} ieșire bara 27 @ {cds[27].c:.2f}")
# --- desenul ----------------------------------------------------------------
RED, GREEN, BLUE, ORANGE, GRAY = "#c00", "#188a3e", "#1a5fb4", "#b06000", "#555"
ch = Chart(
candles=cds,
levels=[
# toate etichetele în dreapta: în stânga sus se suprapuneau cu mark-ul
# dojiului (SL la y=62, text până în ~x196; doji la y=58, din ~x193)
Level(sl, "SL 100.10 (high 4 candele)", "#c00"),
Level(entry, "intrare short 99.00", "#188a3e"),
Level(tp, "TP 97.90 = 1R", "#1a5fb4"),
Level(trail, "trail 96.45", "#b06000"),
# etichetele în dreapta, dincolo de ultima candelă (width > ultima
# candelă); titlul stă în stânga sus, deci nu mai are cu ce să se lovească
Level(sl, "stop 100.15", RED),
Level(entry, "intrare short 99.00", ORANGE),
Level(tp, "ținta 97.85", GREEN),
],
marks=[
Mark(14, "doji 99.20 / 100.10", "#b06000", "above"),
Mark(27, "ieșire pe trail 96.60", "#c00", "above", dy=-6),
zones=[
Zone(0, 9, "1. creștere de 10 candele", BLUE),
Zone(14, 14, "2. doji", ORANGE),
# ca unealta „short position" din TradingView: roșu = risc, SUS;
# verde = câștig, JOS — pe short totul e întors față de long
Zone(16, 19, "", RED, p_top=sl, p_bot=entry),
Zone(16, 19, "", GREEN, p_top=entry, p_bot=tp),
# linia de trail doar unde contează (înălțime 0 nu se randează)
# (de la bara 25), nu pe toată lățimea
Zone(25, 30, "", GRAY, p_top=trail, p_bot=trail - 0.02),
],
scale=30.0, gap=15, body_w=9, left=44, width=640, vol_h=70,
vol_label="volum", title="Sell Doji — daily (exemplu construit, fără ticker)",
# scurt: o linie de caption mai lungă de ~90 de caractere iese din viewBox
# (640px) și se taie la randare
caption="Intrare short la close sub low-ul dojiului, SL la high 4 candele, "
"TP 1:1, apoi trail.",
arrows=[
Arrow(18, "STOPUL SUS, la 100.15 — 5 cenți peste maximul ultimelor 4 candele:\n"
"dacă prețul urcă până aici, creșterea continuă și ideea e moartă",
where="above", price=sl, color=RED, dx=110),
Arrow(16, "AICI INTRI SHORT, la 99.00:\na doua candelă după doji e prima\n"
"care se ÎNCHIDE sub low-ul lui (99.20)",
where="below", color=ORANGE, dx=-70),
Arrow(19, "ținta JOS, la 97.85: tot 1.15, exact cât ai riscat;\naici închizi prima treime",
where="right", price=tp, color=GREEN, dx=50, dy=-32),
Arrow(27, "trail-ul a coborât după preț (96.45);\nprima închidere peste el: ieși cu restul, 96.60",
where="below", color=GRAY, dx=-40),
],
scale=45.0, gap=20, body_w=9, left=44, width=790, vol_h=60,
vol_label="volum", title="Sell Doji pe short — daily (exemplu construit)",
caption="Pe short câștigi când prețul COBOARĂ: stopul stă SUS, ținta JOS, "
"trail-ul coboară după preț. Roșu = ce riști, verde = ce câștigi.",
)
svg = ch.render()