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

@@ -1,4 +1,85 @@
# Progres — atm-curs-dl (actualizat 2026-09-19, 18:30 UTC)
# Progres — atm-curs-dl (actualizat 2026-09-19, 21:15 UTC)
---
# 19.09.2026, 21:15 UTC — `01_buy_doji` refăcut după respingerea userului
## Ce a reclamat userul la mostra de format tutorial
A citit `01_buy_doji.html` și l-a respins. Cererile lui, care sunt acum
contract în `STYLE.md`, secțiunea **„FORMAT TUTORIAL v2"** (prima din fișier):
niveluri 1-2-3 de sus în jos; fiecare termen tehnic explicat inline la prima
folosire („iesire pe trail" nu se presupune știut); zero trimiteri
`fișier:linie` în corpul textului; diagrame „ca la proști", cu săgeți care
spun **și de ce**, și cu zona dreptunghiulară de evidențiere care i-a plăcut
la pasul 7; tranzacția în oglindă pe short cu **diagrama ei completă**; mai
puține tabele; mai scurt.
## Starea: gata, comis. Nimic nu mai rulează.
- Textul: de la **8430 la 4190 de cuvinte**, de la **2451 la ~570 de linii**.
Nivel 1 (din avion, cu mini-glosar de 9 termeni) → nivel 2 (6 pași
mecanici, fiecare cu diagrama lui și „Treci mai departe doar dacă…") →
oglinda short → nivel 3 (rafinări). Sursele, toate, la final, cu legendă de
prescurtări. Două tabele în tot documentul.
- **Toate cele 14 diagrame refăcute** cu zone și săgeți. `substituie.py`: 14
puse, 0 lipsă. Auditul: 8 raportări, toate fals-pozitive `<g transform>`
(perechi de etichete identice din panouri stivuite, în `aplus` și
`fereastra`) — verificate vizual, nu se atinge nimic.
- **Bug-ul vechi din `buy_doji_sell.svg`** (titlul peste eticheta
„doji 99.20 / 100.10") — reparat.
## Decizii de conținut luate azi (ca să nu fie redeschise)
1. **Un singur trade prin toată procedura.** Înainte, pașii 2-4 foloseau
doji 50.10 iar pașii 5-6 doji 53.00 — exact confuzia reclamată. Cifrele
canonice acum: doji **50.10 / 49.25**, intrare **50.40**, stop **49.20**,
1R = **1.20**, TP1 = **51.60**. Low-ul doji-ului a urcat de la 49.20 la
49.25 ca stopul să fie *sub* el, nu pe el. `buy_doji_ansamblu.serie()` e
sursa unică, importată de `stop`, `transe` și `iesire` — coerența e acum
structurală, nu ținută prin disciplină.
2. **Short: stop 100.15, nu 100.10.** Exemplul cursului punea stopul exact pe
high, contrazicând regula oglindită de la pasul 5. Am ales coerența cu
regula; cifra cursului (100.10 / 97.90) e păstrată în text ca observație.
3. **LABU: „triple bottom" și „al doilea test" nu se contrazic.** Ambele sunt
în transcriere. Seria arată acum **trei minime** (82.40 / 82.00 / 81.45)
dar **două atingeri** ale pivotului 86.00 — între primele două prețul urcă
la 88.90 și trece pe deasupra, înainte de al treilea urcă doar la 85.80.
Generatorul are o aserțiune care definește „test" ca minim precedat de o
revenire peste nivel, deci regula rezistă la ajustări viitoare.
4. Panoul de jos de la pasul 5 e **alt traseu**, nu seria comună (fundul mai
face un picior). Textul o spune explicit acum — altfel „a șasea candelă"
vs. „bara 19" pare eroare.
## Ce urmează
- **Userul trebuie să aprobe formatul** înainte să-l aplicăm la celelalte 8
capitole din `17_STRATEGII/`. Asta a fost înțelegerea de la început.
- Neatins, rămas de la `cap02`: în diagramele capitolului 02, SVG-ul cu Excel
etichetează „CROSSING BULL" ce e doar PPD > PPW, iar legenda SVG-ului
A+/mediocru dă confluența ca regulă a cursului, deși e completare.
- `aplus.spec.txt` cere doji cu high 79.00, generatorul are 78.50
(preexistent, nu din lotul de azi).
## CAPCANE NOI (din lotul ăsta)
- **`Chart.render()` restaura `top`/`left`/`width` la ieșire**, deci orice
coordonată calculată cu `_y()`/`_cx()` **după** randare ieșea deplasată cu
~22 px. Reparat azi în `svg_candles.py` (randarea nu mai mută obiectul);
generatoarele care își calculează singure offsetul din SVG-ul randat merg
mai departe — formula dă zero. Dacă ai nevoie de coordonate după randare,
folosește `_render()` și pune o aserțiune că `top`, `left` și lățimea din
`viewBox` n-au fost modificate: altfel o săgeată cu text prea lung mută
tăcut graficul și panourile stivuite se dezaliniază fără să pice nimic.
- **Eticheta unei `Zone` nu stă deasupra dreptunghiului**, ci deasupra celei
mai înalte candele din dreptul textului. La o zonă îngustă cu text lung
ajunge la zeci de pixeli de banda pe care o marchează. Soluție: `text=""`
și eticheta desenată manual, sau `p_top` distanțat pe verticală.
- **Agenții apar în `ListAgents` cu numele sesiunii-părinte**, identic cu al
sesiunii principale, nu cu numele lor de agent. Am cerut din greșeală
închiderea a patru agenți activi crezând că sunt sesiuni vechi. Au refuzat
corect, pentru că cererea era formulată „dacă ai ceva în lucru, refuză și
spune-mi ce ai atins". **Formulați mereu cererile de shutdown așa.**
---

View File

@@ -3,6 +3,59 @@
Referință obligatorie înainte de a scrie/genera orice fișier nou în
`summaries/`. Exemplul de referință: `summaries/05_MODUL_4/01_patternuri_complexe_partea_a_doua.md`.
## FORMAT TUTORIAL v2 — corecțiile userului după ce a citit `01_buy_doji` (19.09.2026, seara)
Userul a citit capitolul rescris în format tutorial și l-a respins. Ce a cerut,
punct cu punct. **Astea bat orice regulă de mai jos care le contrazice.**
### Structura: trei niveluri, de sus în jos
1. **Nivelul 1 — din avion.** O pagină. Ce e strategia, o diagramă mare cu
tot trade-ul adnotat, fraza de decizie, mini-glosarul termenilor. Cine
citește doar atât trebuie să știe deja ce caută pe ecran.
2. **Nivelul 2 — procedura mecanică.** Pașii, în ordinea în care îi faci.
Fiecare pas: o propoziție de acțiune, **o diagramă**, maximum ~300 de
cuvinte, și „Treci mai departe doar dacă…". Aici omul nu alege nimic — dă
din mână, mecanic.
3. **Nivelul 3 — rafinări.** Confirmările care fac un setup A+, perechile de
TF, tranșele, exemplul real, transferul pe prop/BVB, contradicțiile.
Începe cu o linie: „asta citești după 20 de trade-uri făcute mecanic".
### Limbaj
- **Explică fiecare termen tehnic la prima folosire, inline, într-o
propoziție.** „ieșire pe trail", „retest", „1R", „tranșe", „doji" — nimic
nu se presupune știut. Dacă termenul are formă pe grafic, desenează-l.
- Propoziții normale, nu telegrafice. Fără stil abrupt de notiță.
- Cifrele se plimbă cu o diagramă. Un pas care e doar text cu numere e un pas
prost scris.
### Referințe
- **Zero trimiteri `fișier:linie` în corpul textului.** Ele îngreunează
cititul. Toate se mută la finalul fiecărui nivel, într-un bloc „Surse",
grupate pe pas. În text, cel mult un link markdown către un alt capitol
din `summaries/`.
### Diagrame — „ca la proști"
- Fiecare diagramă de preț arată **săgeți cu text**: „aici intri", „aici pui
stopul — sub el ideea e moartă", „aici prima țintă".
- **Zonă dreptunghiulară de evidențiere** peste regiunea despre care e
vorba (userului i-a plăcut explicit cea de la pasul 7). Folosește-o.
- Fiecare săgeată spune și **de ce**, nu doar ce.
- **Tranzacția în oglindă (short) are diagrama ei completă**, nu o
propoziție „e invers". Userul e vizual.
### Volum
- Mai puține tabele. Un tabel doar dacă compari 3+ lucruri pe aceleași
criterii. Altfel: listă sau paragraf.
- Mai scurt. Userul: „te lungesti foarte mult", „daca imi dai extrem de
multe informatii nu stiu care sunt relevante". Ce nu intră în procedura
mecanică merge la nivelul 3 sau se taie.
- Exemplele concrete și setup-urile rămân — alea îi plac. Abstracțiile pleacă.
## FORMAT TUTORIAL pentru capitolele de strategie (cerut de user, 19.09.2026)
Userul a citit `17_STRATEGII/A3_intrarea.md` și a spus: conținutul îi place,

View File

@@ -1,103 +1,166 @@
"""Buy Doji — diagrama de ansamblu (daily, exemplu construit, fără ticker).
Citește specificația `gen/strategii/buy_doji_ansamblu.spec.txt`. Seria de
32 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 50.10/49.20, intrare 50.40, SL 49.20, TP1 51.60, trail 52.60, ieșire
sub trail la bara 28) să iasă exact din serie, nu doar din etichetă.
Citește specificația `gen/strategii/buy_doji_ansamblu.spec.txt`.
Seria de aici e SURSA UNICĂ a trade-ului din capitol: buy_doji_stop,
buy_doji_transe și buy_doji_iesire importă `serie()` și pornesc din
aceleași bare (doji 50.10/49.25, confirmare 50.40, SL 49.20, TP1 51.60),
ca începătorul să urmărească un singur trade prin toată procedura.
Barele 0-19: close-uri, open = close-ul precedentului. Barele 20-28 sunt
date explicit: 21 și 27 deschid cu GAP (low peste high-ul precedentei),
fiindcă regula de trail din curs se sprijină exact pe barele astea.
"""
import sys; sys.path.insert(0, "/workspace/atm-curs-dl")
from svg_candles import Chart, Level, Mark, MA, from_closes
from svg_candles import Candle, Chart, Level, MA, Zone, Arrow, from_closes
# --- seria: 32 de close-uri, exact ca în specificație -----------------------
closes = [
60.20, 59.20, 59.60, 58.40, 57.30, 57.70, 56.50, 55.40, 55.80, 54.70, # 0-9
53.50, 52.30, 51.00, 49.65, # 10-13 downtrend
49.60, # 14 doji
49.90, # 15 +1 (nu confirmă)
50.40, # 16 +2 confirmare => intrare
50.90, 51.20, 51.50, 51.80, 52.10, 52.40, 52.20, 52.70, 52.95, 53.20, # 17-26
52.80, 52.30, 52.00, 51.80, 51.90, # 27-31
]
assert len(closes) == 32
OUT = "/workspace/atm-curs-dl/gen/strategii/buy_doji_ansamblu.svg"
# wick-uri: (up, down) implicite (0.25, 0.30) + excepțiile din specificație
wicks = [(0.25, 0.30)] * 32
wicks[14] = (0.45, 0.40) # doji: high 50.10, low 49.20
wicks[15] = (0.15, 0.15) # high 50.05, low 49.45
wicks[16] = (0.15, 0.15) # high 50.55, low 49.75
for k in range(24, 28): # barele 24-27
wicks[k] = (0.25, 0.20)
DOJI, WAIT, CONF = 14, 15, 16 # indicii barelor-cheie
DOJI_H, DOJI_L = 50.10, 49.25
ENTRY, SL, TP1 = 50.40, 49.20, 51.60
R = 1.20
# volum relativ ales de generator (materialul nu dă volum pe exemplu);
# peste medie pe doji (14) și pe confirmare (16), apoi normal
vols = [42, 44, 40, 46, 43, 41, 45, 42, 44, 47,
43, 45, 48, 52, 78, 46, 88, 55,
50, 48, 52, 47, 45, 49, 46, 44, 48, 51,
54, 47, 45, 46]
assert len(vols) == 32
media_vol = sum(vols) / len(vols)
assert vols[14] > media_vol and vols[16] > media_vol, "volum peste medie pe doji/confirmare"
cds = from_closes(closes, wicks=wicks, vols=vols, start=60.20)
def serie() -> list[Candle]:
"""Cele 32 de bare ale trade-ului, cu verificările de bază."""
closes = [
60.20, 59.20, 59.60, 58.40, 57.30, 57.70, 56.50, 55.40, 55.80, 54.70, # 0-9
53.50, 52.30, 51.00, 49.65, # 10-13 downtrend
49.60, # 14 doji
49.90, # 15 +1 (nu confirmă)
50.40, # 16 confirmare => intrare
50.90, 51.20, 51.50, # 17-19 (19 atinge TP1)
]
wicks = [(0.25, 0.30)] * len(closes)
wicks[14] = (0.45, 0.35) # doji: high 50.10, low 49.25
wicks[15] = (0.15, 0.15) # high 50.05, low 49.45
wicks[16] = (0.15, 0.15) # high 50.55, low 49.75
cds = from_closes(closes, wicks=wicks, start=60.20)
cds += [Candle(*b) for b in [
(51.50, 51.85, 51.40, 51.75), # 20
(52.00, 52.30, 51.95, 52.20), # 21 GAP: low 51.95 > high[20] 51.85 → trail 51.95
(52.20, 52.45, 52.05, 52.35), # 22
(52.35, 52.40, 52.00, 52.10), # 23 retragere, close peste trail: rămâi
(52.10, 52.50, 52.05, 52.40), # 24
(52.40, 52.55, 52.25, 52.50), # 25
(52.50, 52.55, 52.35, 52.45), # 26
(52.70, 53.10, 52.60, 52.95), # 27 GAP: low 52.60 > high[26] 52.55 → trail 52.60
(52.95, 53.00, 52.20, 52.30), # 28 close 52.30 < 52.60: ieși
]]
cds += from_closes([52.00, 51.80, 51.90], wick=0.25, start=52.30) # 29-31
assert len(cds) == 32
for i, c in enumerate(cds):
assert c.l <= min(c.o, c.c) and c.h >= max(c.o, c.c), f"bara {i}: h/l nu cuprind o/c"
if i and i not in (21, 27):
assert abs(c.o - cds[i - 1].c) < 1e-9, f"open[{i}] != close[{i-1}]"
d = cds[DOJI]
assert (round(d.h, 2), round(d.l, 2)) == (DOJI_H, DOJI_L), (d.h, d.l)
assert abs(d.o - d.c) <= 0.10 * (d.h - d.l), "bara 14 nu e doji"
assert cds[WAIT].c <= DOJI_H < cds[CONF].c, "fereastra: 15 nu confirmă, 16 da"
assert abs(cds[CONF].c - ENTRY) < 1e-9
assert abs(min(c.l for c in cds[CONF - 3:CONF + 1]) - DOJI_L) < 1e-9, "low-ul doji nu e cel mai jos din 4"
assert round(DOJI_L - 0.05, 2) == SL and round(ENTRY - SL, 2) == R and round(ENTRY + R, 2) == TP1
return cds
# 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 49.90 sub high-ul dojiului 50.10 — NU confirmă"
cds[16].note = "bara 16: close 50.40 peste 50.10 — confirmare (intrare)"
doji, wait, conf = cds[14], cds[15], cds[16]
entry, sl, tp1, trail = 50.40, 49.20, 51.60, 52.60
def trail(cds, start=CONF + 1):
"""Regula de trail: bara cu low > high-ul precedentei urcă linia la low-ul ei;
ieși la primul close sub linie. Întoarce (treptele, bara de ieșire)."""
t, steps = None, []
for i in range(start, len(cds)):
if t is not None and cds[i].c < t:
return steps, i
if cds[i].l > cds[i - 1].h:
t = cds[i].l
steps.append((i, round(t, 2)))
return steps, None
# --- cele 9 assert-uri cerute de specificație ------------------------------
# 1. SL-ul e exact low-ul dojiului, cel mai jos din fereastra de 4 candele
assert abs(min(cd.l for cd in cds[13:17]) - 49.20) < 1e-9, "min low[13:17] != 49.20"
# 2. intrarea e close-ul barei 16
assert abs(conf.c - entry) < 1e-9, f"close[16]={conf.c} != 50.40"
# 3. confirmarea închide peste high-ul dojiului
assert abs(doji.h - 50.10) < 1e-9 and conf.c > doji.h, "close[16] nu e peste high[14]"
# 4. bara +1 NU confirmă
assert wait.c <= doji.h, "bara 15 ar confirma, fereastra n-ar avea sens"
# 5. 1:1 exact
assert abs(abs(entry - sl) - abs(tp1 - entry)) < 1e-9 and abs((entry - sl) - 1.20) < 1e-9, \
"risc != recompensă (nu e 1:1 exact)"
# 6. primul high >= TP1 după intrare e bara 19
primul_tp = next(i for i in range(17, len(cds)) if cds[i].h >= tp1)
assert primul_tp == 19, f"TP1 51.60 atins întâi la bara {primul_tp}, nu 19"
# 7. trailing 52.60 = low[27]; ieșire la bara 28 sub el; ieșirea e pe profit
assert abs(cds[27].l - trail) < 1e-9, f"low[27]={cds[27].l} != 52.60"
assert abs(cds[28].c - 52.30) < 1e-9 and cds[28].c < trail, "close[28] nu e sub trail"
assert trail > entry, "trail sub intrare, ieșirea n-ar fi pe profit"
# 8. doji: corp <= 10% din amplitudine
assert abs(doji.o - doji.c) <= 0.10 * (doji.h - doji.l), "bara 14 nu e doji"
# 9. downtrend vizibil
assert cds[13].c < cds[0].c - 10, "downtrend prea mic"
print(f"doji {doji.h:.2f}/{doji.l:.2f} intrare {conf.c:.2f} "
f"SL {sl:.2f} TP1 {tp1:.2f} trail {trail:.2f} ieșire bara 28 @ {cds[28].c:.2f}")
if __name__ == "__main__":
cds = serie()
vols = [42, 44, 40, 46, 43, 41, 45, 42, 44, 47,
43, 45, 48, 52, 78, 46, 88, 55,
50, 48, 52, 47, 45, 49, 46, 44, 48, 51,
54, 47, 45, 46]
for c, v in zip(cds, vols):
c.vol = v
media_vol = sum(vols) / len(vols)
assert vols[DOJI] > media_vol and vols[CONF] > media_vol, "volum peste medie pe doji/confirmare"
# --- desenul ----------------------------------------------------------------
ch = Chart(
candles=cds,
levels=[
Level(sl, "SL 49.20 (low 4 candele)", "#c00", label_at="left"),
Level(entry, "intrare 50.40", "#188a3e", label_at="left"),
Level(tp1, "TP1 51.60 = 1R", "#1a5fb4", label_at="left"),
Level(trail, "trail 52.60", "#b06000"),
],
marks=[
Mark(14, "doji 50.10 / 49.20", "#b06000", "below"),
Mark(28, "ieșire pe trail ~52.60", "#c00", "above", dy=-6),
],
mas=[MA(20, "#777", dash="4 3", text="MA(20)")],
scale=24.0, gap=15, body_w=9, left=44, width=640, vol_h=70,
vol_label="volum", title="Buy Doji — daily (exemplu construit, fără ticker)",
caption="Intrare la close-ul confirmării, SL la low-ul ultimelor 4 candele, "
"TP1 1:1, apoi trailing stop.",
)
# --- aserțiunile specificației ---------------------------------------------
primul_tp = next(i for i in range(CONF + 1, len(cds)) if cds[i].h >= TP1)
assert primul_tp == 19, f"TP1 51.60 atins întâi la bara {primul_tp}, nu 19"
steps, iesire = trail(cds)
assert steps == [(21, 51.95), (27, 52.60)], steps
assert iesire == 28 and abs(cds[28].c - 52.30) < 1e-9, iesire
assert steps[-1][1] > ENTRY, "trail sub intrare, ieșirea n-ar fi pe profit"
R_IES = round((cds[28].c - ENTRY) / R, 2)
assert R_IES == 1.58, R_IES
assert cds[13].c < cds[0].c - 10, "downtrend prea mic"
print(f"doji {DOJI_H:.2f}/{DOJI_L:.2f} intrare {ENTRY:.2f} SL {SL:.2f} TP1 {TP1:.2f} "
f"trail {steps} ieșire bara 28 @ {cds[28].c:.2f} = +{R_IES}R")
svg = ch.render()
assert "<svg" in svg and "\n\n" not in svg, "linie goală în SVG"
with open("/workspace/atm-curs-dl/gen/strategii/buy_doji_ansamblu.svg", "w") as f:
f.write(svg)
print("scris gen/strategii/buy_doji_ansamblu.svg")
cds[WAIT].color = "#777" # bara de așteptare: neutră, nu confirmă
GREEN, RED, BLUE, ORANGE, GREY = "#188a3e", "#c00", "#1a5fb4", "#b06000", "#666"
ch = Chart(
candles=cds,
levels=[
Level(TP1, "ținta 1: 51.60", BLUE, label_at="left"),
Level(ENTRY, "intrare 50.40", GREEN, label_at="left"),
Level(SL, "stop 49.20", RED, label_at="left"),
],
zones=[
Zone(4, 13, "1. scăderea: vânzătorii obosesc", RED),
Zone(14, 15, "2. doji: pauză, încă nu intri", ORANGE, p_top=53.9),
Zone(16, 16, "3. confirmarea", GREEN, p_top=52.9),
Zone(17, 28, "4. ieșirea: o treime la țintă, restul pe trail", BLUE, p_top=54.9),
],
arrows=[
Arrow(DOJI, "stopul 49.20, 5 cenți sub doji\nsub el, ideea că vânzătorii\nau obosit e moartă",
where="below", price=SL, color=RED, dx=-150, dy=0),
Arrow(CONF, "AICI INTRI, la close 50.40\nabia acum știi că\ncumpărătorii au câștigat",
where="below", price=ENTRY, color=GREEN, dx=-10, dy=64),
Arrow(19, "ținta 1: 51.60 = riscul (1.20)\nîncă o dată: vinzi o treime",
where="below", price=TP1, color=BLUE, dx=95, dy=74),
Arrow(27, "trailing stop: urcă după preț\nla fiecare gap, nu coboară",
where="above", color=ORANGE, dx=40),
Arrow(28, "ieși la 52.30 (+1.58R)\nprima închidere sub trail",
where="right", color=RED, dx=40, dy=-48),
],
mas=[MA(20, "#999", dash="4 3", text="MA(20)")],
scale=40.0, gap=15, body_w=9, left=44, width=640, vol_h=60,
vol_label="volum", title="Buy Doji — un trade de la cap la coadă (daily, exemplu construit)",
)
svg = ch.render()
# render() mută `top` intern (titlu, săgeți) și îl restaurează: ch._y() de aici
# e mai sus cu atâta. Offsetul se citește din prima linie de Level desenată.
import re as _re
OFF = (float(_re.search(r'<line x1="24" y1="([\d.]+)"', svg).group(1))
- ch._y(ch.levels[0].price))
def Y(p):
return ch._y(p) + OFF
# linia de trail în trepte (Level ar trage-o pe toată lățimea, înainte să existe)
(i1, t1), (i2, t2) = steps
x0, xa, xb = ch._cx(i1) - 7, ch._cx(i2) - 7, ch._cx(iesire) + 7
ya, yb = Y(t1), Y(t2)
step = (f'<polyline points="{x0:.1f},{ya:.1f} {xa:.1f},{ya:.1f} {xa:.1f},{yb:.1f} '
f'{xb:.1f},{yb:.1f}" fill="none" stroke="{ORANGE}" stroke-width="2"/>')
# parantezele 1R: riscul jos, ținta sus, aceeași înălțime = „1:1"
xp = ch._cx(5)
br = []
for lo, hi, txt, col in ((SL, ENTRY, "1R = 1.20 (riscul)", RED),
(ENTRY, TP1, "1R = 1.20 (ținta)", BLUE)):
y1, y2 = Y(hi) + 2, Y(lo) - 2
br.append(f'<polyline points="{xp - 5:.1f},{y1:.1f} {xp:.1f},{y1:.1f} {xp:.1f},{y2:.1f} '
f'{xp - 5:.1f},{y2:.1f}" fill="none" stroke="{col}" stroke-width="1.5"/>')
br.append(f'<text x="{xp + 6:.1f}" y="{(y1 + y2) / 2 + 4:.1f}" fill="{col}" '
f'style="font-weight:bold">{txt}</text>')
body = svg.rsplit("</svg>", 1)[0].rstrip()
svg = "\n ".join([body, step, *br]) + "\n</svg>"
assert "<svg" in svg and "\n\n" not in svg, "linie goală în SVG"
with open(OUT, "w") as f:
f.write(svg)
print("scris gen/strategii/buy_doji_ansamblu.svg")

View File

@@ -1,58 +1,76 @@
TIP: PRET
CHEIE: ansamblu
TITLU: Buy Doji — daily (exemplu construit, fără ticker)
MARCAJ .md: <!-- DIAGRAMA: ansamblu --> (Nivel 0, „Diagrama de ansamblu")
SPEC DIAGRAMĂ — buy_doji_ansamblu
=================================
tip: PRET (un singur panou, cu volum)
destinație: summaries/17_STRATEGII/01_buy_doji.md, nivelul 1 („tot trade-ul")
cheie markdown: <!-- DIAGRAMA: ansamblu -->
titlu SVG: „Buy Doji — un trade de la cap la coadă (daily, exemplu construit)"
rol: SURSA UNICĂ a seriei. buy_doji_stop, buy_doji_transe și
buy_doji_iesire importă `serie()` din generatorul ăsta, ca
toate patru să arate ACELAȘI trade.
CE ARATĂ
Graficul întreg al unui trade Buy Doji long: downtrend de 14 candele,
doji, o candelă de așteptare (în fereastră, care NU confirmă), apoi cea
care confirmă; intrare la close-ul confirmării, SL la extrema ultimelor 4
candele, TP 1:1 atins, apoi poziția rămasă pe trailing stop până la
ieșire. Banda de jos = volum.
TRADE-UL (aceleași cifre în toate cele patru diagrame)
------------------------------------------------------
doji (bara 14): high 50.10, low 49.25
bara 15 (+1): close 49.90, sub 50.10 — NU confirmă
bara 16 (+2): close 50.40 — confirmare => INTRARE 50.40
cel mai jos low din ultimele 4 candele (13-16): 49.25 (al doji-ului)
STOP: 49.20 (5 cenți sub); 1R = 1.20; ȚINTA 1: 51.60 (atinsă la bara 19)
trailing stop: 51.95 (gap la bara 21) → 52.60 (gap la bara 27)
ieșire: close 52.30 la bara 28 = +1.58R
NIVELURILE ȘI ETICHETELE (cu trimitere)
- doji high = 50.10, doji low = 49.20. Etichetă pe bară „doji 50.10 / 49.20".
`13_strategia_3_byh.md:90`, exemplul din `13_strategia_3_byh.md:158-167`.
- intrare = 50.40 (close-ul candelei de confirmare). Etichetă „intrare 50.40".
`13_strategia_3_byh.md:158-167`.
- SL = 49.20 (low-ul dojiului = cel mai jos low din 4 candele). Etichetă
„SL 49.20 (low 4 candele)". Regula: `13_strategia_3_byh.md:192-193`.
- TP1 = 51.60 = 1R (50.40 + 1.20). Etichetă „TP1 51.60 = 1R". Regula 1:1:
`13_strategia_3_byh.md:194-195`.
- linia de trailing = 52.60 (low-ul barei 27), etichetă „trail 52.60";
ieșire la close sub ea (bara 28, close 52.30). Regula de trail:
`13_strategia_3_byh.md:196-200`; „ieșire pe trail ~52.60" în diagrama
lecției: `13_strategia_3_byh.md:91`.
STRUCTURA SERIEI (32 bare, 0-indexate)
--------------------------------------
Barele 0-19 din close-uri, open = close-ul precedentului, fitile (0.25, 0.30),
cu excepțiile: 14 (0.45, 0.35) → high 50.10 / low 49.25; 15 și 16 (0.15, 0.15).
close-uri 0-19: 60.20, 59.20, 59.60, 58.40, 57.30, 57.70, 56.50, 55.40, 55.80,
54.70, 53.50, 52.30, 51.00, 49.65, 49.60, 49.90, 50.40, 50.90, 51.20, 51.50.
Barele 20-28 date explicit (o, h, l, c) — 21 și 27 deschid cu GAP, fiindcă
regula de trail cere o bară cu low peste high-ul precedentei:
20 (51.50, 51.85, 51.40, 51.75)
21 (52.00, 52.30, 51.95, 52.20) GAP: low 51.95 > high[20] 51.85 → trail 51.95
22 (52.20, 52.45, 52.05, 52.35)
23 (52.35, 52.40, 52.00, 52.10) retragere, close peste trail: rămâi în trade
24 (52.10, 52.50, 52.05, 52.40)
25 (52.40, 52.55, 52.25, 52.50)
26 (52.50, 52.55, 52.35, 52.45)
27 (52.70, 53.10, 52.60, 52.95) GAP: low 52.60 > high[26] 52.55 → trail 52.60
28 (52.95, 53.00, 52.20, 52.30) close sub 52.60: IEȘIRE
Barele 29-31 din close-uri 52.00, 51.80, 51.90 (fitil 0.25).
Volum: peste media seriei pe doji (14) și pe confirmare (16), altfel normal.
Valorile de volum sunt alese de generator (materialul nu le dă).
STRUCTURA SERIEI (32 candele, 0-indexate, open = close-ul precedentului)
Lista de close-uri:
[60.20, 59.20, 59.60, 58.40, 57.30, 57.70, 56.50, 55.40, 55.80, 54.70,
53.50, 52.30, 51.00, 49.65, # 13 = ultima bară de downtrend
49.60, # 14 = doji (o 49.65, c 49.60, h 50.10, l 49.20)
49.90, # 15 = +1, sub high-ul dojiului, NU confirmă
50.40, # 16 = +2, confirmare (close peste 50.10) => intrare
50.90, 51.20, 51.50, 51.80, 52.10, 52.40, 52.20, 52.70, 52.95, 53.20,
52.80, 52.30, 52.00, 51.80, 51.90]
Mecioni (up, down) implicite (0.25, 0.30) pentru toate barele, cu excepțiile:
- bara 14 (doji): o=49.65, c=49.60 => wu=0.45 (high 50.10), wd=0.40 (low 49.20);
- bara 15: o=49.60, c=49.90 => wu=0.15 (high 50.05), wd=0.15 (low 49.45);
- bara 16: o=49.90, c=50.40 => wu=0.15 (high 50.55), wd=0.15 (low 49.75);
- barele 24-27: wd=0.20. Cu lista de mai sus, low[27] = 52.60 (linia de trail).
Volum: peste media seriei pe doji și pe confirmare (publicul intră), apoi
normal. Valori relative, alese de generator (materialul nu dă volum pentru
acest exemplu).
ADNOTĂRI (formatul tutorial v2: zone + săgeți cu CE și DE CE)
-------------------------------------------------------------
4 zone dreptunghiulare: „1. scăderea: vânzătorii obosesc" (4-13),
„2. doji: pauză, încă nu intri" (14-15), „3. confirmarea" (16),
„4. ieșirea: o treime la țintă, restul pe trail" (17-28).
5 săgeți: stopul 49.20; „AICI INTRI, la close 50.40"; ținta 1 = riscul;
trailing stop (urcă la fiecare gap); ieșirea la 52.30 (+1.58R).
Două paranteze verticale egale: 49.20→50.40 „1R = 1.20 (riscul)" și
50.40→51.60 „1R = 1.20 (ținta)" — așa se vede 1:1.
Linia de trail e desenată în trepte (un Level ar trage-o pe toată lățimea,
inclusiv înainte să existe).
CE VERIFICĂ GENERATORUL CU assert
1. min(low[13:17]) == 49.20 (SL-ul e exact low-ul dojiului, cel mai jos din 4)
2. close[16] == 50.40 == intrare
3. close[16] > high[14] == 50.10 (confirmarea chiar închide peste high)
4. close[15] <= high[14] (bara +1 NU confirmă — altfel fereastra n-ar avea sens)
5. abs(entry - sl) == abs(tp1 - entry) == 1.20 (1:1 exact, nu aproximat)
6. primul i>16 cu high[i] >= 51.60 este bara 19
7. low[27] == 52.60; close[28] == 52.30 < 52.60; și 52.60 > intrare
(ieșirea pe trail e pe profit)
8. doji: abs(o-c) <= 0.10 * (h-l) (corp ≤ 10%, criteriul din
`28_2025-05-27.md:343-349`)
9. trend: close[13] < close[0] - 10 (downtrend vizibil)
STIL: gap=15, body_w=9, left=44, width=640, vol_h=70, scale ~24, MA(20)
opțional (linia mediei apare pe graficul lecției). Fără linie goală în SVG.
---------------------------------
1. h/l cuprind o/c pe toate barele; open[i] == close[i-1] peste tot în afară
de barele de gap 21 și 27.
2. doji: high 50.10, low 49.25, corp <= 10% din amplitudine.
3. close[15] <= 50.10 < close[16]; close[16] == 50.40 (fereastra are sens).
4. min(low[13:17]) == 49.25; 49.25 - 0.05 == 49.20; 50.40 - 49.20 == 1.20;
50.40 + 1.20 == 51.60.
5. primul high >= 51.60 după intrare e bara 19.
6. regula de trail, calculată pe serie, dă exact [(21, 51.95), (27, 52.60)]
și ieșire la bara 28, close 52.30; 52.60 > intrare (ieșire pe profit).
7. (52.30 - 50.40) / 1.20 == 1.58.
8. volum peste medie pe 14 și 16.
9. downtrend: close[13] < close[0] - 10.
SURSA
-----
- Doji 50.10/49.20 și intrarea la close-ul confirmării: summaries/03_MODUL_2/
13_strategia_3_byh.md:90, :158-167. Low-ul doji-ului e coborât aici la 49.25,
ca stopul de 49.20 să fie SUB el, nu exact pe el (decizie de redactare).
- SL = extrema ultimelor 4 candele: :192-193. Ținta 1:1: :194-195.
- Trail pe gap și ieșire la close sub linie: :196-200.
- Barele de după intrare sunt CONSTRUITE.

View File

@@ -1,116 +1,144 @@
<svg viewBox="0 0 640 498" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif">
<text x="24" y="48" fill="#333" style="font-weight:bold">Buy Doji — daily (exemplu construit, fără ticker)</text>
<line x1="24" y1="326.0" x2="626" y2="326.0" stroke="#c00" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30" y="320.0" fill="#c00">SL 49.20 (low 4 candele)</text>
<line x1="24" y1="297.2" x2="626" y2="297.2" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30" y="291.2" fill="#188a3e">intrare 50.40</text>
<line x1="24" y1="268.4" x2="626" y2="268.4" stroke="#1a5fb4" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30" y="262.4" fill="#1a5fb4">TP1 51.60 = 1R</text>
<line x1="24" y1="244.4" x2="626" y2="244.4" stroke="#b06000" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="612" y="238.4" fill="#b06000" text-anchor="end">trail 52.60</text>
<polyline points="329.0,205.1 344.0,215.2 359.0,223.7 374.0,232.3 389.0,239.8 404.0,245.3 419.0,251.0 434.0,255.0 449.0,258.1 464.0,262.3 479.0,265.5 494.0,267.6 509.0,268.0" fill="none" stroke="#777" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="515" y="262" fill="#777">MA(20)</text>
<line x1="44.0" y1="56.0" x2="44.0" y2="69.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="39.5" y="62.0" width="9" height="1.6" fill="#188a3e"/>
<line x1="59.0" y1="56.0" x2="59.0" y2="93.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="54.5" y="62.0" width="9" height="24.0" fill="#c00"/>
<line x1="74.0" y1="70.4" x2="74.0" y2="93.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="69.5" y="76.4" width="9" height="9.6" fill="#188a3e"/>
<line x1="89.0" y1="70.4" x2="89.0" y2="112.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="84.5" y="76.4" width="9" height="28.8" fill="#c00"/>
<line x1="104.0" y1="99.2" x2="104.0" y2="138.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="99.5" y="105.2" width="9" height="26.4" fill="#c00"/>
<line x1="119.0" y1="116.0" x2="119.0" y2="138.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="114.5" y="122.0" width="9" height="9.6" fill="#188a3e"/>
<line x1="134.0" y1="116.0" x2="134.0" y2="158.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="129.5" y="122.0" width="9" height="28.8" fill="#c00"/>
<line x1="149.0" y1="144.8" x2="149.0" y2="184.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="144.5" y="150.8" width="9" height="26.4" fill="#c00"/>
<line x1="164.0" y1="161.6" x2="164.0" y2="184.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="159.5" y="167.6" width="9" height="9.6" fill="#188a3e"/>
<line x1="179.0" y1="161.6" x2="179.0" y2="201.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="174.5" y="167.6" width="9" height="26.4" fill="#c00"/>
<line x1="194.0" y1="188.0" x2="194.0" y2="230.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="189.5" y="194.0" width="9" height="28.8" fill="#c00"/>
<line x1="209.0" y1="216.8" x2="209.0" y2="258.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="204.5" y="222.8" width="9" height="28.8" fill="#c00"/>
<line x1="224.0" y1="245.6" x2="224.0" y2="290.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="219.5" y="251.6" width="9" height="31.2" fill="#c00"/>
<line x1="239.0" y1="276.8" x2="239.0" y2="322.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="234.5" y="282.8" width="9" height="32.4" fill="#c00"/>
<line x1="254.0" y1="304.4" x2="254.0" y2="326.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="249.5" y="315.2" width="9" height="1.6" fill="#c00"/>
<line x1="269.0" y1="305.6" x2="269.0" y2="320.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="264.5" y="309.2" width="9" height="7.2" fill="#777"/>
<line x1="284.0" y1="293.6" x2="284.0" y2="312.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="279.5" y="297.2" width="9" height="12.0" fill="#188a3e"/>
<line x1="299.0" y1="279.2" x2="299.0" y2="304.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="294.5" y="285.2" width="9" height="12.0" fill="#188a3e"/>
<line x1="314.0" y1="272.0" x2="314.0" y2="292.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="309.5" y="278.0" width="9" height="7.2" fill="#188a3e"/>
<line x1="329.0" y1="264.8" x2="329.0" y2="285.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="324.5" y="270.8" width="9" height="7.2" fill="#188a3e"/>
<line x1="344.0" y1="257.6" x2="344.0" y2="278.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="339.5" y="263.6" width="9" height="7.2" fill="#188a3e"/>
<line x1="359.0" y1="250.4" x2="359.0" y2="270.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="354.5" y="256.4" width="9" height="7.2" fill="#188a3e"/>
<line x1="374.0" y1="243.2" x2="374.0" y2="263.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="369.5" y="249.2" width="9" height="7.2" fill="#188a3e"/>
<line x1="389.0" y1="243.2" x2="389.0" y2="261.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="384.5" y="249.2" width="9" height="4.8" fill="#c00"/>
<line x1="404.0" y1="236.0" x2="404.0" y2="258.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="399.5" y="242.0" width="9" height="12.0" fill="#188a3e"/>
<line x1="419.0" y1="230.0" x2="419.0" y2="246.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="414.5" y="236.0" width="9" height="6.0" fill="#188a3e"/>
<line x1="434.0" y1="224.0" x2="434.0" y2="240.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="429.5" y="230.0" width="9" height="6.0" fill="#188a3e"/>
<line x1="449.0" y1="224.0" x2="449.0" y2="244.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="444.5" y="230.0" width="9" height="9.6" fill="#c00"/>
<line x1="464.0" y1="233.6" x2="464.0" y2="258.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="459.5" y="239.6" width="9" height="12.0" fill="#c00"/>
<line x1="479.0" y1="245.6" x2="479.0" y2="266.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="474.5" y="251.6" width="9" height="7.2" fill="#c00"/>
<line x1="494.0" y1="252.8" x2="494.0" y2="270.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="489.5" y="258.8" width="9" height="4.8" fill="#c00"/>
<line x1="509.0" y1="255.2" x2="509.0" y2="270.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="504.5" y="261.2" width="9" height="2.4" fill="#188a3e"/>
<line x1="24" y1="422.0" x2="626" y2="422.0" stroke="#888"/>
<rect x="39.5" y="388.6" width="9" height="33.4" fill="#188a3e" opacity="0.55"/>
<rect x="54.5" y="387.0" width="9" height="35.0" fill="#c00" opacity="0.55"/>
<rect x="69.5" y="390.2" width="9" height="31.8" fill="#188a3e" opacity="0.55"/>
<rect x="84.5" y="385.4" width="9" height="36.6" fill="#c00" opacity="0.55"/>
<rect x="99.5" y="387.8" width="9" height="34.2" fill="#c00" opacity="0.55"/>
<rect x="114.5" y="389.4" width="9" height="32.6" fill="#188a3e" opacity="0.55"/>
<rect x="129.5" y="386.2" width="9" height="35.8" fill="#c00" opacity="0.55"/>
<rect x="144.5" y="388.6" width="9" height="33.4" fill="#c00" opacity="0.55"/>
<rect x="159.5" y="387.0" width="9" height="35.0" fill="#188a3e" opacity="0.55"/>
<rect x="174.5" y="384.6" width="9" height="37.4" fill="#c00" opacity="0.55"/>
<rect x="189.5" y="387.8" width="9" height="34.2" fill="#c00" opacity="0.55"/>
<rect x="204.5" y="386.2" width="9" height="35.8" fill="#c00" opacity="0.55"/>
<rect x="219.5" y="383.8" width="9" height="38.2" fill="#c00" opacity="0.55"/>
<rect x="234.5" y="380.6" width="9" height="41.4" fill="#c00" opacity="0.55"/>
<rect x="249.5" y="360.0" width="9" height="62.0" fill="#c00" opacity="0.55"/>
<rect x="264.5" y="385.4" width="9" height="36.6" fill="#777" opacity="0.55"/>
<rect x="279.5" y="352.0" width="9" height="70.0" fill="#188a3e" opacity="0.55"/>
<rect x="294.5" y="378.2" width="9" height="43.8" fill="#188a3e" opacity="0.55"/>
<rect x="309.5" y="382.2" width="9" height="39.8" fill="#188a3e" opacity="0.55"/>
<rect x="324.5" y="383.8" width="9" height="38.2" fill="#188a3e" opacity="0.55"/>
<rect x="339.5" y="380.6" width="9" height="41.4" fill="#188a3e" opacity="0.55"/>
<rect x="354.5" y="384.6" width="9" height="37.4" fill="#188a3e" opacity="0.55"/>
<rect x="369.5" y="386.2" width="9" height="35.8" fill="#188a3e" opacity="0.55"/>
<rect x="384.5" y="383.0" width="9" height="39.0" fill="#c00" opacity="0.55"/>
<rect x="399.5" y="385.4" width="9" height="36.6" fill="#188a3e" opacity="0.55"/>
<rect x="414.5" y="387.0" width="9" height="35.0" fill="#188a3e" opacity="0.55"/>
<rect x="429.5" y="383.8" width="9" height="38.2" fill="#188a3e" opacity="0.55"/>
<rect x="444.5" y="381.4" width="9" height="40.6" fill="#c00" opacity="0.55"/>
<rect x="459.5" y="379.0" width="9" height="43.0" fill="#c00" opacity="0.55"/>
<rect x="474.5" y="384.6" width="9" height="37.4" fill="#c00" opacity="0.55"/>
<rect x="489.5" y="386.2" width="9" height="35.8" fill="#c00" opacity="0.55"/>
<rect x="504.5" y="385.4" width="9" height="36.6" fill="#188a3e" opacity="0.55"/>
<text x="24" y="346.0" fill="#555">volum</text>
<text x="254.0" y="340.0" fill="#b06000" text-anchor="middle" style="font-weight:bold">doji 50.10 / 49.20</text>
<text x="464.0" y="217.6" fill="#c00" text-anchor="middle" style="font-weight:bold">ieșire pe trail ~52.60</text>
<text x="24" y="444.0" fill="#777">bara 15: close 49.90 sub high-ul dojiului 50.10 — NU confirmă</text>
<text x="24" y="461.0" fill="#188a3e">bara 16: close 50.40 peste 50.10 — confirmare (intrare)</text>
<text x="24" y="486" fill="#555">Intrare la close-ul confirmării, SL la low-ul ultimelor 4 candele, TP1 1:1, apoi trailing stop.</text>
<svg viewBox="0 0 709 739" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif">
<text x="24" y="48" fill="#333" style="font-weight:bold">Buy Doji — un trade de la cap la coadă (daily, exemplu construit)</text>
<rect x="94.5" y="120.0" width="154.0" height="388.0" fill="#c00" fill-opacity="0.08" stroke="#c00" stroke-width="1"/>
<text x="94.5" y="115.0" fill="#c00" style="font-weight:bold">1. scăderea: vânzătorii obosesc</text>
<rect x="244.5" y="318.0" width="34.0" height="194.0" fill="#b06000" fill-opacity="0.08" stroke="#b06000" stroke-width="1"/>
<text x="244.5" y="313.0" fill="#b06000" style="font-weight:bold">2. doji: pauză, încă nu intri</text>
<rect x="274.5" y="358.0" width="19.0" height="134.0" fill="#188a3e" fill-opacity="0.08" stroke="#188a3e" stroke-width="1"/>
<text x="274.5" y="353.0" fill="#188a3e" style="font-weight:bold">3. confirmarea</text>
<rect x="289.5" y="278.0" width="184.0" height="200.0" fill="#1a5fb4" fill-opacity="0.08" stroke="#1a5fb4" stroke-width="1"/>
<text x="289.5" y="273.0" fill="#1a5fb4" style="font-weight:bold">4. ieșirea: o treime la țintă, restul pe trail</text>
<line x1="24" y1="410.0" x2="695" y2="410.0" stroke="#1a5fb4" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30" y="404.0" fill="#1a5fb4">ținta 1: 51.60</text>
<line x1="24" y1="458.0" x2="695" y2="458.0" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30" y="452.0" fill="#188a3e">intrare 50.40</text>
<line x1="24" y1="506.0" x2="695" y2="506.0" stroke="#c00" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30" y="500.0" fill="#c00">stop 49.20</text>
<polyline points="329.0,304.5 344.0,321.4 359.0,335.4 374.0,349.9 389.0,362.5 404.0,372.3 419.0,382.7 434.0,390.8 449.0,395.7 464.0,402.7 479.0,408.1 494.0,411.5 509.0,412.3" fill="none" stroke="#999" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="515" y="406" fill="#999">MA(20)</text>
<line x1="44.0" y1="56.0" x2="44.0" y2="78.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="39.5" y="66.0" width="9" height="1.6" fill="#188a3e"/>
<line x1="59.0" y1="56.0" x2="59.0" y2="118.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="54.5" y="66.0" width="9" height="40.0" fill="#c00"/>
<line x1="74.0" y1="80.0" x2="74.0" y2="118.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="69.5" y="90.0" width="9" height="16.0" fill="#188a3e"/>
<line x1="89.0" y1="80.0" x2="89.0" y2="150.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="84.5" y="90.0" width="9" height="48.0" fill="#c00"/>
<line x1="104.0" y1="128.0" x2="104.0" y2="194.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="99.5" y="138.0" width="9" height="44.0" fill="#c00"/>
<line x1="119.0" y1="156.0" x2="119.0" y2="194.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="114.5" y="166.0" width="9" height="16.0" fill="#188a3e"/>
<line x1="134.0" y1="156.0" x2="134.0" y2="226.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="129.5" y="166.0" width="9" height="48.0" fill="#c00"/>
<line x1="149.0" y1="204.0" x2="149.0" y2="270.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="144.5" y="214.0" width="9" height="44.0" fill="#c00"/>
<line x1="164.0" y1="232.0" x2="164.0" y2="270.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="159.5" y="242.0" width="9" height="16.0" fill="#188a3e"/>
<line x1="179.0" y1="232.0" x2="179.0" y2="298.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="174.5" y="242.0" width="9" height="44.0" fill="#c00"/>
<line x1="194.0" y1="276.0" x2="194.0" y2="346.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="189.5" y="286.0" width="9" height="48.0" fill="#c00"/>
<line x1="209.0" y1="324.0" x2="209.0" y2="394.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="204.5" y="334.0" width="9" height="48.0" fill="#c00"/>
<line x1="224.0" y1="372.0" x2="224.0" y2="446.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="219.5" y="382.0" width="9" height="52.0" fill="#c00"/>
<line x1="239.0" y1="424.0" x2="239.0" y2="500.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="234.5" y="434.0" width="9" height="54.0" fill="#c00"/>
<line x1="254.0" y1="470.0" x2="254.0" y2="504.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="249.5" y="488.0" width="9" height="2.0" fill="#c00"/>
<line x1="269.0" y1="472.0" x2="269.0" y2="496.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="264.5" y="478.0" width="9" height="12.0" fill="#777"/>
<line x1="284.0" y1="452.0" x2="284.0" y2="484.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="279.5" y="458.0" width="9" height="20.0" fill="#188a3e"/>
<line x1="299.0" y1="428.0" x2="299.0" y2="470.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="294.5" y="438.0" width="9" height="20.0" fill="#188a3e"/>
<line x1="314.0" y1="416.0" x2="314.0" y2="450.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="309.5" y="426.0" width="9" height="12.0" fill="#188a3e"/>
<line x1="329.0" y1="404.0" x2="329.0" y2="438.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="324.5" y="414.0" width="9" height="12.0" fill="#188a3e"/>
<line x1="344.0" y1="400.0" x2="344.0" y2="418.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="339.5" y="404.0" width="9" height="10.0" fill="#188a3e"/>
<line x1="359.0" y1="382.0" x2="359.0" y2="396.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="354.5" y="386.0" width="9" height="8.0" fill="#188a3e"/>
<line x1="374.0" y1="376.0" x2="374.0" y2="392.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="369.5" y="380.0" width="9" height="6.0" fill="#188a3e"/>
<line x1="389.0" y1="378.0" x2="389.0" y2="394.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="384.5" y="380.0" width="9" height="10.0" fill="#c00"/>
<line x1="404.0" y1="374.0" x2="404.0" y2="392.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="399.5" y="378.0" width="9" height="12.0" fill="#188a3e"/>
<line x1="419.0" y1="372.0" x2="419.0" y2="384.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="414.5" y="374.0" width="9" height="4.0" fill="#188a3e"/>
<line x1="434.0" y1="372.0" x2="434.0" y2="380.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="429.5" y="374.0" width="9" height="2.0" fill="#c00"/>
<line x1="449.0" y1="350.0" x2="449.0" y2="370.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="444.5" y="356.0" width="9" height="10.0" fill="#188a3e"/>
<line x1="464.0" y1="354.0" x2="464.0" y2="386.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="459.5" y="356.0" width="9" height="26.0" fill="#c00"/>
<line x1="479.0" y1="372.0" x2="479.0" y2="404.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="474.5" y="382.0" width="9" height="12.0" fill="#c00"/>
<line x1="494.0" y1="384.0" x2="494.0" y2="412.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="489.5" y="394.0" width="9" height="8.0" fill="#c00"/>
<line x1="509.0" y1="388.0" x2="509.0" y2="412.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="504.5" y="398.0" width="9" height="4.0" fill="#188a3e"/>
<line x1="24" y1="713.0" x2="695" y2="713.0" stroke="#888"/>
<rect x="39.5" y="684.4" width="9" height="28.6" fill="#188a3e" opacity="0.55"/>
<rect x="54.5" y="683.0" width="9" height="30.0" fill="#c00" opacity="0.55"/>
<rect x="69.5" y="685.7" width="9" height="27.3" fill="#188a3e" opacity="0.55"/>
<rect x="84.5" y="681.6" width="9" height="31.4" fill="#c00" opacity="0.55"/>
<rect x="99.5" y="683.7" width="9" height="29.3" fill="#c00" opacity="0.55"/>
<rect x="114.5" y="685.0" width="9" height="28.0" fill="#188a3e" opacity="0.55"/>
<rect x="129.5" y="682.3" width="9" height="30.7" fill="#c00" opacity="0.55"/>
<rect x="144.5" y="684.4" width="9" height="28.6" fill="#c00" opacity="0.55"/>
<rect x="159.5" y="683.0" width="9" height="30.0" fill="#188a3e" opacity="0.55"/>
<rect x="174.5" y="681.0" width="9" height="32.0" fill="#c00" opacity="0.55"/>
<rect x="189.5" y="683.7" width="9" height="29.3" fill="#c00" opacity="0.55"/>
<rect x="204.5" y="682.3" width="9" height="30.7" fill="#c00" opacity="0.55"/>
<rect x="219.5" y="680.3" width="9" height="32.7" fill="#c00" opacity="0.55"/>
<rect x="234.5" y="677.5" width="9" height="35.5" fill="#c00" opacity="0.55"/>
<rect x="249.5" y="659.8" width="9" height="53.2" fill="#c00" opacity="0.55"/>
<rect x="264.5" y="681.6" width="9" height="31.4" fill="#777" opacity="0.55"/>
<rect x="279.5" y="653.0" width="9" height="60.0" fill="#188a3e" opacity="0.55"/>
<rect x="294.5" y="675.5" width="9" height="37.5" fill="#188a3e" opacity="0.55"/>
<rect x="309.5" y="678.9" width="9" height="34.1" fill="#188a3e" opacity="0.55"/>
<rect x="324.5" y="680.3" width="9" height="32.7" fill="#188a3e" opacity="0.55"/>
<rect x="339.5" y="677.5" width="9" height="35.5" fill="#188a3e" opacity="0.55"/>
<rect x="354.5" y="681.0" width="9" height="32.0" fill="#188a3e" opacity="0.55"/>
<rect x="369.5" y="682.3" width="9" height="30.7" fill="#188a3e" opacity="0.55"/>
<rect x="384.5" y="679.6" width="9" height="33.4" fill="#c00" opacity="0.55"/>
<rect x="399.5" y="681.6" width="9" height="31.4" fill="#188a3e" opacity="0.55"/>
<rect x="414.5" y="683.0" width="9" height="30.0" fill="#188a3e" opacity="0.55"/>
<rect x="429.5" y="680.3" width="9" height="32.7" fill="#c00" opacity="0.55"/>
<rect x="444.5" y="678.2" width="9" height="34.8" fill="#188a3e" opacity="0.55"/>
<rect x="459.5" y="676.2" width="9" height="36.8" fill="#c00" opacity="0.55"/>
<rect x="474.5" y="681.0" width="9" height="32.0" fill="#c00" opacity="0.55"/>
<rect x="489.5" y="682.3" width="9" height="30.7" fill="#c00" opacity="0.55"/>
<rect x="504.5" y="681.6" width="9" height="31.4" fill="#188a3e" opacity="0.55"/>
<text x="24" y="647.0" fill="#555">volum</text>
<line x1="104.0" y1="536.0" x2="246.1" y2="511.4" stroke="#c00" stroke-width="1.8"/>
<polygon points="254.0,510.0 246.8,515.3 245.4,507.4" fill="#c00"/>
<text x="104.0" y="550.0" fill="#c00" text-anchor="middle" style="font-weight:bold">stopul 49.20, 5 cenți sub doji</text>
<text x="104.0" y="564.0" fill="#c00" text-anchor="middle" style="font-weight:bold">sub el, ideea că vânzătorii</text>
<text x="104.0" y="578.0" fill="#c00" text-anchor="middle" style="font-weight:bold">au obosit e moartă</text>
<line x1="274.0" y1="576.0" x2="283.3" y2="470.0" stroke="#188a3e" stroke-width="1.8"/>
<polygon points="284.0,462.0 287.3,470.3 279.3,469.6" fill="#188a3e"/>
<text x="274.0" y="590.0" fill="#188a3e" text-anchor="middle" style="font-weight:bold">AICI INTRI, la close 50.40</text>
<text x="274.0" y="604.0" fill="#188a3e" text-anchor="middle" style="font-weight:bold">abia acum știi că</text>
<text x="274.0" y="618.0" fill="#188a3e" text-anchor="middle" style="font-weight:bold">cumpărătorii au câștigat</text>
<line x1="424.0" y1="520.0" x2="334.3" y2="420.0" stroke="#1a5fb4" stroke-width="1.8"/>
<polygon points="329.0,414.0 337.3,417.3 331.4,422.6" fill="#1a5fb4"/>
<text x="424.0" y="534.0" fill="#1a5fb4" text-anchor="middle" style="font-weight:bold">ținta 1: 51.60 = riscul (1.20)</text>
<text x="424.0" y="548.0" fill="#1a5fb4" text-anchor="middle" style="font-weight:bold">încă o dată: vinzi o treime</text>
<line x1="489.0" y1="320.0" x2="455.7" y2="341.6" stroke="#b06000" stroke-width="1.8"/>
<polygon points="449.0,346.0 453.5,338.3 457.9,345.0" fill="#b06000"/>
<text x="489.0" y="301.0" fill="#b06000" text-anchor="middle" style="font-weight:bold">trailing stop: urcă după preț</text>
<text x="489.0" y="315.0" fill="#b06000" text-anchor="middle" style="font-weight:bold">la fiecare gap, nu coboară</text>
<line x1="542.5" y1="334.0" x2="479.1" y2="377.5" stroke="#c00" stroke-width="1.8"/>
<polygon points="472.5,382.0 476.8,374.2 481.4,380.8" fill="#c00"/>
<text x="546.5" y="331.0" fill="#c00" text-anchor="start" style="font-weight:bold">ieși la 52.30 (+1.58R)</text>
<text x="546.5" y="345.0" fill="#c00" text-anchor="start" style="font-weight:bold">prima închidere sub trail</text>
<polyline points="352.0,396.0 442.0,396.0 442.0,370.0 471.0,370.0" fill="none" stroke="#b06000" stroke-width="2"/>
<polyline points="114.0,460.0 119.0,460.0 119.0,504.0 114.0,504.0" fill="none" stroke="#c00" stroke-width="1.5"/>
<text x="125.0" y="486.0" fill="#c00" style="font-weight:bold">1R = 1.20 (riscul)</text>
<polyline points="114.0,412.0 119.0,412.0 119.0,456.0 114.0,456.0" fill="none" stroke="#1a5fb4" stroke-width="1.5"/>
<text x="125.0" y="438.0" fill="#1a5fb4" style="font-weight:bold">1R = 1.20 (ținta)</text>
</svg>

Before

Width:  |  Height:  |  Size: 9.3 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -23,7 +23,7 @@ import sys
from pathlib import Path
sys.path.insert(0, "/workspace/atm-curs-dl")
from svg_candles import Candle, Chart, Level, Mark, MA, from_closes # noqa: E402
from svg_candles import Arrow, Candle, Chart, Level, Zone, from_closes # noqa: E402
OUT = Path(__file__).resolve().parent / "buy_doji_aplus.svg"
@@ -118,19 +118,25 @@ PW = 560 # lățimea fiecărui panou
ch_a = Chart(
candles=cds_a,
levels=[Level(42.00, "suport 42.00", GREEN, label_at="left")],
marks=[Mark(DOJI_A, "doji la nivel (low 41.95)", ORANGE, "below"),
Mark(CONF_A, "acumulare", GREEN, "above", dy=-6)],
zones=[Zone(DOJI_A, DOJI_A, "", GREEN, p_top=43.2, p_bot=41.7)],
arrows=[Arrow(DOJI_A, "doji chiar pe nivel:\nvânzarea s-a oprit pe suport",
where="below", color=GREEN, dx=-40),
Arrow(CONF_A, "confirmarea, pe volum mare:\ncumpărătorii mari intră",
where="above", color=GREEN, dx=60)],
mas=[], scale=22.0, gap=15, body_w=9, left=44, width=PW, vol_h=60,
vol_label="volum", title="A+ — doji la suport, volum în acumulare",
caption="acumulare: volum peste media ultimelor 10 bare.",
)
ch_n = Chart(
candles=cds_n,
levels=[Level(78.50, "rezistență 78.50", RED, label_at="right")],
marks=[Mark(DOJI_N, "doji 78.50 / 78.10", ORANGE, "below", dy=93)],
# eticheta zonei ar urca peste titlul panoului (zona e chiar în vârf):
# textul stă pe săgeata din stânga
zones=[Zone(DOJI_N - 1, CONF_N, "", RED, p_top=79.62)],
arrows=[Arrow(DOJI_N, "gap-up în rezistență:\naici cumpără cei întârziați",
where="left", color=RED, dx=-30, dy=30),
Arrow(18, "cade înapoi sub 78.00:\nsemnalul a mințit", where="below", color=RED, dx=40)],
mas=[], scale=22.0, gap=15, body_w=9, left=44, width=PW, vol_h=60,
vol_label="volum", title="Mediocru — gap-up în rezistență, volum varză",
caption="gap-up + doji în rezistență, confirmare pe volum slab.",
)
# ============================================================ wrapper: două panouri alăturate
@@ -145,20 +151,51 @@ def vb_height(svg: str) -> float:
return float(m.group(1))
PANEL_GAP, PAD = 24, 8
TITLE_H, FOOTER_H = 30, 22
svg_a, svg_n = ch_a.render(), ch_n.render()
def vol_note(svg: str, i0: int, i1: int, text: str, color: str, box: bool) -> str:
"""Evidențiere în panoul de volum (Zone/Arrow din svg_candles lucrează doar pe preț).
# „gap-up, volum slab" stă în colțul liber din stânga-sus, cu linie indicatoare
# spre golul dintre bara 13 (high 76.80) și dojiul barei 14 (open 78.20).
GAP_X = (ch_n._cx(DOJI_N - 1) + ch_n._cx(DOJI_N)) / 2
GAP_Y = ch_n._y(77.50)
gap_ann = (
f'<text x="28" y="120" fill="{RED}" style="font-weight:bold">gap-up, volum slab</text>'
f'<line x1="152" y1="116" x2="{GAP_X:.1f}" y2="{GAP_Y:.1f}" stroke="{RED}" stroke-width="1"/>'
f'<circle cx="{GAP_X:.1f}" cy="{GAP_Y:.1f}" r="2.5" fill="{RED}"/>'
)
svg_n = svg_n.replace("</svg>", gap_ann + "</svg>")
Coordonatele se citesc din SVG-ul randat (barele de volum sunt rect-urile cu
opacity 0.55, în ordinea candelelor), ca să nu depindă de deplasarea internă
a lui Chart. Eticheta stă sub linia de bază, unde nu acoperă nimic;
`box` = dreptunghi peste bare, altfel săgeată de jos în sus, sub bară.
"""
bars = [tuple(map(float, m)) for m in re.findall(
r'<rect x="([\d.]+)" y="([\d.]+)" width="([\d.]+)" height="([\d.]+)" '
r'fill="#[0-9a-f]+" opacity="0.55"/>', svg)]
base = bars[0][1] + bars[0][3]
x0, x1 = bars[i0][0] - 4, bars[i1][0] + bars[i1][2] + 4
top = min(b[1] for b in bars[i0:i1 + 1]) - 4
if box:
mark = (f'<rect x="{x0:.1f}" y="{top:.1f}" width="{x1 - x0:.1f}" height="{base - top:.1f}" '
f'fill="{color}" fill-opacity="0.12" stroke="{color}" stroke-width="1"/>')
ty = base + 15
else:
cx = (x0 + x1) / 2
mark = (f'<line x1="{cx:.1f}" y1="{base + 22:.1f}" x2="{cx:.1f}" y2="{base + 9:.1f}" '
f'stroke="{color}" stroke-width="1.8"/>'
f'<polygon points="{cx:.1f},{base + 2:.1f} {cx - 4:.1f},{base + 10:.1f} '
f'{cx + 4:.1f},{base + 10:.1f}" fill="{color}"/>')
ty = base + 34
label = (f'<text x="{x0:.1f}" y="{ty:.1f}" fill="{color}" '
f'style="font-weight:bold">{text}</text>')
# dreptunghiul/săgeata în spatele barelor, eticheta la final
i = svg.index('<rect', svg.index(f'y1="{base:.1f}"'))
svg = svg[:i] + mark + svg[i:]
return svg.replace("</svg>", label + "</svg>")
def grow(svg: str, dh: float) -> str:
"""Mărește viewBox-ul unui panou cu dh px jos, pentru eticheta de sub volum."""
h = vb_height(svg)
return svg.replace(f'0 0 {PW} {h:.0f}"', f'0 0 {PW} {h + dh:.0f}"', 1)
PANEL_GAP, PAD = 24, 8
TITLE_H, FOOTER_H = 30, 0
svg_a = grow(vol_note(ch_a.render(), CONF_A, CONF_A + 4,
"volum în creștere = acumulare", GREEN, box=True), 10)
svg_n = grow(vol_note(ch_n.render(), CONF_N, CONF_N,
"volum slab: nimeni mare nu cumpără", RED, box=False), 30)
HA, HN = vb_height(svg_a), vb_height(svg_n)
assert svg_a.count("\n\n") == 0 and svg_n.count("\n\n") == 0, "linie goală în panou"
@@ -168,9 +205,6 @@ TOTAL_H = PAD + TITLE_H + max(HA, HN) + FOOTER_H + PAD
OFF_A = (PAD, PAD + TITLE_H)
OFF_N = (PAD + PW + PANEL_GAP, PAD + TITLE_H)
FOOTER = ("Surse: 13_strategia_3_byh.md:188-190 (doji la nivel); "
"01_buy_doji_si_strategia_mici.md:227-235 (context invalid).")
wrapper = (
f'<svg viewBox="0 0 {TOTAL_W} {TOTAL_H:.0f}" width="{TOTAL_W}" height="{TOTAL_H:.0f}" '
f'xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif">'
@@ -178,8 +212,6 @@ wrapper = (
f'style="font-weight:bold">Setup A+ vs. setup mediocru (două panouri, exemple construite)</text>'
f'<g transform="translate({OFF_A[0]},{OFF_A[1]})">{inner(svg_a)}</g>'
f'<g transform="translate({OFF_N[0]},{OFF_N[1]})">{inner(svg_n)}</g>'
f'<text x="{TOTAL_W / 2:.0f}" y="{TOTAL_H - PAD:.0f}" fill="#555" '
f'text-anchor="middle">{FOOTER}</text>'
f'</svg>'
)
@@ -217,8 +249,7 @@ for frag, (ox, oy) in ((inner(svg_a), OFF_A), (inner(svg_n), OFF_N)):
all_txt.append((gx, gy, anchor, t))
# textele din wrapper (titlu + footer), în coordonate globale
for x, y, anchor, t in ((TOTAL_W / 2, 20.0, "middle",
"Setup A+ vs. setup mediocru (două panouri, exemple construite)"),
(TOTAL_W / 2, TOTAL_H - PAD, "middle", FOOTER)):
"Setup A+ vs. setup mediocru (două panouri, exemple construite)"),):
gl, gr = span(x, anchor, t)
assert -1 <= gl and gr <= TOTAL_W + 1, f"text din wrapper iese din pânză: {t!r}"
assert 0 <= y <= TOTAL_H, f"text din wrapper în afara înălțimii: {t!r}"
@@ -236,8 +267,10 @@ for i in range(len(all_txt)):
raise AssertionError(f"texte suprapuse: {si!r} / {sj!r}")
# etichetele cerute de spec există în desen
for cheie in ("suport 42.00", "doji la nivel", "acumulare",
"rezistență 78.50", "gap-up, volum slab",
assert "Surse" not in wrapper and ".md:" not in wrapper, "trimiteri la surse în SVG"
for cheie in ("suport 42.00", "doji chiar pe nivel", "vânzarea s-a oprit", "volum în creștere = acumulare",
"rezistență 78.50", "gap-up în rezistență", "cei întârziați",
"semnalul a mințit", "volum slab: nimeni mare nu cumpără",
"A+ — doji la suport, volum în acumulare",
"Mediocru — gap-up în rezistență, volum varză"):
assert cheie in wrapper, f"lipsește din desen: {cheie!r}"

View File

@@ -29,11 +29,18 @@ STRUCTURA SERIEI
Panoul A+ (24 candele): downtrend de la 52 la ~42.60 (10 bare), apoi doji
cu low 41.95 / high 42.90 care „stă" pe suportul 42.00 (low-ul e la 0.1 %
sub nivel), apoi confirmare close 43.60 (> high-ul dojiului) cu volum peste
media pe 10 bare. Etichete: „suport 42.00", „doji la nivel", „acumulare".
media pe 10 bare. Adnotări: zonă verde peste doji („doji chiar pe nivel: vânzarea s-a oprit pe
suport"), zonă verde peste barele de volum ale confirmării („volum în
creștere = acumulare"), săgeată spre confirmare („confirmarea, pe volum
mare: cumpărătorii mari intră"). Level „suport 42.00".
Panoul NU (24 candele): uptrend de la 70 la ~77, apoi un gap-up de la 76.80
la open 78.20, doji cu high 79.00 / low 78.10 chiar sub rezistența 78.50,
apoi confirmare close 79.30 pe volum sub media pe 10 bare, după care prețul
cade înapoi sub 78.00. Etichete: „rezistență 78.50", „gap-up, volum slab".
cade înapoi sub 78.00. Adnotări: zonă roșie peste gap-up + doji + confirmare, cu săgeata „gap-up în
rezistență: aici cumpără cei întârziați"; săgeată spre volumul confirmării
(„volum slab: nimeni mare nu cumpără"); săgeată spre căderea de după („cade
înapoi sub 78.00: semnalul a mințit"). Level „rezistență 78.50".
Fără linie de surse în SVG — trimiterile stau la finalul capitolului.
Nivelurile 42.00 / 78.50 / cifrele de preț sunt construite (materialul nu dă
prețuri pentru acest contrast); regulile și citatele de mai sus sunt din curs.

View File

@@ -1,5 +1,6 @@
<svg viewBox="0 0 1160 480" width="1160" height="480" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif"><text x="580" y="20" fill="#333" text-anchor="middle" style="font-weight:bold">Setup A+ vs. setup mediocru (două panouri, exemple construite)</text><g transform="translate(8,38)">
<svg viewBox="0 0 1160 519" width="1160" height="519" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif"><text x="580" y="20" fill="#333" text-anchor="middle" style="font-weight:bold">Setup A+ vs. setup mediocru (două panouri, exemple construite)</text><g transform="translate(8,38)">
<text x="24" y="48" fill="#333" style="font-weight:bold">A+ — doji la suport, volum în acumulare</text>
<rect x="184.5" y="256.2" width="19.0" height="33.0" fill="#188a3e" fill-opacity="0.08" stroke="#188a3e" stroke-width="1"/>
<line x1="24" y1="282.6" x2="546" y2="282.6" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30" y="276.6" fill="#188a3e">suport 42.00</text>
<line x1="44.0" y1="56.0" x2="44.0" y2="78.0" stroke="#1a1a1a" stroke-width="1.2"/>
@@ -50,113 +51,125 @@
<rect x="369.5" y="177.0" width="9" height="6.6" fill="#188a3e"/>
<line x1="389.0" y1="163.8" x2="389.0" y2="183.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="384.5" y="170.4" width="9" height="6.6" fill="#188a3e"/>
<line x1="24" y1="369.7" x2="546" y2="369.7" stroke="#888"/>
<rect x="39.5" y="336.1" width="9" height="33.6" fill="#c00" opacity="0.55"/>
<rect x="54.5" y="337.9" width="9" height="31.8" fill="#c00" opacity="0.55"/>
<rect x="69.5" y="339.1" width="9" height="30.6" fill="#c00" opacity="0.55"/>
<rect x="84.5" y="340.3" width="9" height="29.4" fill="#c00" opacity="0.55"/>
<rect x="99.5" y="341.5" width="9" height="28.2" fill="#c00" opacity="0.55"/>
<rect x="114.5" y="342.7" width="9" height="27.0" fill="#c00" opacity="0.55"/>
<rect x="129.5" y="343.3" width="9" height="26.4" fill="#c00" opacity="0.55"/>
<rect x="144.5" y="344.5" width="9" height="25.2" fill="#c00" opacity="0.55"/>
<rect x="159.5" y="345.1" width="9" height="24.6" fill="#c00" opacity="0.55"/>
<rect x="174.5" y="346.3" width="9" height="23.4" fill="#c00" opacity="0.55"/>
<rect x="189.5" y="333.7" width="9" height="36.0" fill="#188a3e" opacity="0.55"/>
<rect x="204.5" y="318.1" width="9" height="51.6" fill="#188a3e" opacity="0.55"/>
<rect x="219.5" y="326.5" width="9" height="43.2" fill="#188a3e" opacity="0.55"/>
<rect x="234.5" y="324.7" width="9" height="45.0" fill="#188a3e" opacity="0.55"/>
<rect x="249.5" y="327.7" width="9" height="42.0" fill="#c00" opacity="0.55"/>
<rect x="264.5" y="322.9" width="9" height="46.8" fill="#188a3e" opacity="0.55"/>
<rect x="279.5" y="320.5" width="9" height="49.2" fill="#188a3e" opacity="0.55"/>
<rect x="294.5" y="321.7" width="9" height="48.0" fill="#c00" opacity="0.55"/>
<rect x="309.5" y="318.7" width="9" height="51.0" fill="#188a3e" opacity="0.55"/>
<rect x="324.5" y="316.9" width="9" height="52.8" fill="#188a3e" opacity="0.55"/>
<rect x="339.5" y="314.5" width="9" height="55.2" fill="#188a3e" opacity="0.55"/>
<rect x="354.5" y="312.7" width="9" height="57.0" fill="#188a3e" opacity="0.55"/>
<rect x="369.5" y="310.9" width="9" height="58.8" fill="#188a3e" opacity="0.55"/>
<rect x="384.5" y="309.7" width="9" height="60.0" fill="#188a3e" opacity="0.55"/>
<text x="24" y="303.7" fill="#555">volum</text>
<text x="194.0" y="297.7" fill="#b06000" text-anchor="middle" style="font-weight:bold">doji la nivel (low 41.95)</text>
<text x="209.0" y="225.9" fill="#188a3e" text-anchor="middle" style="font-weight:bold">acumulare</text>
<text x="24" y="400" fill="#555">acumulare: volum peste media ultimelor 10 bare.</text>
</g><g transform="translate(592,38)">
<line x1="24" y1="436.7" x2="546" y2="436.7" stroke="#888"/>
<rect x="200.5" y="381.1" width="77.0" height="55.6" fill="#188a3e" fill-opacity="0.12" stroke="#188a3e" stroke-width="1"/><rect x="39.5" y="403.1" width="9" height="33.6" fill="#c00" opacity="0.55"/>
<rect x="54.5" y="404.9" width="9" height="31.8" fill="#c00" opacity="0.55"/>
<rect x="69.5" y="406.1" width="9" height="30.6" fill="#c00" opacity="0.55"/>
<rect x="84.5" y="407.3" width="9" height="29.4" fill="#c00" opacity="0.55"/>
<rect x="99.5" y="408.5" width="9" height="28.2" fill="#c00" opacity="0.55"/>
<rect x="114.5" y="409.7" width="9" height="27.0" fill="#c00" opacity="0.55"/>
<rect x="129.5" y="410.3" width="9" height="26.4" fill="#c00" opacity="0.55"/>
<rect x="144.5" y="411.5" width="9" height="25.2" fill="#c00" opacity="0.55"/>
<rect x="159.5" y="412.1" width="9" height="24.6" fill="#c00" opacity="0.55"/>
<rect x="174.5" y="413.3" width="9" height="23.4" fill="#c00" opacity="0.55"/>
<rect x="189.5" y="400.7" width="9" height="36.0" fill="#188a3e" opacity="0.55"/>
<rect x="204.5" y="385.1" width="9" height="51.6" fill="#188a3e" opacity="0.55"/>
<rect x="219.5" y="393.5" width="9" height="43.2" fill="#188a3e" opacity="0.55"/>
<rect x="234.5" y="391.7" width="9" height="45.0" fill="#188a3e" opacity="0.55"/>
<rect x="249.5" y="394.7" width="9" height="42.0" fill="#c00" opacity="0.55"/>
<rect x="264.5" y="389.9" width="9" height="46.8" fill="#188a3e" opacity="0.55"/>
<rect x="279.5" y="387.5" width="9" height="49.2" fill="#188a3e" opacity="0.55"/>
<rect x="294.5" y="388.7" width="9" height="48.0" fill="#c00" opacity="0.55"/>
<rect x="309.5" y="385.7" width="9" height="51.0" fill="#188a3e" opacity="0.55"/>
<rect x="324.5" y="383.9" width="9" height="52.8" fill="#188a3e" opacity="0.55"/>
<rect x="339.5" y="381.5" width="9" height="55.2" fill="#188a3e" opacity="0.55"/>
<rect x="354.5" y="379.7" width="9" height="57.0" fill="#188a3e" opacity="0.55"/>
<rect x="369.5" y="377.9" width="9" height="58.8" fill="#188a3e" opacity="0.55"/>
<rect x="384.5" y="376.7" width="9" height="60.0" fill="#188a3e" opacity="0.55"/>
<text x="24" y="370.7" fill="#555">volum</text>
<line x1="154.0" y1="313.7" x2="187.3" y2="292.1" stroke="#188a3e" stroke-width="1.8"/>
<polygon points="194.0,287.7 189.5,295.4 185.1,288.7" fill="#188a3e"/>
<text x="154.0" y="327.7" fill="#188a3e" text-anchor="middle" style="font-weight:bold">doji chiar pe nivel:</text>
<text x="154.0" y="341.7" fill="#188a3e" text-anchor="middle" style="font-weight:bold">vânzarea s-a oprit pe suport</text>
<line x1="269.0" y1="169.0" x2="214.3" y2="231.9" stroke="#188a3e" stroke-width="1.8"/>
<polygon points="209.0,237.9 211.2,229.2 217.3,234.5" fill="#188a3e"/>
<text x="269.0" y="150.0" fill="#188a3e" text-anchor="middle" style="font-weight:bold">confirmarea, pe volum mare:</text>
<text x="269.0" y="164.0" fill="#188a3e" text-anchor="middle" style="font-weight:bold">cumpărătorii mari intră</text>
<text x="200.5" y="451.7" fill="#188a3e" style="font-weight:bold">volum în creștere = acumulare</text></g><g transform="translate(592,38)">
<text x="24" y="48" fill="#333" style="font-weight:bold">Mediocru — gap-up în rezistență, volum varză</text>
<line x1="24" y1="78.0" x2="546" y2="78.0" stroke="#c00" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="532" y="72.0" fill="#c00" text-anchor="end">rezistență 78.50</text>
<line x1="44.0" y1="249.6" x2="44.0" y2="269.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="39.5" y="254.0" width="9" height="11.0" fill="#188a3e"/>
<line x1="59.0" y1="238.6" x2="59.0" y2="258.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="54.5" y="243.0" width="9" height="11.0" fill="#188a3e"/>
<line x1="74.0" y1="226.5" x2="74.0" y2="246.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="69.5" y="230.9" width="9" height="12.1" fill="#188a3e"/>
<line x1="89.0" y1="214.4" x2="89.0" y2="234.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="84.5" y="218.8" width="9" height="12.1" fill="#188a3e"/>
<line x1="104.0" y1="203.4" x2="104.0" y2="222.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="99.5" y="207.8" width="9" height="11.0" fill="#188a3e"/>
<line x1="119.0" y1="192.4" x2="119.0" y2="211.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="114.5" y="196.8" width="9" height="11.0" fill="#188a3e"/>
<line x1="134.0" y1="181.4" x2="134.0" y2="200.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="129.5" y="185.8" width="9" height="11.0" fill="#188a3e"/>
<line x1="149.0" y1="171.5" x2="149.0" y2="189.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="144.5" y="175.9" width="9" height="9.9" fill="#188a3e"/>
<line x1="164.0" y1="161.6" x2="164.0" y2="179.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="159.5" y="166.0" width="9" height="9.9" fill="#188a3e"/>
<line x1="179.0" y1="151.7" x2="179.0" y2="169.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="174.5" y="156.1" width="9" height="9.9" fill="#188a3e"/>
<line x1="194.0" y1="141.8" x2="194.0" y2="159.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="189.5" y="146.2" width="9" height="9.9" fill="#188a3e"/>
<line x1="209.0" y1="133.0" x2="209.0" y2="149.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="204.5" y="137.4" width="9" height="8.8" fill="#188a3e"/>
<line x1="224.0" y1="124.2" x2="224.0" y2="140.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="219.5" y="128.6" width="9" height="8.8" fill="#188a3e"/>
<line x1="239.0" y1="115.4" x2="239.0" y2="131.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="234.5" y="115.4" width="9" height="13.2" fill="#188a3e"/>
<line x1="254.0" y1="78.0" x2="254.0" y2="86.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="249.5" y="84.6" width="9" height="1.6" fill="#188a3e"/>
<line x1="269.0" y1="56.0" x2="269.0" y2="86.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="264.5" y="60.4" width="9" height="24.2" fill="#188a3e"/>
<line x1="284.0" y1="58.2" x2="284.0" y2="80.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="279.5" y="60.4" width="9" height="15.4" fill="#c00"/>
<line x1="299.0" y1="73.6" x2="299.0" y2="93.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="294.5" y="75.8" width="9" height="13.2" fill="#c00"/>
<line x1="314.0" y1="86.8" x2="314.0" y2="106.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="309.5" y="89.0" width="9" height="13.2" fill="#c00"/>
<line x1="329.0" y1="98.9" x2="329.0" y2="115.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="324.5" y="102.2" width="9" height="8.8" fill="#c00"/>
<line x1="344.0" y1="107.7" x2="344.0" y2="124.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="339.5" y="111.0" width="9" height="8.8" fill="#c00"/>
<line x1="359.0" y1="116.5" x2="359.0" y2="130.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="354.5" y="119.8" width="9" height="6.6" fill="#c00"/>
<line x1="374.0" y1="124.2" x2="374.0" y2="137.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="369.5" y="126.4" width="9" height="6.6" fill="#c00"/>
<line x1="389.0" y1="129.7" x2="389.0" y2="144.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="384.5" y="133.0" width="9" height="6.6" fill="#c00"/>
<line x1="24" y1="355.4" x2="546" y2="355.4" stroke="#888"/>
<rect x="39.5" y="311.8" width="9" height="43.6" fill="#188a3e" opacity="0.55"/>
<rect x="54.5" y="309.9" width="9" height="45.5" fill="#188a3e" opacity="0.55"/>
<rect x="69.5" y="310.9" width="9" height="44.5" fill="#188a3e" opacity="0.55"/>
<rect x="84.5" y="308.1" width="9" height="47.3" fill="#188a3e" opacity="0.55"/>
<rect x="99.5" y="309.0" width="9" height="46.4" fill="#188a3e" opacity="0.55"/>
<rect x="114.5" y="306.3" width="9" height="49.1" fill="#188a3e" opacity="0.55"/>
<rect x="129.5" y="307.2" width="9" height="48.2" fill="#188a3e" opacity="0.55"/>
<rect x="144.5" y="304.5" width="9" height="50.9" fill="#188a3e" opacity="0.55"/>
<rect x="159.5" y="305.4" width="9" height="50.0" fill="#188a3e" opacity="0.55"/>
<rect x="174.5" y="302.7" width="9" height="52.7" fill="#188a3e" opacity="0.55"/>
<rect x="189.5" y="303.6" width="9" height="51.8" fill="#188a3e" opacity="0.55"/>
<rect x="204.5" y="300.9" width="9" height="54.5" fill="#188a3e" opacity="0.55"/>
<rect x="219.5" y="301.8" width="9" height="53.6" fill="#188a3e" opacity="0.55"/>
<rect x="234.5" y="299.0" width="9" height="56.4" fill="#188a3e" opacity="0.55"/>
<rect x="249.5" y="302.7" width="9" height="52.7" fill="#188a3e" opacity="0.55"/>
<rect x="264.5" y="328.1" width="9" height="27.3" fill="#188a3e" opacity="0.55"/>
<rect x="279.5" y="305.4" width="9" height="50.0" fill="#c00" opacity="0.55"/>
<rect x="294.5" y="300.9" width="9" height="54.5" fill="#c00" opacity="0.55"/>
<rect x="309.5" y="297.2" width="9" height="58.2" fill="#c00" opacity="0.55"/>
<rect x="324.5" y="299.0" width="9" height="56.4" fill="#c00" opacity="0.55"/>
<rect x="339.5" y="295.4" width="9" height="60.0" fill="#c00" opacity="0.55"/>
<rect x="354.5" y="298.1" width="9" height="57.3" fill="#c00" opacity="0.55"/>
<rect x="369.5" y="296.3" width="9" height="59.1" fill="#c00" opacity="0.55"/>
<rect x="384.5" y="299.9" width="9" height="55.5" fill="#c00" opacity="0.55"/>
<text x="24" y="289.4" fill="#555">volum</text>
<text x="254.0" y="199.8" fill="#b06000" text-anchor="middle" style="font-weight:bold">doji 78.50 / 78.10</text>
<text x="24" y="385" fill="#555">gap-up + doji în rezistență, confirmare pe volum slab.</text>
<text x="28" y="120" fill="#c00" style="font-weight:bold">gap-up, volum slab</text><line x1="152" y1="116" x2="246.5" y2="100.0" stroke="#c00" stroke-width="1"/><circle cx="246.5" cy="100.0" r="2.5" fill="#c00"/></g><text x="580" y="472" fill="#555" text-anchor="middle">Surse: 13_strategia_3_byh.md:188-190 (doji la nivel); 01_buy_doji_si_strategia_mici.md:227-235 (context invalid).</text></svg>
<rect x="229.5" y="56.0" width="49.0" height="86.5" fill="#c00" fill-opacity="0.08" stroke="#c00" stroke-width="1"/>
<line x1="24" y1="80.6" x2="546" y2="80.6" stroke="#c00" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="532" y="74.6" fill="#c00" text-anchor="end">rezistență 78.50</text>
<line x1="44.0" y1="252.2" x2="44.0" y2="272.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="39.5" y="256.6" width="9" height="11.0" fill="#188a3e"/>
<line x1="59.0" y1="241.2" x2="59.0" y2="261.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="54.5" y="245.6" width="9" height="11.0" fill="#188a3e"/>
<line x1="74.0" y1="229.1" x2="74.0" y2="248.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="69.5" y="233.5" width="9" height="12.1" fill="#188a3e"/>
<line x1="89.0" y1="217.0" x2="89.0" y2="236.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="84.5" y="221.4" width="9" height="12.1" fill="#188a3e"/>
<line x1="104.0" y1="206.0" x2="104.0" y2="224.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="99.5" y="210.4" width="9" height="11.0" fill="#188a3e"/>
<line x1="119.0" y1="195.0" x2="119.0" y2="213.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="114.5" y="199.4" width="9" height="11.0" fill="#188a3e"/>
<line x1="134.0" y1="184.0" x2="134.0" y2="202.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="129.5" y="188.4" width="9" height="11.0" fill="#188a3e"/>
<line x1="149.0" y1="174.1" x2="149.0" y2="191.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="144.5" y="178.5" width="9" height="9.9" fill="#188a3e"/>
<line x1="164.0" y1="164.2" x2="164.0" y2="181.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="159.5" y="168.6" width="9" height="9.9" fill="#188a3e"/>
<line x1="179.0" y1="154.3" x2="179.0" y2="171.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="174.5" y="158.7" width="9" height="9.9" fill="#188a3e"/>
<line x1="194.0" y1="144.4" x2="194.0" y2="162.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="189.5" y="148.8" width="9" height="9.9" fill="#188a3e"/>
<line x1="209.0" y1="135.6" x2="209.0" y2="152.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="204.5" y="140.0" width="9" height="8.8" fill="#188a3e"/>
<line x1="224.0" y1="126.8" x2="224.0" y2="143.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="219.5" y="131.2" width="9" height="8.8" fill="#188a3e"/>
<line x1="239.0" y1="118.0" x2="239.0" y2="134.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="234.5" y="118.0" width="9" height="13.2" fill="#188a3e"/>
<line x1="254.0" y1="80.6" x2="254.0" y2="89.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="249.5" y="87.2" width="9" height="1.6" fill="#188a3e"/>
<line x1="269.0" y1="58.6" x2="269.0" y2="89.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="264.5" y="63.0" width="9" height="24.2" fill="#188a3e"/>
<line x1="284.0" y1="60.8" x2="284.0" y2="82.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="279.5" y="63.0" width="9" height="15.4" fill="#c00"/>
<line x1="299.0" y1="76.2" x2="299.0" y2="96.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="294.5" y="78.4" width="9" height="13.2" fill="#c00"/>
<line x1="314.0" y1="89.4" x2="314.0" y2="109.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="309.5" y="91.6" width="9" height="13.2" fill="#c00"/>
<line x1="329.0" y1="101.5" x2="329.0" y2="118.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="324.5" y="104.8" width="9" height="8.8" fill="#c00"/>
<line x1="344.0" y1="110.3" x2="344.0" y2="126.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="339.5" y="113.6" width="9" height="8.8" fill="#c00"/>
<line x1="359.0" y1="119.1" x2="359.0" y2="133.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="354.5" y="122.4" width="9" height="6.6" fill="#c00"/>
<line x1="374.0" y1="126.8" x2="374.0" y2="140.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="369.5" y="129.0" width="9" height="6.6" fill="#c00"/>
<line x1="389.0" y1="132.3" x2="389.0" y2="146.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="384.5" y="135.6" width="9" height="6.6" fill="#c00"/>
<line x1="24" y1="358.0" x2="546" y2="358.0" stroke="#888"/>
<line x1="269.0" y1="380.0" x2="269.0" y2="367.0" stroke="#c00" stroke-width="1.8"/><polygon points="269.0,360.0 265.0,368.0 273.0,368.0" fill="#c00"/><rect x="39.5" y="314.4" width="9" height="43.6" fill="#188a3e" opacity="0.55"/>
<rect x="54.5" y="312.6" width="9" height="45.5" fill="#188a3e" opacity="0.55"/>
<rect x="69.5" y="313.5" width="9" height="44.5" fill="#188a3e" opacity="0.55"/>
<rect x="84.5" y="310.8" width="9" height="47.3" fill="#188a3e" opacity="0.55"/>
<rect x="99.5" y="311.7" width="9" height="46.4" fill="#188a3e" opacity="0.55"/>
<rect x="114.5" y="308.9" width="9" height="49.1" fill="#188a3e" opacity="0.55"/>
<rect x="129.5" y="309.9" width="9" height="48.2" fill="#188a3e" opacity="0.55"/>
<rect x="144.5" y="307.1" width="9" height="50.9" fill="#188a3e" opacity="0.55"/>
<rect x="159.5" y="308.0" width="9" height="50.0" fill="#188a3e" opacity="0.55"/>
<rect x="174.5" y="305.3" width="9" height="52.7" fill="#188a3e" opacity="0.55"/>
<rect x="189.5" y="306.2" width="9" height="51.8" fill="#188a3e" opacity="0.55"/>
<rect x="204.5" y="303.5" width="9" height="54.5" fill="#188a3e" opacity="0.55"/>
<rect x="219.5" y="304.4" width="9" height="53.6" fill="#188a3e" opacity="0.55"/>
<rect x="234.5" y="301.7" width="9" height="56.4" fill="#188a3e" opacity="0.55"/>
<rect x="249.5" y="305.3" width="9" height="52.7" fill="#188a3e" opacity="0.55"/>
<rect x="264.5" y="330.8" width="9" height="27.3" fill="#188a3e" opacity="0.55"/>
<rect x="279.5" y="308.0" width="9" height="50.0" fill="#c00" opacity="0.55"/>
<rect x="294.5" y="303.5" width="9" height="54.5" fill="#c00" opacity="0.55"/>
<rect x="309.5" y="299.9" width="9" height="58.2" fill="#c00" opacity="0.55"/>
<rect x="324.5" y="301.7" width="9" height="56.4" fill="#c00" opacity="0.55"/>
<rect x="339.5" y="298.0" width="9" height="60.0" fill="#c00" opacity="0.55"/>
<rect x="354.5" y="300.8" width="9" height="57.3" fill="#c00" opacity="0.55"/>
<rect x="369.5" y="298.9" width="9" height="59.1" fill="#c00" opacity="0.55"/>
<rect x="384.5" y="302.6" width="9" height="55.5" fill="#c00" opacity="0.55"/>
<text x="24" y="292.0" fill="#555">volum</text>
<line x1="185.5" y1="117.2" x2="238.3" y2="90.8" stroke="#c00" stroke-width="1.8"/>
<polygon points="245.5,87.2 240.1,94.4 236.6,87.2" fill="#c00"/>
<text x="181.5" y="114.2" fill="#c00" text-anchor="end" style="font-weight:bold">gap-up în rezistență:</text>
<text x="181.5" y="128.2" fill="#c00" text-anchor="end" style="font-weight:bold">aici cumpără cei întârziați</text>
<line x1="354.0" y1="154.6" x2="319.6" y2="119.0" stroke="#c00" stroke-width="1.8"/>
<polygon points="314.0,113.2 322.4,116.2 316.7,121.8" fill="#c00"/>
<text x="354.0" y="168.6" fill="#c00" text-anchor="middle" style="font-weight:bold">cade înapoi sub 78.00:</text>
<text x="354.0" y="182.6" fill="#c00" text-anchor="middle" style="font-weight:bold">semnalul a mințit</text>
<text x="260.5" y="392.0" fill="#c00" style="font-weight:bold">volum slab: nimeni mare nu cumpără</text></g></svg>

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -12,7 +12,7 @@ Rulare: python3 gen/strategii/buy_doji_directie.py
from pathlib import Path
OUT = Path(__file__).with_suffix(".svg")
W = 720
W = 900
def trend(start, closes, wick=0.15):
@@ -55,10 +55,11 @@ for name, (o, h, l, c) in (("doji weekly", WK[7]), ("doji daily", DY[9])):
assert WK[8][3] > WK[7][1], "weekly: fără confirmare"
assert DY[10][3] < DY[9][2], "daily: fără confirmare Sell Doji"
ENTRY = DY[10][3]
SL = max(b[1] for b in DY[7:11])
# stopul: 5 cenți peste high-ul ultimelor 4 candele, ca la pasul 5 (oglindit)
SL = round(max(b[1] for b in DY[7:11]) + 0.05, 2)
RISK = round(SL - ENTRY, 2)
TP1 = round(ENTRY - RISK, 2)
assert eq(ENTRY, 83.60) and eq(SL, 84.80) and eq(RISK, 1.20) and eq(TP1, 82.40)
assert eq(ENTRY, 83.60) and eq(SL, 84.85) and eq(RISK, 1.25) and eq(TP1, 82.35)
LOW_AFTER = min(b[2] for b in DY[11:])
assert eq(LOW_AFTER, 83.00) and LOW_AFTER > TP1, "TP1 atins"
HIT = next(i for i in range(11, 17) if DY[i][1] >= SL - 1e-9)
@@ -89,6 +90,16 @@ def rect(x, y, w, h, fill, opacity, stroke="none"):
f'fill-opacity="{opacity}" stroke="{stroke}" rx="3"/>')
def arrow(x1, y1, x2, y2, color):
"""Săgeată de la (x1,y1) la vârful (x2,y2): linie + cap triunghi."""
d = max(((x2 - x1) ** 2 + (y2 - y1) ** 2) ** 0.5, 1e-9)
ux, uy = (x2 - x1) / d, (y2 - y1) / d
bx, by = x2 - 9 * ux, y2 - 9 * uy
line(x1, y1, bx, by, color, 1.8)
out.append(f'<polygon points="{x2:.1f},{y2:.1f} {bx - 4.5 * uy:.1f},{by + 4.5 * ux:.1f} '
f'{bx + 4.5 * uy:.1f},{by - 4.5 * ux:.1f}" fill="{color}"/>')
def candles(bars, x0, gap, yf):
for i, (o, h, l, c) in enumerate(bars):
cx = x0 + i * gap
@@ -112,11 +123,12 @@ rect(xw(7) - 8, yw(WK[8][1]) - 4, WGAP + 16, yw(WK[7][2]) - yw(WK[8][1]) + 8,
GREEN, 0.12, GREEN)
candles(WK, WX0, WGAP, yw)
text(xw(7), yw(WK[7][2]) + 16, "doji weekly", fill=ORANGE, anchor="middle", bold=True)
text(xw(9) + 14, yw(WK[8][3]) + 4, "Buy Doji weekly: direcția = long", fill=GREEN, bold=True)
# insigna de direcție
rect(470, 66, 230, 58, GREEN, 0.10, GREEN)
text(585, 90, "WEEKLY: LONG ↑", fill=GREEN, anchor="middle", bold=True, size=16)
text(585, 110, "confirmare 81.30 &gt; high doji 79.80", fill=GREEN, anchor="middle", size=11)
# săgeata weekly: ce + de ce
arrow(300, yw(WK[8][3]) - 6, xw(8) + 12, yw(WK[8][3]) - 6, GREEN)
text(306, yw(WK[8][3]) - 10, "weekly: Buy Doji confirmat (close 81.30, peste high-ul doji-ului 79.80)",
fill=GREEN, bold=True)
text(306, yw(WK[8][3]) + 8, "deci direcția permisă e LONG: pe daily cauți doar Buy Doji",
fill=GREEN)
w_bottom = yw(min(b[2] for b in WK))
# ---- panoul de jos: daily -----------------------------------------------------
@@ -136,42 +148,33 @@ rect(xd(9) - 8, yd(DY[9][1]) - 3, DGAP + 16, yd(DY[10][2]) - yd(DY[9][1]) + 6, O
line(LX1, y_sl, LX2, y_sl, RED, 1.5, "6 3")
line(xd(10) - 8, y_e, LX2, y_e, ORANGE, 1.5, "6 3")
line(xd(10) - 8, y_tp, LX2, y_tp, GRAY, 1.5, "2 3")
text(COL, y_sl + 4, "SL 84.80 = high 4 candele", fill=RED, size=11)
text(COL, y_sl + 4, "stop 84.85 = 5 cenți peste high-ul de 4 candele", fill=RED, size=11)
text(COL, y_e + 4, "intrare short 83.60", fill=ORANGE, size=11)
text(COL, y_tp + 4, "TP1 82.40 — neatins", fill=GRAY, size=11)
text(COL, y_tp + 4, "ținta 82.35 — neatinsă (a scăzut o zi, la 83.00)",
fill=GRAY, size=11)
candles(DY, DX0, DGAP, yd)
# paranteza „short de 1-2 zile" peste barele 10-11
xa, xb, yb = xd(10) - 6, xd(11) + 6, y_sl - 12
out.append(f'<path d="M{xa:.1f},{yb + 6:.1f} V{yb:.1f} H{xb:.1f} V{yb + 6:.1f}" '
f'fill="none" stroke="{GRAY}" stroke-width="1.2"/>')
text(xb, yb - 6, "short de 1-2 zile: permis", fill=GRAY, anchor="end", bold=True)
# SL lovit la bara 14
# SL lovit la bara 14: săgeată din dreapta sus
cx14 = xd(HIT)
out.append(f'<circle cx="{cx14:.1f}" cy="{y_sl:.1f}" r="7" fill="none" stroke="{RED}" '
f'stroke-width="2"/>')
y_lbl = DT - 22
line(cx14, y_sl - 8, cx14, y_lbl + 4, RED, 1.2)
text(cx14 - 6, y_lbl, "SL lovit: poziția short contra weekly", fill=RED, anchor="middle", bold=True)
y_hit = DT - 40
arrow(560, y_hit + 6, cx14 + 9, y_sl - 9, RED)
text(568, y_hit, "aici te-a scos: stopul 84.85, lovit a patra zi", fill=RED, bold=True)
text(568, y_hit + 18, "banii mari de pe weekly cumpără mai departe", fill=RED)
# Sell Doji: etichetă sub panou, cu leader spre confirmare
# intrarea short: săgeată de jos-dreapta spre close-ul confirmării
y_bot = yd(min(b[2] for b in DY))
y_sd = y_bot + 22
line(xd(10), yd(DY[10][2]) + 4, xd(10), y_sd - 12, ORANGE, 1.2)
text(xd(10) - 20, y_sd, "Sell Doji daily: tehnic valid (close 83.60 &lt; low doji 83.95)",
x_e = xd(12) + 6
arrow(x_e, y_tp + 30, xd(10) + 7, y_e + 4, ORANGE)
text(x_e + 6, y_tp + 28, "aici ai intrat SHORT, la 83.60: Sell Doji corect ca formă",
fill=ORANGE, bold=True)
text(x_e + 6, y_tp + 46, "(close sub low-ul doji-ului 83.95) — dar contra weekly-ului",
fill=ORANGE)
# insigna de contrast
rect(470, DT - 36, 230, 58, RED, 0.08, RED)
text(585, DT - 12, "short daily = CONTRA ✗", fill=RED, anchor="middle", bold=True, size=16)
text(585, DT + 8, "weekly zice long; daily urcă mai departe", fill=RED, anchor="middle", size=11)
y0 = y_sd + 32
text(20, y0, "Short scurt înăuntrul structurii weekly: da. Poziție short contra ei: nu.",
fill=INK, bold=True)
text(20, y0 + 18, "Seria e construită: un singur caz ilustrează regula, nu o dovedește.", fill="#555")
H = y0 + 30
y0 = max(y_bot, y_tp + 46) + 34
text(20, y0, "Seria e construită: un singur caz ilustrează regula, nu o dovedește.", fill="#555")
H = y0 + 24
svg = (f'<svg viewBox="0 0 {W} {H:.0f}" xmlns="http://www.w3.org/2000/svg" '
f'style="width:100%;height:auto;font:12px sans-serif">\n ' + "\n ".join(out) + "\n</svg>")

View File

@@ -38,19 +38,32 @@ open[0] = 81.30, fitile 0.15 peste/sub corp (uptrend de 9 candele).
NIVELURI (panoul daily)
-----------------------
intrare short 83.60 (portocaliu), SL 84.80 roșu („SL 84.80 = high 4 candele"),
TP1 82.40 punctat („TP1 82.40 — neatins").
Paranteză orizontală peste barele 10-11: „short de 1-2 zile: permis" (gri).
Mark(14, "SL lovit: poziția short contra weekly", roșu, above).
intrare short 83.60 (portocaliu), stop 84.85 roșu („stop 84.85 = 5 cenți peste
high-ul de 4 candele"), ținta 82.35 punctată („neatinsă — a scăzut o zi, la 83.00").
Stopul e 5 cenți peste extremă, ca oglinda pasului 5 din capitol (51.60 -> 51.55).
Paranteza „short de 1-2 zile: permis" a fost scoasă (nuanță de nivel 3, încărca
pasul mecanic), la fel și insignele de colț — locul lor îl iau săgețile.
SĂGEȚI (format tutorial v2: ce ȘI de ce, 1 pe weekly + 2 pe daily)
- weekly, spre confirmare: „weekly: Buy Doji confirmat (close 81.30, peste
high-ul doji-ului 79.80)" / „deci direcția permisă e LONG: pe daily cauți
doar Buy Doji".
- daily, spre close-ul confirmării: „aici ai intrat SHORT, la 83.60: Sell Doji
corect ca formă (close sub low-ul doji-ului 83.95) — dar contra weekly-ului".
- daily, spre bara 14 pe linia stopului: „aici te-a scos: stopul 84.85, lovit a
patra zi" / „banii mari de pe weekly cumpără mai departe".
Zone: verde peste doji-ul + confirmarea weekly, portocalie peste Sell Doji-ul
daily (portocaliu, nu roșu, ca să nu se confunde cu linia stopului).
Lățime 900 (textele săgeților stau în dreapta candelelor).
ASSERT-URI
----------
1. open[i] == close[i-1] pe ambele panouri; h/l cuprind o/c.
2. Doji weekly și doji daily: abs(o-c) <= 0.10*(h-l).
3. weekly close[8] > high[7]; daily close[10] < low[9].
4. SL == max(h for bare daily 7..10) == 84.80; risc == 1.20; TP1 == 82.40.
5. min(l for bare daily 11..16) == 83.00 > 82.40 (TP1 neatins).
6. primul i>10 cu high >= 84.80 este 14.
4. SL == max(h for bare daily 7..10) + 0.05 == 84.85; risc == 1.25; TP1 == 82.35.
5. min(l for bare daily 11..16) == 83.00 > 82.35 (TP1 neatins).
6. primul i>10 cu high >= 84.85 este 14.
SURSA
-----

View File

@@ -1,4 +1,4 @@
<svg viewBox="0 0 720 605" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif">
<svg viewBox="0 0 900 579" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif">
<text x="20.0" y="24.0" fill="#333" style="font-weight:bold;font-size:14px">NU: Sell Doji daily contra unui Buy Doji weekly — exemplu construit</text>
<text x="20.0" y="50.0" fill="#555" style="font-weight:bold">weekly: direcția</text>
<rect x="164.0" y="152.6" width="32.0" height="56.0" fill="#188a3e" fill-opacity="0.12" stroke="#188a3e" rx="3"/>
@@ -23,19 +23,19 @@
<line x1="204.0" y1="143.4" x2="204.0" y2="162.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="199.5" y="147.0" width="9" height="13.2" fill="#188a3e"/>
<text x="172.0" y="220.6" fill="#d06a00" text-anchor="middle" style="font-weight:bold">doji weekly</text>
<text x="218.0" y="164.2" fill="#188a3e" style="font-weight:bold">Buy Doji weekly: direcția = long</text>
<rect x="470.0" y="66.0" width="230.0" height="58.0" fill="#188a3e" fill-opacity="0.1" stroke="#188a3e" rx="3"/>
<text x="585.0" y="90.0" fill="#188a3e" text-anchor="middle" style="font-weight:bold;font-size:16px">WEEKLY: LONG ↑</text>
<text x="585.0" y="110.0" fill="#188a3e" text-anchor="middle" style="font-size:11px">confirmare 81.30 &gt; high doji 79.80</text>
<line x1="20.0" y1="238.6" x2="700.0" y2="238.6" stroke="#ddd" stroke-width="1"/>
<line x1="300.0" y1="154.2" x2="209.0" y2="154.2" stroke="#188a3e" stroke-width="1.8"/>
<polygon points="200.0,154.2 209.0,149.7 209.0,158.7" fill="#188a3e"/>
<text x="306.0" y="150.2" fill="#188a3e" style="font-weight:bold">weekly: Buy Doji confirmat (close 81.30, peste high-ul doji-ului 79.80)</text>
<text x="306.0" y="168.2" fill="#188a3e">deci direcția permisă e LONG: pe daily cauți doar Buy Doji</text>
<line x1="20.0" y1="238.6" x2="880.0" y2="238.6" stroke="#ddd" stroke-width="1"/>
<text x="20.0" y="260.6" fill="#555" style="font-weight:bold">daily: săptămânile de după confirmare (open 81.30 = close-ul ei)</text>
<rect x="214.0" y="371.6" width="34.0" height="60.0" fill="#d06a00" fill-opacity="0.15" stroke="#d06a00" rx="3"/>
<line x1="212.0" y1="374.6" x2="392.0" y2="374.6" stroke="#c00" stroke-width="1.5" stroke-dasharray="6 3"/>
<line x1="212.0" y1="372.6" x2="392.0" y2="372.6" stroke="#c00" stroke-width="1.5" stroke-dasharray="6 3"/>
<line x1="232.0" y1="422.6" x2="392.0" y2="422.6" stroke="#d06a00" stroke-width="1.5" stroke-dasharray="6 3"/>
<line x1="232.0" y1="470.6" x2="392.0" y2="470.6" stroke="#777" stroke-width="1.5" stroke-dasharray="2 3"/>
<text x="400.0" y="378.6" fill="#c00" style="font-size:11px">SL 84.80 = high 4 candele</text>
<line x1="232.0" y1="472.6" x2="392.0" y2="472.6" stroke="#777" stroke-width="1.5" stroke-dasharray="2 3"/>
<text x="400.0" y="376.6" fill="#c00" style="font-size:11px">stop 84.85 = 5 cenți peste high-ul de 4 candele</text>
<text x="400.0" y="426.6" fill="#d06a00" style="font-size:11px">intrare short 83.60</text>
<text x="400.0" y="474.6" fill="#777" style="font-size:11px">TP1 82.40 — neatins</text>
<text x="400.0" y="476.6" fill="#777" style="font-size:11px">ținta 82.35 — neatinsă (a scăzut o zi, la 83.00)</text>
<line x1="60.0" y1="492.6" x2="60.0" y2="520.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="55.5" y="498.6" width="9" height="16.0" fill="#188a3e"/>
<line x1="78.0" y1="472.6" x2="78.0" y2="504.6" stroke="#1a1a1a" stroke-width="1.2"/>
@@ -70,16 +70,14 @@
<rect x="325.5" y="342.6" width="9" height="20.0" fill="#188a3e"/>
<line x1="348.0" y1="314.6" x2="348.0" y2="346.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="343.5" y="322.6" width="9" height="20.0" fill="#188a3e"/>
<path d="M234.0,368.6 V362.6 H264.0 V368.6" fill="none" stroke="#777" stroke-width="1.2"/>
<text x="264.0" y="356.6" fill="#777" text-anchor="end" style="font-weight:bold">short de 1-2 zile: permis</text>
<circle cx="312.0" cy="374.6" r="7" fill="none" stroke="#c00" stroke-width="2"/>
<line x1="312.0" y1="366.6" x2="312.0" y2="296.6" stroke="#c00" stroke-width="1.2"/>
<text x="306.0" y="292.6" fill="#c00" text-anchor="middle" style="font-weight:bold">SL lovit: poziția short contra weekly</text>
<line x1="240.0" y1="432.6" x2="240.0" y2="530.6" stroke="#d06a00" stroke-width="1.2"/>
<text x="220.0" y="542.6" fill="#d06a00" style="font-weight:bold">Sell Doji daily: tehnic valid (close 83.60 &lt; low doji 83.95)</text>
<rect x="470.0" y="278.6" width="230.0" height="58.0" fill="#c00" fill-opacity="0.08" stroke="#c00" rx="3"/>
<text x="585.0" y="302.6" fill="#c00" text-anchor="middle" style="font-weight:bold;font-size:16px">short daily = CONTRA ✗</text>
<text x="585.0" y="322.6" fill="#c00" text-anchor="middle" style="font-size:11px">weekly zice long; daily urcă mai departe</text>
<text x="20.0" y="574.6" fill="#333" style="font-weight:bold">Short scurt înăuntrul structurii weekly: da. Poziție short contra ei: nu.</text>
<text x="20.0" y="592.6" fill="#555">Seria e construită: un singur caz ilustrează regula, nu o dovedește.</text>
<circle cx="312.0" cy="372.6" r="7" fill="none" stroke="#c00" stroke-width="2"/>
<line x1="560.0" y1="280.6" x2="329.5" y2="360.6" stroke="#c00" stroke-width="1.8"/>
<polygon points="321.0,363.6 328.0,356.4 331.0,364.9" fill="#c00"/>
<text x="568.0" y="274.6" fill="#c00" style="font-weight:bold">aici te-a scos: stopul 84.85, lovit a patra zi</text>
<text x="568.0" y="292.6" fill="#c00">banii mari de pe weekly cumpără mai departe</text>
<line x1="282.0" y1="502.6" x2="250.8" y2="434.8" stroke="#d06a00" stroke-width="1.8"/>
<polygon points="247.0,426.6 254.9,432.9 246.7,436.7" fill="#d06a00"/>
<text x="288.0" y="500.6" fill="#d06a00" style="font-weight:bold">aici ai intrat SHORT, la 83.60: Sell Doji corect ca formă</text>
<text x="288.0" y="518.6" fill="#d06a00">(close sub low-ul doji-ului 83.95) — dar contra weekly-ului</text>
<text x="20.0" y="554.6" fill="#555">Seria e construită: un singur caz ilustrează regula, nu o dovedește.</text>
</svg>

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 7.1 KiB

View File

@@ -1,30 +1,31 @@
#!/usr/bin/env python3
"""Ce e doji și ce nu — patru candele cu același high 50.10 și low 49.20.
"""Ce e un doji și ce nu — patru candele cu același high 50.10 și low 49.20.
Citește `gen/strategii/buy_doji_doji_forma.spec.txt` și scrie
`gen/strategii/buy_doji_doji_forma.svg`. Definiție de o candelă (stilul
vechi, candele izolate): diferă doar corpul, deci testul „corp ≤ 10 % din
range, fitil în ambele părți" se vede direct pe formă.
`gen/strategii/buy_doji_doji_forma.svg`. E prima imagine din capitol: cine o
vede nu știe ce e un doji, deci candela A primește săgeți pe corp și pe
fiecare fitil, cu explicația de ce arată așa, iar C și D sunt contraexemple.
Zonă verde peste A și B („doji"), zonă roșie peste C și D („nu e doji").
Desenat direct, nu cu `Chart`: `tag`/`note` din svg_candles pun etichetele
pe un singur rând sau în blocul de jos, iar aici fiecare etichetă trebuie să
stea lipită sub candela ei, pe 2-3 rânduri.
stea lipită sub candela ei, pe 2-3 rânduri, plus săgeți cu text pe lateral.
Rulare: python3 gen/strategii/buy_doji_doji_forma.py
"""
from pathlib import Path
OUT = Path(__file__).with_suffix(".svg")
GREEN, RED, GREY = "#188a3e", "#c00", "#555"
GREEN, RED, GREY, BLUE = "#188a3e", "#c00", "#555", "#1a5fb4"
H, L = 50.10, 49.20
RNG = H - L
# (nume, o, h, l, c, verdict, rânduri de etichetă sub candelă)
CANDLES = [
("A", 49.60, 50.10, 49.20, 49.55, "DA", ["DA: corp 0.05", "= 5.6 % din range"]),
("B", 49.62, 50.10, 49.20, 49.53, "DA", ["DA, la limită:", "corp 0.09 = 10 %", "(parametrul 10)"]),
("A", 49.60, 50.10, 49.20, 49.55, "DA", ["DA: corp 0.05", "= 5,6 % din înălțime"]),
("B", 49.62, 50.10, 49.20, 49.53, "DA", ["DA, la limită:", "corp 0.09 = 10 %"]),
("C", 49.80, 50.10, 49.20, 49.50, "NU", ["NU: corp 0.30", "= 33 %"]),
("D", 50.05, 50.10, 49.20, 50.10, "NU", ["NU: corp mic (5.6 %),", "dar fără fitil sus"]),
("D", 50.05, 50.10, 49.20, 50.10, "NU", ["NU: corp mic (5,6 %),", "dar fără fitil sus"]),
]
# --- assert-urile din spec --------------------------------------------------
@@ -39,8 +40,8 @@ _, oD, hD, _, cD, *_ = CANDLES[3]
assert max(oD, cD) == hD
# --- geometrie ---------------------------------------------------------------
SCALE, TOP, W = 260, 72, 740
XS = [150, 300, 450, 600] # centrele candelelor
SCALE, TOP, W = 260, 210, 1000
XS = [350, 490, 690, 860] # centrele candelelor: A, B (doji) | C, D (nu)
BODY_W = 26
@@ -61,16 +62,45 @@ def text(x, yy, s, color=GREY, anchor="start", bold=False, size=12):
t(f'<text x="{x:.1f}" y="{yy:.1f}" fill="{color}" text-anchor="{anchor}"{style}>{s}</text>')
text(24, 22, "Ce e doji și ce nu — aceeași bară 50.10 / 49.20", "#333", bold=True)
def zone(x0, x1, y0, y1, label, color):
t(f'<rect x="{x0:.1f}" y="{y0:.1f}" width="{x1 - x0:.1f}" height="{y1 - y0:.1f}" '
f'fill="{color}" fill-opacity="0.10" stroke="{color}" stroke-width="1"/>')
text(x0 + 6, y0 - 7, label, color, bold=True)
def arrow(x1, y1, x2, y2, color, lines, anchor="start"):
"""Săgeată de la (x1,y1) [coada, lângă text] la (x2,y2) [vârf, pe țintă]."""
d = max(((x2 - x1) ** 2 + (y2 - y1) ** 2) ** 0.5, 1e-9)
ux, uy = (x2 - x1) / d, (y2 - y1) / d
bx, by = x2 - 8 * ux, y2 - 8 * uy
t(f'<line x1="{x1:.1f}" y1="{y1:.1f}" x2="{bx:.1f}" y2="{by:.1f}" '
f'stroke="{color}" stroke-width="1.6"/>')
t(f'<polygon points="{x2:.1f},{y2:.1f} {bx - 4 * uy:.1f},{by + 4 * ux:.1f} '
f'{bx + 4 * uy:.1f},{by - 4 * ux:.1f}" fill="{color}"/>')
dx = -6 if anchor == "end" else (0 if anchor == "middle" else 6)
# la săgeata verticală textul stă deasupra cozii, altfel intră peste ea
y0 = (y1 - 10 - 14 * (len(lines) - 1) if anchor == "middle"
else y1 + 4 - 14 * (len(lines) - 1) / 2)
for k, s in enumerate(lines):
text(x1 + dx, y0 + 14 * k, s, color, anchor, bold=(k == 0))
text(24, 30, "Ce e un doji și ce nu — aceeași bară, 50.10 sus și 49.20 jos", "#333",
bold=True, size=14)
# zonele: A+B sunt doji, C+D nu
label_y0 = y(L) + 28
z_bot = label_y0 + 16 * 2 - 4
zone(XS[0] - 58, XS[1] + 62, y(H) - 30, z_bot, "doji", GREEN)
zone(XS[2] - 62, XS[3] + 74, y(H) - 30, z_bot, "nu e doji", RED)
# high și low comune: linii subțiri pe toată lățimea
for p in (H, L):
t(f'<line x1="{XS[0] - 30}" y1="{y(p):.1f}" x2="{W - 24}" y2="{y(p):.1f}" '
t(f'<line x1="{XS[0] - 100}" y1="{y(p):.1f}" x2="{W - 24}" y2="{y(p):.1f}" '
f'stroke="#bbb" stroke-dasharray="4 3"/>')
text(XS[0] - 36, y(H) + 4, "high 50.10", anchor="end")
text(XS[0] - 36, y(L) + 4, "low 49.20", anchor="end")
text(24, y(H) - 6, "cât de sus a urcat prețul: 50.10")
text(24, y(L) + 14, "cât de jos a coborât: 49.20")
label_y0 = y(L) + 24
for (n, o, h, l, c, verdict, lines), x in zip(CANDLES, XS):
color = GREEN if c >= o else RED
vcol = GREEN if verdict == "DA" else RED
@@ -78,25 +108,34 @@ for (n, o, h, l, c, verdict, lines), x in zip(CANDLES, XS):
top, bot = y(max(o, c)), y(min(o, c))
t(f'<rect x="{x - BODY_W / 2:.1f}" y="{top:.1f}" width="{BODY_W}" '
f'height="{max(bot - top, 1.6):.1f}" fill="{color}"/>')
text(x, y(H) - 14, verdict, vcol, "middle", bold=True, size=18)
for k, s in enumerate(lines):
text(x, label_y0 + 16 * k, s, vcol, "middle", bold=(k == 0))
# prețurile pe A: open la stânga (mai sus), close la dreapta (mai jos)
x = XS[0]
text(x - 36, y(oA) + 2, "open 49.60", anchor="end")
t(f'<line x1="{x - 32}" y1="{y(oA):.1f}" x2="{x - 14}" y2="{y(oA):.1f}" stroke="{GREY}"/>')
text(x + 36, y(cA) + 8, "close 49.55")
t(f'<line x1="{x + 14}" y1="{y(cA):.1f}" x2="{x + 32}" y2="{y(cA):.1f}" stroke="{GREY}"/>')
# --- săgețile pe A: corp, fitil sus, fitil jos -------------------------------
xA = XS[0]
arrow(xA - 60, y(49.92), xA - 3, y(49.85), BLUE, anchor="end",
lines=["fitilul de sus", "cumpărătorii au împins, dar n-au ținut"])
arrow(xA - 60, y(49.575), xA - 15, y(49.575), BLUE, anchor="end",
lines=["corpul: aproape o linie",
"open și close aproape egale — nimeni",
"n-a câștigat ziua"])
arrow(xA - 60, y(49.30), xA - 3, y(49.375), BLUE, anchor="end",
lines=["fitilul de jos", "vânzătorii au împins, dar n-au ținut"])
# prețurile de open/close, în dreapta candelei A
text(xA + 20, y(oA) - 2, "open 49.60")
text(xA + 20, y(cA) + 10, "close 49.55")
# D: close = high, deci fitilul de sus lipsește
x = XS[3]
text(x + 20, y(H) + 12, "← fără fitil sus", RED)
# --- săgețile pe contraexemple ----------------------------------------------
xC, xD = XS[2], XS[3]
arrow(xC + 34, y(H) - 112, xC + 14, y(49.78), RED,
lines=["corp prea gros (33 %)", "aici una din tabere a câștigat —", "nu mai e indecizie"])
arrow(xD, y(H) - 34, xD, y(H) - 4, RED, anchor="middle",
lines=["fără fitil sus", "regula cere fitil în ambele părți"])
cap_y = label_y0 + 16 * 3 + 14
text(24, cap_y, f"Test doji: corp ≤ 10 % din range ({RNG:.2f}) și fitil în ambele părți. "
"Scară: 0.10 = 26 px.")
height = cap_y + 12
cap_y = z_bot + 30
text(24, cap_y, f"Doji = corpul e cel mult 10 % din înălțimea totală a barei "
f"(aici înălțimea e {RNG:.2f}) și are fitil și sus, și jos.")
height = cap_y + 16
svg = (f'<svg viewBox="0 0 {W} {height:.0f}" xmlns="http://www.w3.org/2000/svg" '
f'style="width:100%;height:auto;font:12px sans-serif">\n '

View File

@@ -1,10 +1,11 @@
SPEC DIAGRAMĂ — buy_doji_doji_forma
===================================
tip: DEFINIȚIE de o candelă (stil vechi permis de STYLE.md: 4 candele
izolate, gap 92, body_w 26), fără trend, fără volum.
destinație: summaries/17_STRATEGII/01_buy_doji.md, Pasul 3
izolate, body_w 26), fără trend, fără volum. Adnotată „ca la
proști": 2 zone dreptunghiulare + 5 săgeți cu text (CE + DE CE).
destinație: summaries/17_STRATEGII/01_buy_doji.md, nivelul 1 („Ce e un doji")
cheie markdown: <!-- DIAGRAMA: doji_forma -->
titlu SVG: „Ce e doji și ce nu — aceeași bară 50.10 / 49.20"
titlu SVG: „Ce e un doji și ce nu — aceeași bară, 50.10 sus și 49.20 jos"
CE TREBUIE SĂ DEMONSTREZE
-------------------------
@@ -17,9 +18,25 @@ A (49.60, 50.10, 49.20, 49.55) „DA: corp 0.05 = 5.6 % din range"
B (49.62, 50.10, 49.20, 49.53) „DA, la limită: corp 0.09 = 10 % (parametrul 10)"
C (49.80, 50.10, 49.20, 49.50) „NU: corp 0.30 = 33 %"
D (50.05, 50.10, 49.20, 50.10) „NU: corp mic (5.6 %), dar fără fitil sus"
Deasupra fiecărei candele: „DA" verde / „NU" roșu.
Etichete de preț pe A: „high 50.10", „low 49.20", „open 49.60", „close 49.55"
(open deasupra lui close, pentru că open > close; verifică ordinea pe axă).
Verdictul e în eticheta de sub candelă („DA: …" verde / „NU: …" roșu) și în
eticheta zonei; nu se mai scrie DA/NU mare deasupra barei (se bătea cap în cap
cu textul săgeților).
Etichete de preț pe A: „cât de sus a urcat prețul: 50.10", „cât de jos a
coborât: 49.20", „open 49.60", „close 49.55" (open deasupra lui close, pentru
că open > close; verifică ordinea pe axă).
ZONE (dreptunghiuri de evidențiere, fill-opacity 0.10)
------------------------------------------------------
verde peste A și B, etichetă „doji"; roșie peste C și D, etichetă „nu e doji".
SĂGEȚI (text pe 2-3 rânduri: CE, apoi DE CE)
--------------------------------------------
pe A, din stânga: spre fitilul de sus („fitilul de sus / cumpărătorii au
împins, dar n-au ținut"); spre corp („corpul: aproape o linie / open și close
aproape egale — nimeni n-a câștigat ziua"); spre fitilul de jos („fitilul de
jos / vânzătorii au împins, dar n-au ținut").
pe C, de sus: „corp prea gros (33 %) / aici una din tabere a câștigat — nu mai
e indecizie". pe D, de sus: „fără fitil sus / regula cere fitil în ambele părți".
ASSERT-URI
----------

View File

@@ -1,34 +1,52 @@
<svg viewBox="0 0 740 404" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif">
<text x="24.0" y="22.0" fill="#333" text-anchor="start" style="font-weight:bold;font-size:12px">Ce e doji și ce nu — aceeași bară 50.10 / 49.20</text>
<line x1="120" y1="72.0" x2="716" y2="72.0" stroke="#bbb" stroke-dasharray="4 3"/>
<line x1="120" y1="306.0" x2="716" y2="306.0" stroke="#bbb" stroke-dasharray="4 3"/>
<text x="114.0" y="76.0" fill="#555" text-anchor="end">high 50.10</text>
<text x="114.0" y="310.0" fill="#555" text-anchor="end">low 49.20</text>
<line x1="150" y1="72.0" x2="150" y2="306.0" stroke="#1a1a1a" stroke-width="1.4"/>
<rect x="137.0" y="202.0" width="26" height="13.0" fill="#c00"/>
<text x="150.0" y="58.0" fill="#188a3e" text-anchor="middle" style="font-weight:bold;font-size:18px">DA</text>
<text x="150.0" y="330.0" fill="#188a3e" text-anchor="middle" style="font-weight:bold;font-size:12px">DA: corp 0.05</text>
<text x="150.0" y="346.0" fill="#188a3e" text-anchor="middle">= 5.6 % din range</text>
<line x1="300" y1="72.0" x2="300" y2="306.0" stroke="#1a1a1a" stroke-width="1.4"/>
<rect x="287.0" y="196.8" width="26" height="23.4" fill="#c00"/>
<text x="300.0" y="58.0" fill="#188a3e" text-anchor="middle" style="font-weight:bold;font-size:18px">DA</text>
<text x="300.0" y="330.0" fill="#188a3e" text-anchor="middle" style="font-weight:bold;font-size:12px">DA, la limită:</text>
<text x="300.0" y="346.0" fill="#188a3e" text-anchor="middle">corp 0.09 = 10 %</text>
<text x="300.0" y="362.0" fill="#188a3e" text-anchor="middle">(parametrul 10)</text>
<line x1="450" y1="72.0" x2="450" y2="306.0" stroke="#1a1a1a" stroke-width="1.4"/>
<rect x="437.0" y="150.0" width="26" height="78.0" fill="#c00"/>
<text x="450.0" y="58.0" fill="#c00" text-anchor="middle" style="font-weight:bold;font-size:18px">NU</text>
<text x="450.0" y="330.0" fill="#c00" text-anchor="middle" style="font-weight:bold;font-size:12px">NU: corp 0.30</text>
<text x="450.0" y="346.0" fill="#c00" text-anchor="middle">= 33 %</text>
<line x1="600" y1="72.0" x2="600" y2="306.0" stroke="#1a1a1a" stroke-width="1.4"/>
<rect x="587.0" y="72.0" width="26" height="13.0" fill="#188a3e"/>
<text x="600.0" y="58.0" fill="#c00" text-anchor="middle" style="font-weight:bold;font-size:18px">NU</text>
<text x="600.0" y="330.0" fill="#c00" text-anchor="middle" style="font-weight:bold;font-size:12px">NU: corp mic (5.6 %),</text>
<text x="600.0" y="346.0" fill="#c00" text-anchor="middle">dar fără fitil sus</text>
<text x="114.0" y="204.0" fill="#555" text-anchor="end">open 49.60</text>
<line x1="118" y1="202.0" x2="136" y2="202.0" stroke="#555"/>
<text x="186.0" y="223.0" fill="#555" text-anchor="start">close 49.55</text>
<line x1="164" y1="215.0" x2="182" y2="215.0" stroke="#555"/>
<text x="620.0" y="84.0" fill="#c00" text-anchor="start">← fără fitil sus</text>
<text x="24.0" y="392.0" fill="#555" text-anchor="start">Test doji: corp ≤ 10 % din range (0.90) și fitil în ambele părți. Scară: 0.10 = 26 px.</text>
<svg viewBox="0 0 1000 546" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif">
<text x="24.0" y="30.0" fill="#333" text-anchor="start" style="font-weight:bold;font-size:14px">Ce e un doji și ce nu — aceeași bară, 50.10 sus și 49.20 jos</text>
<rect x="292.0" y="180.0" width="260.0" height="320.0" fill="#188a3e" fill-opacity="0.10" stroke="#188a3e" stroke-width="1"/>
<text x="298.0" y="173.0" fill="#188a3e" text-anchor="start" style="font-weight:bold;font-size:12px">doji</text>
<rect x="628.0" y="180.0" width="306.0" height="320.0" fill="#c00" fill-opacity="0.10" stroke="#c00" stroke-width="1"/>
<text x="634.0" y="173.0" fill="#c00" text-anchor="start" style="font-weight:bold;font-size:12px">nu e doji</text>
<line x1="250" y1="210.0" x2="976" y2="210.0" stroke="#bbb" stroke-dasharray="4 3"/>
<line x1="250" y1="444.0" x2="976" y2="444.0" stroke="#bbb" stroke-dasharray="4 3"/>
<text x="24.0" y="204.0" fill="#555" text-anchor="start">cât de sus a urcat prețul: 50.10</text>
<text x="24.0" y="458.0" fill="#555" text-anchor="start">cât de jos a coborât: 49.20</text>
<line x1="350" y1="210.0" x2="350" y2="444.0" stroke="#1a1a1a" stroke-width="1.4"/>
<rect x="337.0" y="340.0" width="26" height="13.0" fill="#c00"/>
<text x="350.0" y="472.0" fill="#188a3e" text-anchor="middle" style="font-weight:bold;font-size:12px">DA: corp 0.05</text>
<text x="350.0" y="488.0" fill="#188a3e" text-anchor="middle">= 5,6 % din înălțime</text>
<line x1="490" y1="210.0" x2="490" y2="444.0" stroke="#1a1a1a" stroke-width="1.4"/>
<rect x="477.0" y="334.8" width="26" height="23.4" fill="#c00"/>
<text x="490.0" y="472.0" fill="#188a3e" text-anchor="middle" style="font-weight:bold;font-size:12px">DA, la limită:</text>
<text x="490.0" y="488.0" fill="#188a3e" text-anchor="middle">corp 0.09 = 10 %</text>
<line x1="690" y1="210.0" x2="690" y2="444.0" stroke="#1a1a1a" stroke-width="1.4"/>
<rect x="677.0" y="288.0" width="26" height="78.0" fill="#c00"/>
<text x="690.0" y="472.0" fill="#c00" text-anchor="middle" style="font-weight:bold;font-size:12px">NU: corp 0.30</text>
<text x="690.0" y="488.0" fill="#c00" text-anchor="middle">= 33 %</text>
<line x1="860" y1="210.0" x2="860" y2="444.0" stroke="#1a1a1a" stroke-width="1.4"/>
<rect x="847.0" y="210.0" width="26" height="13.0" fill="#188a3e"/>
<text x="860.0" y="472.0" fill="#c00" text-anchor="middle" style="font-weight:bold;font-size:12px">NU: corp mic (5,6 %),</text>
<text x="860.0" y="488.0" fill="#c00" text-anchor="middle">dar fără fitil sus</text>
<line x1="290.0" y1="256.8" x2="339.4" y2="272.6" stroke="#1a5fb4" stroke-width="1.6"/>
<polygon points="347.0,275.0 338.2,276.4 340.6,268.8" fill="#1a5fb4"/>
<text x="284.0" y="253.8" fill="#1a5fb4" text-anchor="end" style="font-weight:bold;font-size:12px">fitilul de sus</text>
<text x="284.0" y="267.8" fill="#1a5fb4" text-anchor="end">cumpărătorii au împins, dar n-au ținut</text>
<line x1="290.0" y1="346.5" x2="327.0" y2="346.5" stroke="#1a5fb4" stroke-width="1.6"/>
<polygon points="335.0,346.5 327.0,350.5 327.0,342.5" fill="#1a5fb4"/>
<text x="284.0" y="336.5" fill="#1a5fb4" text-anchor="end" style="font-weight:bold;font-size:12px">corpul: aproape o linie</text>
<text x="284.0" y="350.5" fill="#1a5fb4" text-anchor="end">open și close aproape egale — nimeni</text>
<text x="284.0" y="364.5" fill="#1a5fb4" text-anchor="end">n-a câștigat ziua</text>
<line x1="290.0" y1="418.0" x2="339.4" y2="401.1" stroke="#1a5fb4" stroke-width="1.6"/>
<polygon points="347.0,398.5 340.7,404.9 338.1,397.3" fill="#1a5fb4"/>
<text x="284.0" y="415.0" fill="#1a5fb4" text-anchor="end" style="font-weight:bold;font-size:12px">fitilul de jos</text>
<text x="284.0" y="429.0" fill="#1a5fb4" text-anchor="end">vânzătorii au împins, dar n-au ținut</text>
<text x="370.0" y="338.0" fill="#555" text-anchor="start">open 49.60</text>
<text x="370.0" y="363.0" fill="#555" text-anchor="start">close 49.55</text>
<line x1="724.0" y1="98.0" x2="704.8" y2="285.2" stroke="#c00" stroke-width="1.6"/>
<polygon points="704.0,293.2 700.8,284.8 708.8,285.6" fill="#c00"/>
<text x="730.0" y="88.0" fill="#c00" text-anchor="start" style="font-weight:bold;font-size:12px">corp prea gros (33 %)</text>
<text x="730.0" y="102.0" fill="#c00" text-anchor="start">aici una din tabere a câștigat —</text>
<text x="730.0" y="116.0" fill="#c00" text-anchor="start">nu mai e indecizie</text>
<line x1="860.0" y1="176.0" x2="860.0" y2="198.0" stroke="#c00" stroke-width="1.6"/>
<polygon points="860.0,206.0 856.0,198.0 864.0,198.0" fill="#c00"/>
<text x="860.0" y="152.0" fill="#c00" text-anchor="middle" style="font-weight:bold;font-size:12px">fără fitil sus</text>
<text x="860.0" y="166.0" fill="#c00" text-anchor="middle">regula cere fitil în ambele părți</text>
<text x="24.0" y="530.0" fill="#555" text-anchor="start">Doji = corpul e cel mult 10 % din înălțimea totală a barei (aici înălțimea e 0.90) și are fitil și sus, și jos.</text>
</svg>

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

@@ -6,10 +6,14 @@ Citește `gen/strategii/buy_doji_fereastra.spec.txt` și scrie
cu aceeași serie până la doji: sus confirmarea vine la bara +2 (în fereastră),
jos niciuna din +1..+3 nu confirmă, iar a 4-a închide sub low-ul dojiului.
Toate cifrele din desen vin din specificație: doji h 50.10 / l 49.20,
closes-urile DA/NU, pragul 50.10, low-ul 49.20. Seriile sunt construite
(open = close-ul barei anterioare, mai puțin open-ul primei bare, start-ul),
ca nivelurile afirmate să iasă exact din serie.
Adnotat „ca la proști": zonă dreptunghiulară peste cele 3 candele ale
ferestrei pe ambele panouri, plus săgeți cu text care spun CE și DE CE
(„aici NU intri — s-a închis sub high-ul dojiului", „AICI INTRI, la close").
Toate cifrele din desen vin din specificație: doji h 50.10 / l 49.25,
closes-urile DA/NU, pragul 50.10. Seriile sunt construite (open = close-ul
barei anterioare, mai puțin open-ul primei bare, start-ul), ca nivelurile
afirmate să iasă exact din serie.
Rulare: python3 gen/strategii/buy_doji_fereastra.py
"""
@@ -18,21 +22,23 @@ import sys
from pathlib import Path
sys.path.insert(0, "/workspace/atm-curs-dl")
from svg_candles import Chart, Level, Mark, from_closes # noqa: E402
from svg_candles import Arrow, Chart, Mark, from_closes # noqa: E402
OUT = Path(__file__).with_suffix(".svg")
W = 460
VGAP = 34
SCALE = 45.0 # px / unitate, aceeași pe ambele panouri (comparație)
W = 640
VGAP = 0
SCALE = 60.0 # px / unitate, aceeași pe ambele panouri (comparație)
LEFT, GAP = 64, 40
ORANGE, RED, GREEN, BLUE, GREY = "#b06000", "#c00", "#188a3e", "#1a5fb4", "#555"
# --- seriile din specificație ----------------------------------------------
CLOSES_DA = [52.20, 51.40, 50.60, 49.65,
49.60, # doji, h 50.10 / l 49.20
49.60, # doji, h 50.10 / l 49.25
49.90, # +1 — sub 50.10
50.40, # +2 — peste 50.10 => confirmă
50.80]
CLOSES_NU = [52.20, 51.40, 50.60, 49.65,
49.60, # doji, h 50.10 / l 49.20
49.60, # doji, h 50.10 / l 49.25
49.95, # +1
50.05, # +2
49.85, # +3
@@ -40,13 +46,13 @@ CLOSES_NU = [52.20, 51.40, 50.60, 49.65,
assert len(CLOSES_DA) == 8 and len(CLOSES_NU) == 9
assert CLOSES_DA[:5] == CLOSES_NU[:5]
HIGH_DOJI, LOW_DOJI = 50.10, 49.20
HIGH_DOJI, LOW_DOJI = 50.10, 49.25
# wick-uri: (up, down). Doji-ul (index 4) primește mecioni ca să iasă exact
# h=50.10 / l=49.20; restul au mecioni mici, egali.
# wick-uri: (up, down). Doji-ul (index 4) primește fitile ca să iasă exact
# h=50.10 / l=49.25; restul au fitile mici, egale.
wicks_da = [(0.15, 0.15)] * len(CLOSES_DA)
wicks_nu = [(0.15, 0.15)] * len(CLOSES_NU)
wicks_da[4] = wicks_nu[4] = (0.45, 0.40)
wicks_da[4] = wicks_nu[4] = (0.45, 0.35)
START = CLOSES_DA[0] + 0.15 # prima bară roșie, open > close
cds_da = from_closes(CLOSES_DA, wicks=wicks_da, start=START)
@@ -72,7 +78,7 @@ assert abs(cds_da[5].c - 49.90) < 1e-9 and cds_da[5].c <= HIGH_DOJI, \
assert abs(cds_da[6].c - entry) < 1e-9 and abs(entry - 50.40) < 1e-9, \
"intrarea nu e close-ul de 50.40 al barei +2"
# 2. NU: niciun close din +1..+3 nu depășește 50.10; a 4-a închide sub 49.20
# 2. NU: niciun close din +1..+3 nu depășește 50.10; a 4-a închide sub 49.25
assert all(cds_nu[i].c <= HIGH_DOJI for i in (5, 6, 7)), \
"un close din +1..+3 ar confirma, fereastra n-ar fi expirat"
assert cds_nu[8].c < LOW_DOJI, f"close[+4]={cds_nu[8].c} nu e sub {LOW_DOJI}"
@@ -87,54 +93,102 @@ ser_nu = [(round(c.o, 9), round(c.h, 9), round(c.l, 9), round(c.c, 9)) for c in
assert ser_da == ser_nu, "panourile nu au aceeași serie până la doji"
# --- desen: două Chart-uri, lipite vertical într-un singur SVG -------------
cds_nu[7].note = "+1: 49.95 · +2: 50.05 · +3: 49.85 — toate sub 50.10"
ch_da = Chart(
candles=cds_da,
marks=[Mark(4, "doji", ORANGE, "above")],
arrows=[
Arrow(5, "aici NU intri: s-a închis sub 50.10\nsemnalul cere o ÎNCHIDERE peste",
where="below", color=RED),
Arrow(6, "AICI INTRI, la close 50.40\nprima închidere peste\nhigh-ul dojiului",
price=entry, where="right", color=GREEN, dx=20, dy=46),
],
scale=SCALE, gap=GAP, body_w=13, left=LEFT, width=W,
title="DA — confirmare la +2, în fereastră",
)
ch_nu = Chart(
candles=cds_nu,
marks=[Mark(4, "doji", ORANGE, "above"), Mark(8, "a 4-a", RED, "above")],
arrows=[
Arrow(7, "a treia s-a închis tot sub 50.10\nfereastra s-a terminat: ștergi setup-ul",
where="above", color=RED, dx=135),
Arrow(8, "a închis sub low-ul dojiului\nsetup mort — nu mai intri",
where="below", color=RED),
],
scale=SCALE, gap=GAP, body_w=13, left=LEFT, width=W,
title="NU — nicio confirmare în 3 candele",
)
def _panel(ch: Chart):
svg = ch.render()
m = re.search(r'viewBox="0 0 (\d+) ([\d.]+)"', svg)
"""`_render()`, nu `render()`: al doilea restaurează top/left după desen,
iar liniile și zonele desenate de mână ar pica deplasate față de body."""
svg = ch._render()
m = re.search(r'viewBox="0 0 ([\d.]+) ([\d.]+)"', svg)
assert m, "viewBox lipsă"
assert float(m.group(1)) == W, f"textul unei săgeți iese din {W}px"
body = svg[svg.index(">") + 1:svg.rindex("</svg>")]
return body, float(m.group(2))
# DA — confirmarea vine la +2
cds_da[5].note = "+1: close 49.90 — sub 50.10, nu confirmă"
cds_da[6].note = "+2: close 50.40 — peste 50.10, confirmă (intrare la close)"
ch_da = Chart(
candles=cds_da,
levels=[Level(HIGH_DOJI, "high doji 50.10", "#b06000", label_at="left"),
Level(LOW_DOJI, "low doji 49.20", "#c00", label_at="left")],
marks=[Mark(4, "doji", "#b06000", "above"),
Mark(6, f"confirmare +2 — intrare {entry:.2f}", "#188a3e", "above")],
scale=SCALE, gap=40, body_w=13, left=44, width=W,
title="DA — confirmare la +2, în fereastră",
)
def level(ch, price, text, color, below=False, at_left=True):
"""Linie punctată pe toată lățimea + etichetă, desenată de mână: eticheta
din `Level` stă lipită de linie și cade peste candelele care o traversează."""
y = ch._y(price)
out = [f'<line x1="24" y1="{y:.1f}" x2="{W - 14}" y2="{y:.1f}" stroke="{color}" '
f'stroke-width="1.5" stroke-dasharray="4 3"/>']
for k, s in enumerate(text):
ty = (y + 15 + 14 * k) if below else (y - 6 - 14 * (len(text) - 1 - k))
tx, anchor = (30, "start") if at_left else (W - 24, "end")
out.append(f'<text x="{tx}" y="{ty:.1f}" fill="{color}" text-anchor="{anchor}" '
f'style="font-weight:bold">{s}</text>')
return out
def zone(ch, i0, i1, label, color, lift=0.0):
"""Dreptunghi de evidențiere peste candelele i0..i1, cu eticheta deasupra.
`lift` ridică marginea de sus (și deci eticheta), ca să nu cadă peste
săgețile care intră în zonă de sus."""
cds = ch.candles[i0:i1 + 1]
x0, x1 = ch._cx(i0) - 16, ch._cx(i1) + 16
y0 = ch._y(max(c.h for c in cds)) - 8 - lift
y1 = ch._y(min(c.l for c in cds)) + 8
return [f'<rect x="{x0:.1f}" y="{y0:.1f}" width="{x1 - x0:.1f}" height="{y1 - y0:.1f}" '
f'fill="{color}" fill-opacity="0.12" stroke="{color}" stroke-width="1"/>',
f'<text x="{x0 + 6:.1f}" y="{y0 - 7:.1f}" fill="{color}" '
f'style="font-weight:bold">{label}</text>']
# NU — nicio confirmare în 3 candele, apoi setup mort
cds_nu[5].note = "+1: 49.95; +2: 50.05; +3: 49.85 — toate sub 50.10"
cds_nu[8].note = "a 4-a: close 49.15 — sub low-ul dojiului 49.20, setup mort"
ch_nu = Chart(
candles=cds_nu,
levels=[Level(HIGH_DOJI, "high doji 50.10", "#b06000", label_at="left"),
Level(LOW_DOJI, "low doji 49.20", "#c00", label_at="left")],
marks=[Mark(4, "doji", "#b06000", "above"),
Mark(8, "a 4-a", "#c00", "above")],
scale=SCALE, gap=40, body_w=13, left=44, width=W,
title="NU — nicio confirmare în 3 candele",
)
body_da, h_da = _panel(ch_da)
body_nu, h_nu = _panel(ch_nu)
extra_da = (zone(ch_da, 5, 7, "fereastra: 3 candele", BLUE)
+ level(ch_da, HIGH_DOJI,
["high-ul dojiului 50.10", "trebuie ÎNCHIS peste,", "nu doar atins"],
ORANGE, below=True)
+ level(ch_da, LOW_DOJI, ["low-ul dojiului 49.25"], RED, below=True))
extra_nu = (zone(ch_nu, 5, 7, "fereastra: 3 candele", BLUE)
+ level(ch_nu, HIGH_DOJI,
["high-ul dojiului 50.10", "trebuie ÎNCHIS peste,", "nu doar atins"],
ORANGE, below=True)
+ level(ch_nu, LOW_DOJI, ["low-ul dojiului 49.25"], RED, below=True))
cap1 = "Serii construite: open = close-ul barei anterioare."
cap2 = "Doji: h 50.10 / l 49.20. Fereastra = maximum 3 candele după doji."
cap2 = "Doji: h 50.10 / l 49.25. Fereastra = maximum 3 candele după doji."
cap_top = h_da + VGAP + h_nu + 20
H = cap_top + 22
parts = [
f'<svg viewBox="0 0 {W} {H:.0f}" xmlns="http://www.w3.org/2000/svg" '
f'style="width:100%;height:auto;font:12px sans-serif">',
f'<g transform="translate(0,0)">{body_da}</g>',
f'<g transform="translate(0,{h_da + VGAP:.0f})">{body_nu}</g>',
f'<text x="24" y="{cap_top:.0f}" fill="#555">{cap1}</text>',
f'<text x="24" y="{cap_top + 17:.0f}" fill="#555">{cap2}</text>',
# zonele și liniile întâi, ca să stea în spatele candelelor
f'<g transform="translate(0,0)">{"".join(extra_da)}{body_da}</g>',
f'<g transform="translate(0,{h_da + VGAP:.0f})">{"".join(extra_nu)}{body_nu}</g>',
f'<text x="24" y="{cap_top:.0f}" fill="{GREY}">{cap1}</text>',
f'<text x="24" y="{cap_top + 17:.0f}" fill="{GREY}">{cap2}</text>',
"</svg>",
]
svg = "\n ".join(parts)
@@ -162,7 +216,8 @@ def _texts(body: str, y_off: float, tag: str):
return out
labels = _texts(body_da, 0.0, "DA") + _texts(body_nu, h_da + VGAP, "NU")
labels = (_texts(body_da + "".join(extra_da), 0.0, "DA")
+ _texts(body_nu + "".join(extra_nu), h_da + VGAP, "NU"))
for left, right, y, s, tag in labels:
assert left >= -2 and right <= W + 2, f"[{tag}] text iese din panză: {s!r}"
assert 0 <= y <= H, f"[{tag}] text în afara înălțimii: {s!r} (y={y:.0f})"

View File

@@ -5,7 +5,7 @@ MARCAJ .md: <!-- DIAGRAMA: fereastra --> (Nivel 1, §1.2 Setup)
CE ARATĂ
Două panouri mici, unul sub altul, cu aceeași serie până la doji:
- Panoul DA: doji high 50.10; bara +1 închide 49.90 (sub high); bara +2
- Panoul DA: doji high 50.10 / low 49.25; bara +1 închide 49.90 (sub high); bara +2
închide 50.40 (peste 50.10) => Buy Doji valid, intrare la close.
- Panoul NU: doji high 50.10; barele +1, +2, +3 închid 49.95, 50.05, 49.85
(toate sub high); a 4-a bară închide 49.15, sub low-ul dojiului => setup
@@ -15,7 +15,8 @@ numeric. Diferența e strict numerică, nu vizuală
(`13_strategia_3_byh.md:179-180`).
NIVELURILE ȘI ETICHETELE (cu trimitere)
- high doji = 50.10, low doji = 49.20 (exemplul construit al lecției):
- high doji = 50.10, low doji = 49.25 (low-ul e coborât de la 49.20 ca stopul
de 49.20 din pașii 5-6 să iasă SUB low, nu exact pe el):
`13_strategia_3_byh.md:158-167`.
- fereastra = maximum 3 candele după doji: `13_strategia_3_byh.md:151-156`.
- „setup expirat, nu intri" la lipsa confirmării: `13_strategia_3_byh.md:168-176`;
@@ -23,23 +24,39 @@ NIVELURILE ȘI ETICHETELE (cu trimitere)
STRUCTURA SERIEI
Panoul DA (8 candele): close-uri [52.20, 51.40, 50.60, 49.65,
49.60 (doji, h 50.10 / l 49.20),
49.60 (doji, h 50.10 / l 49.25),
49.90 (+1), 50.40 (+2, confirmă), 50.80]
Panoul NU (9 candele): close-uri [52.20, 51.40, 50.60, 49.65,
49.60 (doji, h 50.10 / l 49.20),
49.60 (doji, h 50.10 / l 49.25),
49.95 (+1), 50.05 (+2), 49.85 (+3), 49.15 (a 4-a, sub low)]
Mecioni: doji wu=0.45/wd=0.40 ca să dea exact h=50.10, l=49.20; restul
Fitile: doji wu=0.45/wd=0.35 ca să dea exact h=50.10, l=49.25; restul
(0.15, 0.15). Serie continuă, open = close-ul precedentului.
CE VERIFICĂ GENERATORUL CU assert
1. Panoul DA: primul close > 50.10 e bara +2 (index 6 din panou), adică în
fereastră; close[+1] <= 50.10.
2. Panoul NU: niciun close din +1..+3 nu depășește 50.10; close[+4] < 49.20.
2. Panoul NU: niciun close din +1..+3 nu depășește 50.10; close[+4] < 49.25.
3. Ambele doji: abs(o-c) <= 0.10*(h-l).
4. Ambele panouri au exact aceeași serie până la doji (aceleași 5 bare).
5. Distanța în pixeli de la 50.10 la 50.40 (DA) să fie > 0 și vizibil
(scara comună pe panou).
STIL: două `Chart`-uri separate sau un SVG cu două grupuri; gap=40, body_w=13,
width=460, fără vol_h (nu se vorbește de volum aici). Titluri
„DA — confirmare la +2, în fereastră" / „NU — nicio confirmare în 3 candele".
Fără linie goală în SVG.
ADNOTĂRI („ca la proști")
- ZONĂ albastră peste barele +1..+3 pe ambele panouri, etichetă
„fereastra: 3 candele".
- Panoul DA: săgeată pe +1 („aici NU intri: s-a închis sub 50.10 / semnalul cere
o ÎNCHIDERE peste"); săgeată din dreapta pe close-ul barei +2 („AICI INTRI, la
close 50.40 / prima închidere peste / high-ul dojiului").
- Panoul NU: săgeată pe +3 („a treia s-a închis tot sub 50.10 / fereastra s-a
terminat: ștergi setup-ul"); săgeată pe a 4-a („a închis sub low-ul dojiului /
setup mort — nu mai intri").
- Liniile 50.10 și 49.25 și etichetele lor se desenează de mână, nu cu `Level`:
eticheta din `Level` stă lipită de linie, la dreapta, și cade peste candele.
Eticheta lui 50.10 e pe trei rânduri, jos-stânga: „high-ul dojiului 50.10 /
trebuie ÎNCHIS peste, / nu doar atins".
STIL: două `Chart`-uri în două grupuri `<g transform>`; scale=60, gap=40,
body_w=13, left=64, width=640, fără vol_h (nu se vorbește de volum aici).
Titluri „DA — confirmare la +2, în fereastră" / „NU — nicio confirmare în 3
candele". Randare cu `ch._render()` (vezi nota din buy_doji_trend.spec.txt).
Fără linie goală în SVG. Generatorul verifică singur că nicio etichetă nu iese
din pânză și că două etichete din același panou nu se suprapun.

View File

@@ -1,60 +1,65 @@
<svg viewBox="0 0 460 614" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif">
<g transform="translate(0,0)">
<svg viewBox="0 0 640 750" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif">
<g transform="translate(0,0)"><rect x="248.0" y="141.0" width="112.0" height="106.0" fill="#1a5fb4" fill-opacity="0.12" stroke="#1a5fb4" stroke-width="1"/><text x="254.0" y="134.0" fill="#1a5fb4" style="font-weight:bold">fereastra: 3 candele</text><line x1="24" y1="200.0" x2="626" y2="200.0" stroke="#b06000" stroke-width="1.5" stroke-dasharray="4 3"/><text x="30" y="215.0" fill="#b06000" text-anchor="start" style="font-weight:bold">high-ul dojiului 50.10</text><text x="30" y="229.0" fill="#b06000" text-anchor="start" style="font-weight:bold">trebuie ÎNCHIS peste,</text><text x="30" y="243.0" fill="#b06000" text-anchor="start" style="font-weight:bold">nu doar atins</text><line x1="24" y1="251.0" x2="626" y2="251.0" stroke="#c00" stroke-width="1.5" stroke-dasharray="4 3"/><text x="30" y="266.0" fill="#c00" text-anchor="start" style="font-weight:bold">low-ul dojiului 49.25</text>
<text x="24" y="48" fill="#333" style="font-weight:bold">DA — confirmare la +2, în fereastră</text>
<line x1="24" y1="164.0" x2="446" y2="164.0" stroke="#b06000" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30" y="158.0" fill="#b06000">high doji 50.10</text>
<line x1="24" y1="204.5" x2="446" y2="204.5" stroke="#c00" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30" y="198.5" fill="#c00">low doji 49.20</text>
<line x1="44.0" y1="56.0" x2="44.0" y2="76.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="37.5" y="62.7" width="13" height="6.7" fill="#c00"/>
<line x1="84.0" y1="62.7" x2="84.0" y2="112.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="77.5" y="69.5" width="13" height="36.0" fill="#c00"/>
<line x1="124.0" y1="98.8" x2="124.0" y2="148.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="117.5" y="105.5" width="13" height="36.0" fill="#c00"/>
<line x1="164.0" y1="134.8" x2="164.0" y2="191.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="157.5" y="141.5" width="13" height="42.8" fill="#c00"/>
<line x1="204.0" y1="164.0" x2="204.0" y2="204.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="197.5" y="184.3" width="13" height="2.2" fill="#c00"/>
<line x1="244.0" y1="166.3" x2="244.0" y2="193.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="237.5" y="173.0" width="13" height="13.5" fill="#188a3e"/>
<line x1="284.0" y1="143.8" x2="284.0" y2="179.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="277.5" y="150.5" width="13" height="22.5" fill="#188a3e"/>
<line x1="324.0" y1="125.8" x2="324.0" y2="157.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="317.5" y="132.5" width="13" height="18.0" fill="#188a3e"/>
<text x="204.0" y="154.0" fill="#b06000" text-anchor="middle" style="font-weight:bold">doji</text>
<text x="284.0" y="133.8" fill="#188a3e" text-anchor="middle" style="font-weight:bold">confirmare +2 — intrare 50.40</text>
<text x="24" y="226.5" fill="#188a3e">+1: close 49.90 — sub 50.10, nu confirmă</text>
<text x="24" y="243.5" fill="#188a3e">+2: close 50.40 — peste 50.10, confirmă (intrare la close)</text>
<line x1="64.0" y1="56.0" x2="64.0" y2="83.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="57.5" y="65.0" width="13" height="9.0" fill="#c00"/>
<line x1="104.0" y1="65.0" x2="104.0" y2="131.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="97.5" y="74.0" width="13" height="48.0" fill="#c00"/>
<line x1="144.0" y1="113.0" x2="144.0" y2="179.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="137.5" y="122.0" width="13" height="48.0" fill="#c00"/>
<line x1="184.0" y1="161.0" x2="184.0" y2="236.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="177.5" y="170.0" width="13" height="57.0" fill="#c00"/>
<line x1="224.0" y1="200.0" x2="224.0" y2="251.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="217.5" y="227.0" width="13" height="3.0" fill="#c00"/>
<line x1="264.0" y1="203.0" x2="264.0" y2="239.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="257.5" y="212.0" width="13" height="18.0" fill="#188a3e"/>
<line x1="304.0" y1="173.0" x2="304.0" y2="221.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="297.5" y="182.0" width="13" height="30.0" fill="#188a3e"/>
<line x1="344.0" y1="149.0" x2="344.0" y2="191.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="337.5" y="158.0" width="13" height="24.0" fill="#188a3e"/>
<text x="224.0" y="190.0" fill="#b06000" text-anchor="middle" style="font-weight:bold">doji</text>
<line x1="264.0" y1="269.0" x2="264.0" y2="251.0" stroke="#c00" stroke-width="1.8"/>
<polygon points="264.0,243.0 268.0,251.0 260.0,251.0" fill="#c00"/>
<text x="264.0" y="283.0" fill="#c00" text-anchor="middle" style="font-weight:bold">aici NU intri: s-a închis sub 50.10</text>
<text x="264.0" y="297.0" fill="#c00" text-anchor="middle" style="font-weight:bold">semnalul cere o ÎNCHIDERE peste</text>
<line x1="364.5" y1="228.0" x2="320.4" y2="187.4" stroke="#188a3e" stroke-width="1.8"/>
<polygon points="314.5,182.0 323.1,184.5 317.7,190.4" fill="#188a3e"/>
<text x="368.5" y="218.0" fill="#188a3e" text-anchor="start" style="font-weight:bold">AICI INTRI, la close 50.40</text>
<text x="368.5" y="232.0" fill="#188a3e" text-anchor="start" style="font-weight:bold">prima închidere peste</text>
<text x="368.5" y="246.0" fill="#188a3e" text-anchor="start" style="font-weight:bold">high-ul dojiului</text>
</g>
<g transform="translate(0,298)">
<g transform="translate(0,332)"><rect x="248.0" y="186.0" width="112.0" height="61.0" fill="#1a5fb4" fill-opacity="0.12" stroke="#1a5fb4" stroke-width="1"/><text x="254.0" y="179.0" fill="#1a5fb4" style="font-weight:bold">fereastra: 3 candele</text><line x1="24" y1="200.0" x2="626" y2="200.0" stroke="#b06000" stroke-width="1.5" stroke-dasharray="4 3"/><text x="30" y="215.0" fill="#b06000" text-anchor="start" style="font-weight:bold">high-ul dojiului 50.10</text><text x="30" y="229.0" fill="#b06000" text-anchor="start" style="font-weight:bold">trebuie ÎNCHIS peste,</text><text x="30" y="243.0" fill="#b06000" text-anchor="start" style="font-weight:bold">nu doar atins</text><line x1="24" y1="251.0" x2="626" y2="251.0" stroke="#c00" stroke-width="1.5" stroke-dasharray="4 3"/><text x="30" y="266.0" fill="#c00" text-anchor="start" style="font-weight:bold">low-ul dojiului 49.25</text>
<text x="24" y="48" fill="#333" style="font-weight:bold">NU — nicio confirmare în 3 candele</text>
<line x1="24" y1="164.0" x2="446" y2="164.0" stroke="#b06000" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30" y="158.0" fill="#b06000">high doji 50.10</text>
<line x1="24" y1="204.5" x2="446" y2="204.5" stroke="#c00" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30" y="198.5" fill="#c00">low doji 49.20</text>
<line x1="44.0" y1="56.0" x2="44.0" y2="76.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="37.5" y="62.7" width="13" height="6.7" fill="#c00"/>
<line x1="84.0" y1="62.7" x2="84.0" y2="112.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="77.5" y="69.5" width="13" height="36.0" fill="#c00"/>
<line x1="124.0" y1="98.8" x2="124.0" y2="148.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="117.5" y="105.5" width="13" height="36.0" fill="#c00"/>
<line x1="164.0" y1="134.8" x2="164.0" y2="191.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="157.5" y="141.5" width="13" height="42.8" fill="#c00"/>
<line x1="204.0" y1="164.0" x2="204.0" y2="204.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="197.5" y="184.3" width="13" height="2.2" fill="#c00"/>
<line x1="244.0" y1="164.0" x2="244.0" y2="193.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="237.5" y="170.7" width="13" height="15.8" fill="#188a3e"/>
<line x1="284.0" y1="159.5" x2="284.0" y2="177.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="277.5" y="166.3" width="13" height="4.5" fill="#188a3e"/>
<line x1="324.0" y1="159.5" x2="324.0" y2="182.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="317.5" y="166.3" width="13" height="9.0" fill="#c00"/>
<line x1="364.0" y1="168.5" x2="364.0" y2="213.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="357.5" y="175.2" width="13" height="31.5" fill="#c00"/>
<text x="204.0" y="154.0" fill="#b06000" text-anchor="middle" style="font-weight:bold">doji</text>
<text x="364.0" y="158.5" fill="#c00" text-anchor="middle" style="font-weight:bold">a 4-a</text>
<text x="24" y="235.5" fill="#188a3e">+1: 49.95; +2: 50.05; +3: 49.85 — toate sub 50.10</text>
<text x="24" y="252.5" fill="#c00">a 4-a: close 49.15 — sub low-ul dojiului 49.20, setup mort</text>
<line x1="64.0" y1="56.0" x2="64.0" y2="83.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="57.5" y="65.0" width="13" height="9.0" fill="#c00"/>
<line x1="104.0" y1="65.0" x2="104.0" y2="131.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="97.5" y="74.0" width="13" height="48.0" fill="#c00"/>
<line x1="144.0" y1="113.0" x2="144.0" y2="179.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="137.5" y="122.0" width="13" height="48.0" fill="#c00"/>
<line x1="184.0" y1="161.0" x2="184.0" y2="236.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="177.5" y="170.0" width="13" height="57.0" fill="#c00"/>
<line x1="224.0" y1="200.0" x2="224.0" y2="251.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="217.5" y="227.0" width="13" height="3.0" fill="#c00"/>
<line x1="264.0" y1="200.0" x2="264.0" y2="239.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="257.5" y="209.0" width="13" height="21.0" fill="#188a3e"/>
<line x1="304.0" y1="194.0" x2="304.0" y2="218.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="297.5" y="203.0" width="13" height="6.0" fill="#188a3e"/>
<line x1="344.0" y1="194.0" x2="344.0" y2="224.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="337.5" y="203.0" width="13" height="12.0" fill="#c00"/>
<line x1="384.0" y1="206.0" x2="384.0" y2="266.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="377.5" y="215.0" width="13" height="42.0" fill="#c00"/>
<text x="224.0" y="190.0" fill="#b06000" text-anchor="middle" style="font-weight:bold">doji</text>
<text x="384.0" y="196.0" fill="#c00" text-anchor="middle" style="font-weight:bold">a 4-a</text>
<line x1="479.0" y1="164.0" x2="351.9" y2="188.5" stroke="#c00" stroke-width="1.8"/>
<polygon points="344.0,190.0 351.1,184.6 352.6,192.4" fill="#c00"/>
<text x="479.0" y="145.0" fill="#c00" text-anchor="middle" style="font-weight:bold">a treia s-a închis tot sub 50.10</text>
<text x="479.0" y="159.0" fill="#c00" text-anchor="middle" style="font-weight:bold">fereastra s-a terminat: ștergi setup-ul</text>
<line x1="384.0" y1="296.0" x2="384.0" y2="278.0" stroke="#c00" stroke-width="1.8"/>
<polygon points="384.0,270.0 388.0,278.0 380.0,278.0" fill="#c00"/>
<text x="384.0" y="310.0" fill="#c00" text-anchor="middle" style="font-weight:bold">a închis sub low-ul dojiului</text>
<text x="384.0" y="324.0" fill="#c00" text-anchor="middle" style="font-weight:bold">setup mort — nu mai intri</text>
<text x="24" y="355.0" fill="#c00">+1: 49.95 · +2: 50.05 · +3: 49.85 — toate sub 50.10</text>
</g>
<text x="24" y="592" fill="#555">Serii construite: open = close-ul barei anterioare.</text>
<text x="24" y="609" fill="#555">Doji: h 50.10 / l 49.20. Fereastra = maximum 3 candele după doji.</text>
<text x="24" y="728" fill="#555">Serii construite: open = close-ul barei anterioare.</text>
<text x="24" y="745" fill="#555">Doji: h 50.10 / l 49.25. Fereastra = maximum 3 candele după doji.</text>
</svg>

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 7.0 KiB

View File

@@ -1,222 +1,150 @@
#!/usr/bin/env python3
"""Buy Doji — ieșirea: trailing stop pe gap-uri și limita de 8 candele.
"""Buy Doji — ieșirea: prima treime la țintă, a doua pe trailing stop, limita de 8 candele.
Citește `gen/strategii/buy_doji_iesire.spec.txt` și scrie
`gen/strategii/buy_doji_iesire.svg`: două panouri stivuite.
Citește `gen/strategii/buy_doji_iesire.spec.txt`. Barele vin din
`buy_doji_ansamblu.serie()` — același trade ca în restul capitolului
(doji 50.10/49.25, intrare 50.40, stop 49.20, ținta 1 51.60).
A — seria din buy_doji_transe (barele 0-18) continuată cu 19-23. Barele 19
și 21 deschid cu GAP (excepție cerută de spec): regula de trail cere o
bară cu low peste high-ul precedentei, imposibil dacă open = close
anterior. De aceea barele 15-23 sunt construite explicit, nu cu
`from_closes`.
B — doji 50.10 / 49.20, intrare 50.40, apoi 8 candele fără TP și fără SL.
A — prima treime iese la ținta 51.60; apoi două candele cu gap urcă linia
de trailing stop (51.95, apoi 52.60); a doua treime iese la prima
închidere sub linie, 52.30 (+1.58R).
B — același setup, dar prețul stă 8 candele între stop și țintă: ieși la
close-ul celei de-a 8-a, 50.70 (+0.25R).
Barele de după intrare, în ambele panouri, sunt CONSTRUITE.
Sursa regulilor: summaries/03_MODUL_2/13_strategia_3_byh.md:196-213.
Rulare: python3 gen/strategii/buy_doji_iesire.py
Barele de după intrare din panoul B sunt CONSTRUITE.
"""
import re
import sys
from pathlib import Path
sys.path.insert(0, "/workspace/atm-curs-dl")
from svg_candles import Candle, Chart, Level, Mark, from_closes # noqa: E402
sys.path.insert(0, str(Path(__file__).parent))
from svg_candles import Chart, Level, Zone, Arrow, from_closes # noqa: E402
from buy_doji_ansamblu import serie, CONF, ENTRY, SL, TP1, R, trail # noqa: E402
OUT = Path(__file__).with_suffix(".svg")
W = 660
VGAP = 10
S = 10 # prima bară arătată
GREEN, RED, ORANGE, BLUE, GREY = "#188a3e", "#c00", "#b06000", "#1a5fb4", "#555"
W, VGAP = 760, 14
# --- PANOUL A ----------------------------------------------------------------
ENTRY_A, SL_A, TP1_A = 53.70, 51.55, 55.85
R_A = round(ENTRY_A - SL_A, 2) # 2.15
full = serie()
steps, iesire = trail(full) # [(21, 51.95), (27, 52.60)], 28
a = full[S:iesire + 1]
cf = CONF - S
EXIT_A = a[iesire - S].c
R_A = round((EXIT_A - ENTRY) / R, 2)
tp_i = next(i for i in range(CONF + 1, len(full)) if full[i].h >= TP1)
a = from_closes([60.40, 59.60, 59.90, 58.80, 58.10, 58.40, 57.20, 56.30,
56.60, 55.30, 54.20, 52.40], wick=0.15, start=61.00)
a += [Candle(*ohlc) for ohlc in [
(52.40, 53.00, 51.60, 52.30), # 12 doji
(52.30, 52.85, 52.10, 52.60), # 13 +1
(52.60, 53.85, 52.45, 53.70), # 14 confirmare = intrare
(53.70, 53.80, 53.10, 53.45), # 15
(53.45, 54.20, 53.35, 54.10), # 16
(54.10, 54.85, 54.00, 54.70), # 17
(54.70, 56.00, 54.60, 55.90), # 18 atinge TP1
(56.30, 56.95, 56.20, 56.80), # 19 GAP
(56.80, 57.35, 56.60, 57.20), # 20
(57.60, 58.10, 57.45, 57.90), # 21 GAP
(57.90, 58.00, 57.50, 57.60), # 22
(57.60, 57.70, 57.10, 57.20), # 23 close sub trail
]]
assert len(a) == 24
# --- aserțiunile panoului A -------------------------------------------------------
assert steps == [(21, 51.95), (27, 52.60)] and iesire == 28, (steps, iesire)
for i, t in steps: # gap-urile sunt reale
assert full[i].l > full[i - 1].h, f"bara {i} nu deschide cu gap"
assert all(full[i].c >= steps[0][1] for i in range(steps[0][0], iesire)), \
"ar fi ieșit mai devreme: un close sub linia de trail"
assert EXIT_A == 52.30 and R_A == 1.58 and EXIT_A < steps[-1][1]
assert tp_i == 19 and full[tp_i].h >= TP1 > full[tp_i - 1].h, tp_i
for c in a:
assert c.l <= min(c.o, c.c) and c.h >= max(c.o, c.c), "h/l nu cuprind o/c"
# A1. gap-urile reale
assert a[19].l > a[18].h and a[21].l > a[20].h, "barele de gap nu au low > high anterior"
# A2. open = close anterior, în afară de 19 și 21 (și 0-14, ca în transe)
for i in range(1, 24):
if i not in (19, 21):
assert abs(a[i].o - a[i - 1].c) < 1e-9, f"A: open[{i}] != close[{i-1}]"
# regula de trail, calculată pe serie: primul gap după intrare stabilește
# trail-ul, fiecare gap următor îl urcă; ieși la primul close sub el
trail, steps, exit_i = None, [], None
for i in range(15, 24):
if trail is not None and a[i].c < trail:
exit_i = i
break
if a[i].l > a[i - 1].h:
trail = a[i].l
steps.append((i, trail))
assert [(i, round(t, 2)) for i, t in steps] == [(19, 56.20), (21, 57.45)], steps
# A3.
assert a[22].c >= 57.45 and a[23].c < 57.45 and exit_i == 23, exit_i
EXIT_A = a[23].c
# A4.
assert R_A == 2.15 and round((EXIT_A - ENTRY_A) / R_A, 2) == 1.63
# A5. TP1 = 1R, atins prima oară la bara 18
assert round(ENTRY_A + R_A, 2) == TP1_A
assert next(i for i in range(15, 24) if a[i].h >= TP1_A) == 18
assert abs(a[14].c - ENTRY_A) < 1e-9
# --- panoul B: 8 candele între stop și țintă --------------------------------------
b = full[S:CONF + 1]
b += from_closes([50.60, 50.30, 50.90, 50.50, 51.10, 50.80, 51.20, 50.70],
wick=0.15, start=ENTRY)
opt = b[cf + 1:]
EXIT_B = opt[-1].c
R_B = round((EXIT_B - ENTRY) / R, 2)
assert len(opt) == 8, len(opt)
for i in range(1, len(b)):
assert abs(b[i].o - b[i - 1].c) < 1e-9, f"B: open[{i}] != close[{i-1}]"
assert all(c.h < TP1 and c.l > SL for c in opt), "B: o bară atinge ținta sau stopul"
assert (round(max(c.h for c in opt), 2), round(min(c.l for c in opt), 2)) == (51.35, 50.15)
assert EXIT_B == 50.70 and R_B == 0.25
print(f"iesire A: treapta 1 {steps[0][1]:.2f}, treapta 2 {steps[1][1]:.2f}, "
f"ieșire {EXIT_A:.2f} = +{R_A}R (ținta 1 {TP1:.2f} la bara {tp_i}); "
f"B: ieșire {EXIT_B:.2f} = +{R_B}R")
common: dict = dict(scale=40.0, gap=18, body_w=9, left=48, width=W)
ch_a = Chart(
candles=a,
levels=[Level(ENTRY_A, "intrare 53.70", GREEN),
Level(TP1_A, "TP1 55.85 — tranșa 1: +1R", GREEN, dash="2 3")],
scale=40, gap=16, body_w=9, left=44, width=W,
title="A — trailing stop pe gap-uri (seria de la intrarea în tranșe)",
caption="a treia treime: o lași mai departe (break-even / trend)",
levels=[Level(TP1, "ținta 1: 51.60 (= 1R)", GREEN, "2 3"),
Level(ENTRY, "intrarea: 50.40", GREY, "4 3"),
Level(SL, "stopul: 49.20", RED, "4 3")],
zones=[Zone(cf, tp_i - S, "", GREEN), Zone(tp_i - S + 1, iesire - S, "", BLUE)],
arrows=[
Arrow(tp_i - S, "ținta 1 atinsă: vinzi prima treime\nai luat exact cât riscai (1R)",
where="above", price=TP1, color=GREEN, dx=10, dy=-26),
Arrow(steps[0][0] - S, "gap: low-ul de azi e peste high-ul de ieri\nlinia de trail urcă la 51.95",
where="below", price=steps[0][1], color=ORANGE, dx=130, dy=40),
Arrow(steps[1][0] - S, "încă un gap: linia urcă la 52.60\nurcă doar, nu coboară niciodată",
where="above", price=steps[1][1], color=ORANGE, dx=150),
Arrow(iesire - S, "prima închidere sub linie: ieși\ncu a doua treime, la 52.30 (+1.58R)",
where="below", price=EXIT_A, color=RED, dx=110, dy=96),
],
title="A — prima treime la țintă, a doua pe trailing stop",
**common,
)
# --- PANOUL B ----------------------------------------------------------------
ENTRY_B, SL_B, TP1_B = 50.40, 49.20, 51.60
R_B = round(ENTRY_B - SL_B, 2) # 1.20
b = from_closes([52.20, 51.40, 50.60, 49.65], wick=0.15, start=53.00)
b += [Candle(*ohlc) for ohlc in [
(49.65, 50.10, 49.20, 49.60), # 4 doji
(49.60, 50.05, 49.45, 49.90), # 5 +1
(49.90, 50.55, 49.75, 50.40), # 6 confirmare = intrare
]]
b += from_closes([50.60, 50.30, 50.90, 50.50, 51.10, 50.80, 51.20, 50.70],
wick=0.15, start=b[-1].c)
assert len(b) == 15
# B1.
for i in range(1, 15):
assert abs(b[i].o - b[i - 1].c) < 1e-9, f"B: open[{i}] != close[{i-1}]"
d = b[4]
assert abs(d.o - d.c) <= 0.10 * (d.h - d.l) and (d.h, d.l) == (50.10, 49.20)
assert b[6].c > d.h and abs(b[6].c - ENTRY_B) < 1e-9
# B2. 8 candele fără TP și fără SL
after = b[7:15]
assert all(c.h < TP1_B and c.l > SL_B for c in after)
assert round(max(c.h for c in after), 2) == 51.35 and round(min(c.l for c in after), 2) == 50.15
assert round(ENTRY_B + R_B, 2) == TP1_B
# B3.
EXIT_B = b[14].c
assert round((EXIT_B - ENTRY_B) / R_B, 2) == 0.25
for k, c in enumerate(after, 1):
c.tag = str(k)
ch_b = Chart(
candles=b,
levels=[Level(TP1_B, "TP1 51.60", GREEN, dash="2 3"),
Level(ENTRY_B, "intrare 50.40", GREEN),
Level(SL_B, "SL 49.20", RED)],
marks=[Mark(4, "doji", ORANGE, "below")],
scale=48, gap=16, body_w=9, left=44, width=W,
title="B — limita de 8 candele",
levels=[Level(TP1, "ținta 1: 51.60 — neatinsă", GREEN, "2 3"),
Level(ENTRY, "intrarea: 50.40", GREY, "4 3"),
Level(SL, "stopul: 49.20 — neatins", RED, "4 3")],
zones=[Zone(cf + 1, len(b) - 1, "", GREY, p_top=TP1, p_bot=SL)],
arrows=[
Arrow(len(b) - 1, "a 8-a candelă: ieși oricum, la close 50.70 (+0.25R)\nbanii blocați aici lipsesc din alt trade",
where="below", price=EXIT_B, color=GREY, dx=120, dy=40),
],
title="B — limita de 8 candele: nici ținta, nici stopul",
**common,
)
for k, c in enumerate(opt, 1):
c.tag = str(k)
# --- etichete plasate de mână: Mark centrează textul, iar aici textele lungi
# ar cădea peste candelele vecine. Le ancorez lângă bară, pe partea liberă.
def label(ch, i, price, text, color, anchor="start", dx=0):
x = ch._cx(i) + dx
return (f'<text x="{x:.1f}" y="{ch._y(price):.1f}" fill="{color}" '
f'text-anchor="{anchor}" style="font-weight:bold">{text}</text>')
def panou(ch, sus_de=0.0):
ch.top += sus_de
svg = ch.render()
h = float(re.search(r'viewBox="0 0 [\d.]+ ([\d.]+)"', svg).group(1))
# render() mută `top`/`left` intern și le restaurează: tot ce desenăm noi
# după randare trebuie deplasat cu aceiași pixeli
off_y = float(re.search(r'<line x1="24" y1="([\d.]+)"', svg).group(1)) - ch._y(ch.levels[0].price)
off_x = float(re.search(r'<line x1="([\d.]+)"[^>]*stroke="#1a1a1a"', svg).group(1)) - ch._cx(0)
return svg[svg.index(">") + 1:svg.rindex("</svg>")].strip(), h, off_x, off_y
def panel(ch, extra):
svg = ch.render() # render() fixează scala (_pmax, top)
h = float(re.search(r'viewBox="0 0 \d+ ([\d.]+)"', svg).group(1))
body = svg[svg.index(">") + 1:svg.rindex("</svg>")].strip()
return body + "".join("\n " + e for e in extra(ch)), h
body_a, h_a, ax, ay = panou(ch_a)
Y, X = (lambda p: ch_a._y(p) + ay), (lambda i: ch_a._cx(i) + ax)
(i1, t1), (i2, t2) = [(i - S, t) for i, t in steps]
extra_a = [
# linia de trail, în trepte
f'<polyline points="{X(i1) - 7:.1f},{Y(t1):.1f} {X(i2) - 7:.1f},{Y(t1):.1f} '
f'{X(i2) - 7:.1f},{Y(t2):.1f} {X(iesire - S) + 7:.1f},{Y(t2):.1f}" '
f'fill="none" stroke="{ORANGE}" stroke-width="2"/>',
f'<text x="{X(iesire - S) + 14:.1f}" y="{Y(t2) + 4:.1f}" fill="{ORANGE}" style="font-weight:bold">'
f'linia de trailing stop</text>',
# etichetele zonelor, lângă ele (Zone le-ar ridica deasupra candelelor vecine)
f'<text x="{X(cf) - 6:.1f}" y="{Y(SL) + 60:.1f}" fill="{GREEN}" style="font-weight:bold">'
f'prima treime: de la intrare la ținta 1:1</text>',
f'<text x="{X(tp_i - S + 1) - 6:.1f}" y="{Y(SL) + 78:.1f}" fill="{BLUE}" style="font-weight:bold">'
f'a doua treime: merge pe trailing stop</text>',
]
extra_a.append(f'<text x="24" y="{Y(SL) + 100:.1f}" fill="{GREY}">A treia treime o lași mai '
f'departe, cu stopul mutat la intrare (break-even).</text>')
h_a = max(h_a, Y(SL) + 112)
def trail_a(ch):
x19, x21, x23 = ch._cx(19) - 7, ch._cx(21) - 8, ch._cx(23) + 7
y1, y2 = ch._y(steps[0][1]), ch._y(steps[1][1])
# golul dintre high-ul barei precedente și low-ul barei de gap, hașurat:
# la 0.10-0.20 de preț are doar câțiva pixeli și se pierde sub linia de trail
gaps = [f'<rect x="{ch._cx(i - 1) - 7:.1f}" y="{ch._y(a[i].l):.1f}" width="{ch.gap + 14}" '
f'height="{ch._y(a[i - 1].h) - ch._y(a[i].l):.1f}" fill="{ORANGE}" opacity="0.35"/>'
for i, _ in steps]
return gaps + [
f'<polyline points="{x19:.1f},{y1:.1f} {x21:.1f},{y1:.1f} {x21:.1f},{y2:.1f} '
f'{x23:.1f},{y2:.1f}" fill="none" stroke="{ORANGE}" stroke-width="2"/>',
label(ch, 18, 56.25, "TP1: ieși cu 1/3", GREEN, "end", 4),
label(ch, 19, 55.35, "gap: low &gt; high anterior → trail 56.20", ORANGE, "start", -4),
label(ch, 21, 58.35, "gap → trail 57.45", ORANGE, "middle"),
label(ch, 23, 57.30, "close sub trail: ieși cu 1/3", RED, "start", 14),
label(ch, 23, 56.88, f"la 57.20 = +{(EXIT_A - ENTRY_A) / R_A:.2f}R", RED, "start", 14),
]
def mark_b(ch):
return [
label(ch, 14, 51.05, "a 8-a candelă: nici TP, nici SL", GREY, "start", 10),
label(ch, 14, 50.75, f"→ ieși la 50.70 = +{(EXIT_B - ENTRY_B) / R_B:.2f}R", GREY, "start", 10),
]
# panourile se stivuiesc prin `top` (nu prin <g transform>): audit_diagrams
# citește coordonatele brute și ar vedea panourile suprapuse.
T = 26
ch_a.top += T
body_a, h_a = panel(ch_a, trail_a)
ch_b.top += h_a + VGAP
body_b, H_B = panel(ch_b, mark_b)
TITLE = "Ieșirea: trailing stop pe gap-uri și limita de 8 candele — exemple construite"
CAP = "Barele de după intrare sunt construite. Regulile: 13_strategia_3_byh.md:196-213."
cap_y = H_B + 12
H = cap_y + 10
body_b, h_b, bx, by = panou(ch_b, h_a + VGAP)
extra_b = [
f'<text x="{ch_b._cx(cf + 1) + bx - 6:.1f}" y="{ch_b._y(TP1) + by - 8:.1f}" fill="{GREY}" '
f'style="font-weight:bold">8 candele în care nu se întâmplă nimic</text>',
]
H = h_b + 8
svg = "\n ".join([
f'<svg viewBox="0 0 {W} {H:.0f}" xmlns="http://www.w3.org/2000/svg" '
f'style="width:100%;height:auto;font:12px sans-serif">',
f'<text x="24" y="18" fill="#333" style="font-weight:bold">{TITLE}</text>',
body_a,
body_b,
f'<text x="24" y="{cap_y:.0f}" fill="{GREY}">{CAP}</text>',
body_a, *extra_a,
f'<line x1="24" y1="{h_a + VGAP / 2:.0f}" x2="{W - 14}" y2="{h_a + VGAP / 2:.0f}" stroke="#ddd"/>',
body_b, *extra_b,
]) + "\n</svg>"
assert "\n\n" not in svg
# --- etichete în panză și fără suprapuneri (lățimi aproximate) ---------------
TEXT = re.compile(r'<text x="([-\d.]+)" y="([-\d.]+)"([^>]*)>(.*?)</text>', re.S)
def texts(body, y_off, tag):
for m in TEXT.finditer(body):
x, y, attrs = float(m.group(1)), float(m.group(2)) + y_off, m.group(3)
s = m.group(4).replace("&gt;", ">")
wpx = len(s) * 12 * (0.62 if "bold" in attrs else 0.52)
anchor = re.search(r'text-anchor="(\w+)"', attrs)
anchor = anchor.group(1) if anchor else "start"
x0 = x - wpx if anchor == "end" else (x - wpx / 2 if anchor == "middle" else x)
yield x0, x0 + wpx, y, s, tag
labels = list(texts(body_a, 0, "A")) + list(texts(body_b, 0, "B"))
for x0, x1, y, s, tag in labels:
assert x0 >= -2 and x1 <= W + 2 and 0 <= y <= H, f"[{tag}] text iese din panză: {s!r}"
for i, (l1, r1, y1, s1, t1) in enumerate(labels):
for l2, r2, y2, s2, t2 in labels[i + 1:]:
assert not (t1 == t2 and abs(y1 - y2) < 12 and l1 < r2 - 4 and l2 < r1 - 4), \
f"[{t1}] texte suprapuse: {s1!r} / {s2!r}"
assert "\n\n" not in svg, "linie goală în SVG"
for tx, ty in re.findall(r'<text x="([-\d.]+)" y="([-\d.]+)"', svg):
assert 0 <= float(tx) <= W and 0 <= float(ty) <= H, f"text în afara pânzei la ({tx}, {ty})"
OUT.write_text(svg, encoding="utf-8")
print(f"A: trail {steps}, ieșire bara {exit_i} la {EXIT_A:.2f} = "
f"+{(EXIT_A - ENTRY_A) / R_A:.2f}R; B: ieșire la {EXIT_B:.2f} = "
f"+{(EXIT_B - ENTRY_B) / R_B:.2f}R")
print(f"scris {OUT} ({W}x{H:.0f})")

View File

@@ -1,57 +1,51 @@
SPEC DIAGRAMĂ — buy_doji_iesire
===============================
tip: PRET, două panouri stivuite
destinație: summaries/17_STRATEGII/01_buy_doji.md, Pasul 9 (ieșirea)
destinație: summaries/17_STRATEGII/01_buy_doji.md, pasul cu ieșirea
cheie markdown: <!-- DIAGRAMA: iesire -->
titlu SVG: „Ieșirea: trailing stop pe gap-uri și limita de 8 candele — exemple construite"
stil: candele lipite (gap 15-18, body_w 9-10), fără volum.
EXCEPȚIE CERUTĂ: în panoul A, barele 19 și 21 deschid cu GAP
(open != close anterior). Regula de trail are nevoie de o bară
cu low peste high-ul precedentei, ceea ce fără gap e imposibil.
Toate celelalte bare: open = close anterior.
titluri SVG: A „prima treime la țintă, a doua pe trailing stop";
B „limita de 8 candele: nici ținta, nici stopul"
serie: `buy_doji_ansamblu.serie()` — A: barele 10-28; B: barele 10-16
plus 8 bare construite.
PANOUL A — trailing stop (seria buy_doji_transe, continuată)
------------------------------------------------------------
Barele 0-18: identice cu buy_doji_transe. Apoi:
19 (56.30, 56.95, 56.20, 56.80) GAP: low 56.20 > high[18] 56.00 → trail = 56.20
20 (56.80, 57.35, 56.60, 57.20)
21 (57.60, 58.10, 57.45, 57.90) GAP: low 57.45 > high[20] 57.35 → trail urcă la 57.45
22 (57.90, 58.00, 57.50, 57.60) close 57.60 ≥ 57.45: rămâi
23 (57.60, 57.70, 57.10, 57.20) close 57.20 < 57.45: ieși
Niveluri: intrare 53.70; TP1 55.85 („tranșa 1: +1R"); trail în trepte:
segment 56.20 de la bara 19 la 20, segment 57.45 de la bara 21 la 23.
Marks: Mark(18, "TP1: ieși cu 1/3"), Mark(19, "gap: low > high anterior → trail 56.20"),
Mark(21, "trail 57.45"), Mark(23, "close sub trail: ieși cu 1/3 la 57.20 = +1.63R").
Text sub panou: „a treia treime: o lași mai departe (break-even / trend)".
PANOUL A — ieșirea în trepte
----------------------------
Intrare 50.40, stop 49.20, 1R = 1.20.
- ținta 1 51.60 atinsă la bara 19: iese prima treime (+1R);
- bara 21 deschide cu gap (low 51.95 > high[20] 51.85): linia de trailing stop
se așază la 51.95;
- bara 27, alt gap (low 52.60 > high[26] 52.55): linia urcă la 52.60;
- bara 28 închide la 52.30, sub linie: iese a doua treime, +1.58R;
- a treia treime rămâne mai departe, cu stopul la intrare (break-even).
Adnotări: zonă verde de la intrare la țintă, zonă albastră pe porțiunea de
trail, linia de trail desenată în trepte, patru săgeți (ținta atinsă, primul
gap, al doilea gap, ieșirea).
PANOUL B — limita de 8 candele
------------------------------
open[0] = 53.00; close-uri: 52.20, 51.40, 50.60, 49.65, fitile 0.15;
4 doji (49.65, 50.10, 49.20, 49.60)
5 +1 (49.60, 50.05, 49.45, 49.90)
6 confirmare (49.90, 50.55, 49.75, 50.40) intrare 50.40
7-14 close-uri: 50.60, 50.30, 50.90, 50.50, 51.10, 50.80, 51.20, 50.70
(fitile 0.15; open = close anterior)
Niveluri: intrare 50.40, SL 49.20, TP1 51.60.
Numerotare 1..8 sub barele 7-14. Mark(14, "a 8-a candelă: nici TP, nici SL → ieși la 50.70 = +0.25R").
Aceleași bare până la confirmare, apoi 8 bare construite, close-uri 50.60,
50.30, 50.90, 50.50, 51.10, 50.80, 51.20, 50.70 (fitile 0.15, open = close
anterior). Niciuna nu atinge ținta 51.60 sau stopul 49.20 (max high 51.35, min
low 50.15). La close-ul celei de-a 8-a ieși oricum: 50.70 = +0.25R.
Adnotări: zonă gri între stop și țintă peste cele 8 bare, numerotate 1..8, și o
săgeată: „banii blocați aici lipsesc din alt trade".
ASSERT-URI
----------
A1. low[19] > high[18] și low[21] > high[20] (gap-urile reale).
A2. open[i] == close[i-1] pentru i în 15..23, cu excepția 19 și 21.
A3. close[22] >= 57.45 și close[23] < 57.45; primul close sub trail după bara 19 e 23.
A4. round((57.20-53.70)/2.15, 2) == 1.63.
A5. primul i>14 cu high >= 55.85 este 18.
B1. open[i] == close[i-1] peste tot; doji abs(o-c) <= 0.10*(h-l); close[6] > 50.10.
B2. pentru barele 7-14: high < 51.60 și low > 49.20 (max high 51.35, min low 50.15).
B3. round((50.70-50.40)/1.20, 2) == 0.25.
A1. regula de trail, calculată pe serie, dă [(21, 51.95), (27, 52.60)];
barele 21 și 27 au low peste high-ul barei precedente (gap-uri reale).
A2. niciun close între bara 21 și ieșire nu e sub 51.95 (n-ar fi ieșit mai devreme).
A3. ieșirea: close 52.30 la bara 28, sub 52.60; (52.30 - 50.40) / 1.20 == 1.58.
A4. ținta 51.60 e atinsă prima dată la bara 19 (bara 18 nu o atinge).
B1. open[i] == close[i-1] pe toată seria; exact 8 bare după intrare.
B2. toate cele 8 au high < 51.60 și low > 49.20; max high 51.35, min low 50.15.
B3. ieșire 50.70; (50.70 - 50.40) / 1.20 == 0.25.
B4. niciun text nu iese din pânză.
SURSA
-----
- Trail: low-ul barei cu low peste high-ul precedentei; ieși la close sub el:
summaries/03_MODUL_2/13_strategia_3_byh.md:196-200.
- 3 poziții (1/3 TP, 1/3 trail, 1/3 mai departe): :204-213 (tabel marcat de
sumarizator ca completare, :341-350).
- Trei poziții (1/3 la țintă, 1/3 pe trail, 1/3 mai departe): :204-213.
- Limita de 8 candele: :201-202.
- Doji 50.10/49.20, intrare 50.40, SL 49.20: exemplul lecției, :158-167.
- Barele după intrare, în ambele panouri, sunt CONSTRUITE.
- Barele de după intrare din panoul B sunt CONSTRUITE.

View File

@@ -1,114 +1,122 @@
<svg viewBox="0 0 660 826" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif">
<text x="24" y="18" fill="#333" style="font-weight:bold">Ieșirea: trailing stop pe gap-uri și limita de 8 candele — exemple construite</text>
<text x="24" y="74" fill="#333" style="font-weight:bold">A — trailing stop pe gap-uri (seria de la intrarea în tranșe)</text>
<line x1="24" y1="380.0" x2="646" y2="380.0" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="632" y="374.0" fill="#188a3e" text-anchor="end">intrare 53.70</text>
<line x1="24" y1="294.0" x2="646" y2="294.0" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="2 3"/>
<text x="632" y="288.0" fill="#188a3e" text-anchor="end">TP1 55.85 — tranșa 1: +1R</text>
<line x1="44.0" y1="82.0" x2="44.0" y2="118.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="39.5" y="88.0" width="9" height="24.0" fill="#c00"/>
<line x1="60.0" y1="106.0" x2="60.0" y2="150.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="55.5" y="112.0" width="9" height="32.0" fill="#c00"/>
<line x1="76.0" y1="126.0" x2="76.0" y2="150.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="71.5" y="132.0" width="9" height="12.0" fill="#188a3e"/>
<line x1="92.0" y1="126.0" x2="92.0" y2="182.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="87.5" y="132.0" width="9" height="44.0" fill="#c00"/>
<line x1="108.0" y1="170.0" x2="108.0" y2="210.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="103.5" y="176.0" width="9" height="28.0" fill="#c00"/>
<line x1="124.0" y1="186.0" x2="124.0" y2="210.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="119.5" y="192.0" width="9" height="12.0" fill="#188a3e"/>
<line x1="140.0" y1="186.0" x2="140.0" y2="246.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="135.5" y="192.0" width="9" height="48.0" fill="#c00"/>
<line x1="156.0" y1="234.0" x2="156.0" y2="282.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="151.5" y="240.0" width="9" height="36.0" fill="#c00"/>
<line x1="172.0" y1="258.0" x2="172.0" y2="282.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="167.5" y="264.0" width="9" height="12.0" fill="#188a3e"/>
<line x1="188.0" y1="258.0" x2="188.0" y2="322.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="183.5" y="264.0" width="9" height="52.0" fill="#c00"/>
<line x1="204.0" y1="310.0" x2="204.0" y2="366.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="199.5" y="316.0" width="9" height="44.0" fill="#c00"/>
<line x1="220.0" y1="354.0" x2="220.0" y2="438.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="215.5" y="360.0" width="9" height="72.0" fill="#c00"/>
<line x1="236.0" y1="408.0" x2="236.0" y2="464.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="231.5" y="432.0" width="9" height="4.0" fill="#c00"/>
<line x1="252.0" y1="414.0" x2="252.0" y2="444.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="247.5" y="424.0" width="9" height="12.0" fill="#188a3e"/>
<line x1="268.0" y1="374.0" x2="268.0" y2="430.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="263.5" y="380.0" width="9" height="44.0" fill="#188a3e"/>
<line x1="284.0" y1="376.0" x2="284.0" y2="404.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="279.5" y="380.0" width="9" height="10.0" fill="#c00"/>
<line x1="300.0" y1="360.0" x2="300.0" y2="394.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="295.5" y="364.0" width="9" height="26.0" fill="#188a3e"/>
<line x1="316.0" y1="334.0" x2="316.0" y2="368.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="311.5" y="340.0" width="9" height="24.0" fill="#188a3e"/>
<line x1="332.0" y1="288.0" x2="332.0" y2="344.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="327.5" y="292.0" width="9" height="48.0" fill="#188a3e"/>
<line x1="348.0" y1="250.0" x2="348.0" y2="280.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="343.5" y="256.0" width="9" height="20.0" fill="#188a3e"/>
<line x1="364.0" y1="234.0" x2="364.0" y2="264.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="359.5" y="240.0" width="9" height="16.0" fill="#188a3e"/>
<line x1="380.0" y1="204.0" x2="380.0" y2="230.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="375.5" y="212.0" width="9" height="12.0" fill="#188a3e"/>
<line x1="396.0" y1="208.0" x2="396.0" y2="228.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="391.5" y="212.0" width="9" height="12.0" fill="#c00"/>
<line x1="412.0" y1="220.0" x2="412.0" y2="244.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="407.5" y="224.0" width="9" height="16.0" fill="#c00"/>
<text x="24" y="494" fill="#555">a treia treime: o lași mai departe (break-even / trend)</text>
<rect x="325.0" y="280.0" width="30" height="8.0" fill="#b06000" opacity="0.35"/>
<rect x="357.0" y="230.0" width="30" height="4.0" fill="#b06000" opacity="0.35"/>
<polyline points="341.0,280.0 372.0,280.0 372.0,230.0 419.0,230.0" fill="none" stroke="#b06000" stroke-width="2"/>
<text x="336.0" y="278.0" fill="#188a3e" text-anchor="end" style="font-weight:bold">TP1: ieși cu 1/3</text>
<text x="344.0" y="314.0" fill="#b06000" text-anchor="start" style="font-weight:bold">gap: low &gt; high anterior → trail 56.20</text>
<text x="380.0" y="194.0" fill="#b06000" text-anchor="middle" style="font-weight:bold">gap → trail 57.45</text>
<text x="426.0" y="236.0" fill="#c00" text-anchor="start" style="font-weight:bold">close sub trail: ieși cu 1/3</text>
<text x="426.0" y="252.8" fill="#c00" text-anchor="start" style="font-weight:bold">la 57.20 = +1.63R</text>
<text x="24" y="564" fill="#333" style="font-weight:bold">B — limita de 8 candele</text>
<line x1="24" y1="646.4" x2="646" y2="646.4" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="2 3"/>
<text x="632" y="640.4" fill="#188a3e" text-anchor="end">TP1 51.60</text>
<line x1="24" y1="704.0" x2="646" y2="704.0" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="632" y="698.0" fill="#188a3e" text-anchor="end">intrare 50.40</text>
<line x1="24" y1="761.6" x2="646" y2="761.6" stroke="#c00" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="632" y="755.6" fill="#c00" text-anchor="end">SL 49.20</text>
<line x1="44.0" y1="572.0" x2="44.0" y2="624.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="39.5" y="579.2" width="9" height="38.4" fill="#c00"/>
<line x1="60.0" y1="610.4" x2="60.0" y2="663.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="55.5" y="617.6" width="9" height="38.4" fill="#c00"/>
<line x1="76.0" y1="648.8" x2="76.0" y2="701.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="71.5" y="656.0" width="9" height="38.4" fill="#c00"/>
<line x1="92.0" y1="687.2" x2="92.0" y2="747.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="87.5" y="694.4" width="9" height="45.6" fill="#c00"/>
<line x1="108.0" y1="718.4" x2="108.0" y2="761.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="103.5" y="740.0" width="9" height="2.4" fill="#c00"/>
<line x1="124.0" y1="720.8" x2="124.0" y2="749.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="119.5" y="728.0" width="9" height="14.4" fill="#188a3e"/>
<line x1="140.0" y1="696.8" x2="140.0" y2="735.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="135.5" y="704.0" width="9" height="24.0" fill="#188a3e"/>
<line x1="156.0" y1="687.2" x2="156.0" y2="711.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="151.5" y="694.4" width="9" height="9.6" fill="#188a3e"/>
<text x="156.0" y="779.6" fill="#188a3e" text-anchor="middle" style="font-weight:bold">1</text>
<line x1="172.0" y1="687.2" x2="172.0" y2="716.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="167.5" y="694.4" width="9" height="14.4" fill="#c00"/>
<text x="172.0" y="779.6" fill="#c00" text-anchor="middle" style="font-weight:bold">2</text>
<line x1="188.0" y1="672.8" x2="188.0" y2="716.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="183.5" y="680.0" width="9" height="28.8" fill="#188a3e"/>
<text x="188.0" y="779.6" fill="#188a3e" text-anchor="middle" style="font-weight:bold">3</text>
<line x1="204.0" y1="672.8" x2="204.0" y2="706.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="199.5" y="680.0" width="9" height="19.2" fill="#c00"/>
<text x="204.0" y="779.6" fill="#c00" text-anchor="middle" style="font-weight:bold">4</text>
<line x1="220.0" y1="663.2" x2="220.0" y2="706.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="215.5" y="670.4" width="9" height="28.8" fill="#188a3e"/>
<text x="220.0" y="779.6" fill="#188a3e" text-anchor="middle" style="font-weight:bold">5</text>
<line x1="236.0" y1="663.2" x2="236.0" y2="692.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="231.5" y="670.4" width="9" height="14.4" fill="#c00"/>
<text x="236.0" y="779.6" fill="#c00" text-anchor="middle" style="font-weight:bold">6</text>
<line x1="252.0" y1="658.4" x2="252.0" y2="692.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="247.5" y="665.6" width="9" height="19.2" fill="#188a3e"/>
<text x="252.0" y="779.6" fill="#188a3e" text-anchor="middle" style="font-weight:bold">7</text>
<line x1="268.0" y1="658.4" x2="268.0" y2="696.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="263.5" y="665.6" width="9" height="24.0" fill="#c00"/>
<text x="268.0" y="779.6" fill="#c00" text-anchor="middle" style="font-weight:bold">8</text>
<text x="108.0" y="775.6" fill="#b06000" text-anchor="middle" style="font-weight:bold">doji</text>
<text x="278.0" y="672.8" fill="#555" text-anchor="start" style="font-weight:bold">a 8-a candelă: nici TP, nici SL</text>
<text x="278.0" y="687.2" fill="#555" text-anchor="start" style="font-weight:bold">→ ieși la 50.70 = +0.25R</text>
<text x="24" y="816" fill="#555">Barele de după intrare sunt construite. Regulile: 13_strategia_3_byh.md:196-213.</text>
<svg viewBox="0 0 760 795" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif">
<text x="24" y="48" fill="#333" style="font-weight:bold">A — prima treime la țintă, a doua pe trailing stop</text>
<rect x="146.5" y="176.0" width="73.0" height="96.0" fill="#188a3e" fill-opacity="0.08" stroke="#188a3e" stroke-width="1"/>
<rect x="218.5" y="122.0" width="163.0" height="84.0" fill="#1a5fb4" fill-opacity="0.08" stroke="#1a5fb4" stroke-width="1"/>
<line x1="24" y1="190.0" x2="746" y2="190.0" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="2 3"/>
<text x="732" y="184.0" fill="#188a3e" text-anchor="end">ținta 1: 51.60 (= 1R)</text>
<line x1="24" y1="238.0" x2="746" y2="238.0" stroke="#555" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="732" y="232.0" fill="#555" text-anchor="end">intrarea: 50.40</text>
<line x1="24" y1="286.0" x2="746" y2="286.0" stroke="#c00" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="732" y="280.0" fill="#c00" text-anchor="end">stopul: 49.20</text>
<line x1="48.0" y1="56.0" x2="48.0" y2="126.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="43.5" y="66.0" width="9" height="48.0" fill="#c00"/>
<line x1="66.0" y1="104.0" x2="66.0" y2="174.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="61.5" y="114.0" width="9" height="48.0" fill="#c00"/>
<line x1="84.0" y1="152.0" x2="84.0" y2="226.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="79.5" y="162.0" width="9" height="52.0" fill="#c00"/>
<line x1="102.0" y1="204.0" x2="102.0" y2="280.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="97.5" y="214.0" width="9" height="54.0" fill="#c00"/>
<line x1="120.0" y1="250.0" x2="120.0" y2="284.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="115.5" y="268.0" width="9" height="2.0" fill="#c00"/>
<line x1="138.0" y1="252.0" x2="138.0" y2="276.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="133.5" y="258.0" width="9" height="12.0" fill="#188a3e"/>
<line x1="156.0" y1="232.0" x2="156.0" y2="264.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="151.5" y="238.0" width="9" height="20.0" fill="#188a3e"/>
<line x1="174.0" y1="208.0" x2="174.0" y2="250.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="169.5" y="218.0" width="9" height="20.0" fill="#188a3e"/>
<line x1="192.0" y1="196.0" x2="192.0" y2="230.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="187.5" y="206.0" width="9" height="12.0" fill="#188a3e"/>
<line x1="210.0" y1="184.0" x2="210.0" y2="218.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="205.5" y="194.0" width="9" height="12.0" fill="#188a3e"/>
<line x1="228.0" y1="180.0" x2="228.0" y2="198.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="223.5" y="184.0" width="9" height="10.0" fill="#188a3e"/>
<line x1="246.0" y1="162.0" x2="246.0" y2="176.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="241.5" y="166.0" width="9" height="8.0" fill="#188a3e"/>
<line x1="264.0" y1="156.0" x2="264.0" y2="172.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="259.5" y="160.0" width="9" height="6.0" fill="#188a3e"/>
<line x1="282.0" y1="158.0" x2="282.0" y2="174.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="277.5" y="160.0" width="9" height="10.0" fill="#c00"/>
<line x1="300.0" y1="154.0" x2="300.0" y2="172.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="295.5" y="158.0" width="9" height="12.0" fill="#188a3e"/>
<line x1="318.0" y1="152.0" x2="318.0" y2="164.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="313.5" y="154.0" width="9" height="4.0" fill="#188a3e"/>
<line x1="336.0" y1="152.0" x2="336.0" y2="160.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="331.5" y="154.0" width="9" height="2.0" fill="#c00"/>
<line x1="354.0" y1="130.0" x2="354.0" y2="150.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="349.5" y="136.0" width="9" height="10.0" fill="#188a3e"/>
<line x1="372.0" y1="134.0" x2="372.0" y2="166.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="367.5" y="136.0" width="9" height="26.0" fill="#c00"/>
<line x1="220.0" y1="118.0" x2="211.2" y2="178.1" stroke="#188a3e" stroke-width="1.8"/>
<polygon points="210.0,186.0 207.2,177.5 215.1,178.7" fill="#188a3e"/>
<text x="220.0" y="99.0" fill="#188a3e" text-anchor="middle" style="font-weight:bold">ținta 1 atinsă: vinzi prima treime</text>
<text x="220.0" y="113.0" fill="#188a3e" text-anchor="middle" style="font-weight:bold">ai luat exact cât riscai (1R)</text>
<line x1="376.0" y1="246.0" x2="253.1" y2="183.6" stroke="#b06000" stroke-width="1.8"/>
<polygon points="246.0,180.0 254.9,180.1 251.3,187.2" fill="#b06000"/>
<text x="376.0" y="260.0" fill="#b06000" text-anchor="middle" style="font-weight:bold">gap: low-ul de azi e peste high-ul de ieri</text>
<text x="376.0" y="274.0" fill="#b06000" text-anchor="middle" style="font-weight:bold">linia de trail urcă la 51.95</text>
<line x1="504.0" y1="120.0" x2="361.9" y2="144.6" stroke="#b06000" stroke-width="1.8"/>
<polygon points="354.0,146.0 361.2,140.7 362.6,148.6" fill="#b06000"/>
<text x="504.0" y="101.0" fill="#b06000" text-anchor="middle" style="font-weight:bold">încă un gap: linia urcă la 52.60</text>
<text x="504.0" y="115.0" fill="#b06000" text-anchor="middle" style="font-weight:bold">urcă doar, nu coboară niciodată</text>
<line x1="482.0" y1="288.0" x2="377.4" y2="171.9" stroke="#c00" stroke-width="1.8"/>
<polygon points="372.0,166.0 380.3,169.3 374.4,174.6" fill="#c00"/>
<text x="482.0" y="302.0" fill="#c00" text-anchor="middle" style="font-weight:bold">prima închidere sub linie: ieși</text>
<text x="482.0" y="316.0" fill="#c00" text-anchor="middle" style="font-weight:bold">cu a doua treime, la 52.30 (+1.58R)</text>
<polyline points="239.0,176.0 347.0,176.0 347.0,150.0 379.0,150.0" fill="none" stroke="#b06000" stroke-width="2"/>
<text x="386.0" y="154.0" fill="#b06000" style="font-weight:bold">linia de trailing stop</text>
<text x="150.0" y="346.0" fill="#188a3e" style="font-weight:bold">prima treime: de la intrare la ținta 1:1</text>
<text x="222.0" y="364.0" fill="#1a5fb4" style="font-weight:bold">a doua treime: merge pe trailing stop</text>
<text x="24" y="386.0" fill="#555">A treia treime o lași mai departe, cu stopul mutat la intrare (break-even).</text>
<line x1="24" y1="405" x2="746" y2="405" stroke="#ddd"/>
<text x="24" y="460" fill="#333" style="font-weight:bold">B — limita de 8 candele: nici ținta, nici stopul</text>
<rect x="164.5" y="602.0" width="145.0" height="96.0" fill="#555" fill-opacity="0.08" stroke="#555" stroke-width="1"/>
<line x1="24" y1="602.0" x2="746" y2="602.0" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="2 3"/>
<text x="732" y="596.0" fill="#188a3e" text-anchor="end">ținta 1: 51.60 — neatinsă</text>
<line x1="24" y1="650.0" x2="746" y2="650.0" stroke="#555" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="732" y="644.0" fill="#555" text-anchor="end">intrarea: 50.40</text>
<line x1="24" y1="698.0" x2="746" y2="698.0" stroke="#c00" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="732" y="692.0" fill="#c00" text-anchor="end">stopul: 49.20 — neatins</text>
<line x1="48.0" y1="468.0" x2="48.0" y2="538.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="43.5" y="478.0" width="9" height="48.0" fill="#c00"/>
<line x1="66.0" y1="516.0" x2="66.0" y2="586.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="61.5" y="526.0" width="9" height="48.0" fill="#c00"/>
<line x1="84.0" y1="564.0" x2="84.0" y2="638.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="79.5" y="574.0" width="9" height="52.0" fill="#c00"/>
<line x1="102.0" y1="616.0" x2="102.0" y2="692.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="97.5" y="626.0" width="9" height="54.0" fill="#c00"/>
<line x1="120.0" y1="662.0" x2="120.0" y2="696.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="115.5" y="680.0" width="9" height="2.0" fill="#c00"/>
<line x1="138.0" y1="664.0" x2="138.0" y2="688.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="133.5" y="670.0" width="9" height="12.0" fill="#188a3e"/>
<line x1="156.0" y1="644.0" x2="156.0" y2="676.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="151.5" y="650.0" width="9" height="20.0" fill="#188a3e"/>
<line x1="174.0" y1="636.0" x2="174.0" y2="656.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="169.5" y="642.0" width="9" height="8.0" fill="#188a3e"/>
<text x="174.0" y="763.0" fill="#188a3e" text-anchor="middle" style="font-weight:bold">1</text>
<line x1="192.0" y1="636.0" x2="192.0" y2="660.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="187.5" y="642.0" width="9" height="12.0" fill="#c00"/>
<text x="192.0" y="763.0" fill="#c00" text-anchor="middle" style="font-weight:bold">2</text>
<line x1="210.0" y1="624.0" x2="210.0" y2="660.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="205.5" y="630.0" width="9" height="24.0" fill="#188a3e"/>
<text x="210.0" y="763.0" fill="#188a3e" text-anchor="middle" style="font-weight:bold">3</text>
<line x1="228.0" y1="624.0" x2="228.0" y2="652.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="223.5" y="630.0" width="9" height="16.0" fill="#c00"/>
<text x="228.0" y="763.0" fill="#c00" text-anchor="middle" style="font-weight:bold">4</text>
<line x1="246.0" y1="616.0" x2="246.0" y2="652.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="241.5" y="622.0" width="9" height="24.0" fill="#188a3e"/>
<text x="246.0" y="763.0" fill="#188a3e" text-anchor="middle" style="font-weight:bold">5</text>
<line x1="264.0" y1="616.0" x2="264.0" y2="640.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="259.5" y="622.0" width="9" height="12.0" fill="#c00"/>
<text x="264.0" y="763.0" fill="#c00" text-anchor="middle" style="font-weight:bold">6</text>
<line x1="282.0" y1="612.0" x2="282.0" y2="640.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="277.5" y="618.0" width="9" height="16.0" fill="#188a3e"/>
<text x="282.0" y="763.0" fill="#188a3e" text-anchor="middle" style="font-weight:bold">7</text>
<line x1="300.0" y1="612.0" x2="300.0" y2="644.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="295.5" y="618.0" width="9" height="20.0" fill="#c00"/>
<text x="300.0" y="763.0" fill="#c00" text-anchor="middle" style="font-weight:bold">8</text>
<line x1="420.0" y1="708.0" x2="307.0" y2="645.9" stroke="#555" stroke-width="1.8"/>
<polygon points="300.0,642.0 308.9,642.4 305.1,649.4" fill="#555"/>
<text x="420.0" y="722.0" fill="#555" text-anchor="middle" style="font-weight:bold">a 8-a candelă: ieși oricum, la close 50.70 (+0.25R)</text>
<text x="420.0" y="736.0" fill="#555" text-anchor="middle" style="font-weight:bold">banii blocați aici lipsesc din alt trade</text>
<text x="168.0" y="594.0" fill="#555" style="font-weight:bold">8 candele în care nu se întâmplă nimic</text>
</svg>

Before

Width:  |  Height:  |  Size: 9.5 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -2,16 +2,19 @@
"""LABU — Buy Doji la pivotul monthly (Nivel 2.5).
Citește `gen/strategii/buy_doji_labu.spec.txt` și scrie
`gen/strategii/buy_doji_labu.svg`: 49 de candele daily, downtrend → triple
bottom → doji la pivotul monthly 86.00 → confirmare (close 89.50 peste
high-ul dojiului) → bull reversal → higher high, cu SL 81.45 (−9 %) și
`gen/strategii/buy_doji_labu.svg`: 57 de candele daily, downtrend → triple
bottom (trei minime aproape egale, dar pivotul lunar atins doar de două ori)
→ doji la pivotul monthly 86.00 → confirmare (close 89.50 peste high-ul
dojiului) → bull reversal → higher high, cu SL 81.45 (−9 %) și
TP 116.35 (+30 %).
Toate cifrele din desen vin din specificație: pivot 86.00, intrare 89.50,
SL 81.45, TP 116.35, high/low-ul dojiului (86.30 / 84.20) și low-urile
triple bottom-ului (82.40 / 81.45 / 81.45). Procentele 9 % și 30 % sunt ale
cursului (reale); nivelurile de preț sunt construite de sumarizator —
legenda o spune explicit.
legenda o spune explicit. Capitolul spune și „triple bottom", și „doji la al
doilea test al pivotului": desenul le satisface pe amândouă — trei minime în
zona 81-83, dintre care doar primele două vin după o urcare peste 86.00.
Rulare: python3 gen/strategii/buy_doji_labu.py
"""
@@ -20,7 +23,7 @@ import sys
from pathlib import Path
sys.path.insert(0, "/workspace/atm-curs-dl")
from svg_candles import Chart, Level, MA, Mark, from_closes # noqa: E402
from svg_candles import Arrow, Chart, Level, MA, Mark, Zone, from_closes # noqa: E402
OUT = Path(__file__).with_suffix(".svg")
@@ -29,50 +32,88 @@ PIVOT = 86.00 # pivot monthly (construit)
ENTRY = 89.50 # intrare = close-ul confirmării (construit)
SL = 81.45 # SL = −9 % față de intrare (construit; procentul e real)
TP = 116.35 # TP = +30 % față de intrare (construit; procentul e real)
DOJI_H, DOJI_L = 86.30, 84.20
DOJI_H, DOJI_L = 86.80, 84.90
I_DOJI, I_CONF = 33, 34
B1, B2, B3 = 16, 25, 31 # cele trei picioare ale triplului fund
# (B1, B2 = testele pivotului; B3 rămâne sub el)
I_RETEST = 37 # revenirea care testează intrarea și ține
FLAG = (42, 45) # consolidarea scurtă (bull flag)
I_TP = 55 # bara pe care prețul atinge 116.35
# --- seria de close-uri din specificație -----------------------------------
# --- seria de close-uri -----------------------------------------------------
# Textul capitolului e sursa: „triple bottom" (trei minime aproape egale) și
# „doji la al doilea test al pivotului". Nu se bat cap în cap: sunt trei
# minime de preț, dar doar două dintre ele vin după o urcare peste 86.00 —
# al treilea e o alunecare care nu mai atinge pivotul de sus în jos.
# Restul: „+30 % într-o lună" (21 de bare daily de la confirmare) și etapele
# „retest → bull flag → breakout". Prețurile sunt construite în jurul
# nivelurilor deja folosite în capitol (86.00 / 89.50 / 81.45 / 97.55 / 116.35).
closes = [
# downtrend 0-14
108.0, 106.5, 105.0, 103.0, 101.5, 100.0, 98.0, 96.5, 95.0, 93.5,
92.5, 91.0, 89.5, 87.5, 85.5,
# triple bottom 15 / 23 / 31
82.80, 84.5, 86.5, 88.0, 88.50,
87.0, 85.0, 83.0, 81.50,
83.5, 85.5, 87.0, 87.80, 87.0, 85.0,
83.0, 81.60, 85.00,
84.90, # 33 = doji (o 85.00, c 84.90, h 86.30, l 84.20)
89.50, # 34 = confirmare, close > 86.30 => intrare
# bull reversal / trend up 35-48
91.0, 93.0, 92.0, 95.0, 97.0, 96.0, 99.0, 102.0, 101.0, 105.0, 108.0,
112.0, 116.35, 118.0,
# 15-16: primul test al pivotului (bottom 1, low 82.40)
83.5, 82.80,
# 17-20: revenire peste pivot (88.90 high) — de aici vine al doilea test
84.5, 86.5, 88.0, 88.5,
# 21-24: coboară înapoi prin pivot: al doilea test al lui 86.00
87.0, 85.5, 84.0, 82.8,
# 25: bottom 2 (low 82.00), la capătul celui de-al doilea test
82.30,
# 26-29: un pull-up scurt care NU mai ajunge la pivot (high max 85.80)
83.5, 84.8, 85.4, 84.2,
# 30: alunecă iar, fără să fi atins pivotul între timp
83.0,
# 31: bottom 3 (low 81.45 = stopul) — al treilea minim, nu un test nou
81.90,
# 32: bara de întoarcere, închide peste pivot
86.10,
# 33 = doji: o 86.10, c 86.00, h 86.80, l 84.90 — corpul chiar pe pivot
86.00,
# 34 = confirmare: close 89.50 peste high-ul dojiului => intrare
89.50,
# 35-36: pornirea
92.0, 94.0,
# 37: retest — cade la 89.60, pe intrare, și ține
91.0,
# 38-41: reia urcarea și trece de ținta 1:1 (97.55)
93.5, 95.5, 98.5, 100.0,
# 42-45: bull flag — patru candele care se odihnesc
99.2, 99.8, 98.9, 99.5,
# 46-54: breakout și continuare
102.5, 104.0, 103.0, 106.0, 108.5, 107.5, 110.5, 112.5, 114.0,
# 55: +30 % față de intrare; 56: încă un higher high
116.35, 117.5,
]
assert len(closes) == 49, f"seria are {len(closes)} bare, spec cere 49"
assert len(closes) == 57, f"seria are {len(closes)} bare, aștept 57"
# wick-uri: (up, down). Restul (0.4, 0.5); ajustate ca low-urile/high-urile
# cerute de asserts să iasă exact (bar 15/23/31 = triple bottom; bar 16/24
# nu au voie să coboare sub piciorul din stânga; bar 33 = doji).
# wick-uri: (sus, jos) față de corp. Restul (0.4, 0.5); ajustate ca low-urile
# cerute de assert-uri să iasă exact.
wicks = [(0.4, 0.5)] * len(closes)
wicks[15] = (0.4, 0.40) # low 82.40
wicks[16] = (0.4, 0.20) # low 82.60 > 82.40 (piciorul 1 rămâne minim local)
wicks[23] = (0.4, 0.05) # low 81.45
wicks[24] = (0.4, 0.00) # low 81.50 > 81.45 (piciorul 2 rămâne minim local)
wicks[31] = (0.4, 0.15) # low 81.45
wicks[32] = (0.4, 0.10) # low 81.50 (nu sub 81.45)
wicks[33] = (1.30, 0.70) # doji: high 86.30, low 84.20
wicks[B1] = (0.4, 0.40) # bottom 1: low 82.40
wicks[17] = (0.4, 0.00) # low 82.80 > 82.40 (piciorul 1 rămâne minim local)
wicks[B2] = (0.4, 0.30) # bottom 2: low 82.00
wicks[26] = (0.4, 0.00) # low 82.30 > 82.00 (piciorul 2 rămâne minim local)
wicks[B3] = (0.4, 0.45) # bottom 3: low 81.45 = stopul
wicks[32] = (0.4, 0.00) # low 81.90 (nu coboară sub 81.45)
wicks[I_DOJI] = (0.70, 1.10) # doji: high 86.80, low 84.90
wicks[35] = (0.4, 0.00) # prima bară după intrare nu se mai duce sub 89.50
wicks[I_RETEST] = (0.4, 1.40) # retest: low 89.60, peste intrarea de 89.50
# volume construite: vânzare peste medie la triple bottom și la confirmare.
# Nu sunt numere din curs (nu sunt etichetate), doar panoul de volum cerut.
# volume construite: vânzare peste medie la cele două picioare, volum mare pe
# confirmare, volum mic pe flag. Nu sunt numere din curs.
vols = [
55, 52, 48, 50, 45, 47, 44, 46, 42, 44,
40, 42, 38, 41, 58,
62, 50, 46, 44, 43,
45, 44, 47, 66, 55,
50, 47, 45, 44, 42,
43, 45, 60, 72, 84,
78, 70, 64, 60, 58,
54, 52, 56, 60, 66,
74, 82, 90, 98,
62, 68, 50, 46, 44,
43, 45, 44, 47, 46,
45, 47, 52, 45, 44,
48, 70, 62, 58, 88,
76, 70, 58, 62, 66,
72, 70, 44, 40, 38,
42, 74, 70, 64, 68,
72, 66, 74, 78, 82,
90, 96,
]
assert len(vols) == len(closes), f"volume {len(vols)} != bare {len(closes)}"
@@ -80,80 +121,134 @@ cds = from_closes(closes, wicks=wicks, vols=vols, start=110.0)
assert abs(cds[0].o - 110.0) < 1e-9 and cds[0].c < cds[0].o, "prima bară nu e roșie"
# nota explicativă a dojiului (bloc stânga-jos, nu se suprapune cu candelele)
cds[33].note = ("bara 33 = doji: o 85.00, c 84.90, h 86.30, l 84.20 — "
"corp mic exact pe pivotul monthly 86.00 (indecizie la suport)")
cds[I_DOJI].note = ("doji = corp mic (o 86.10, c 86.00): cumpărătorii și vânzătorii sunt la "
"egalitate, exact pe pivotul lunar 86.00")
TP1 = round(ENTRY + (ENTRY - SL), 2) # ținta 1:1: cât ai riscat
assert abs(TP1 - 97.55) < 1e-9, f"ținta 1:1 = {TP1}, capitolul spune 97.55"
R = (TP - ENTRY) / (ENTRY - SL)
assert 3.2 <= R <= 3.4, f"{R:.2f}R, capitolul spune „cam 3,3R”"
I_TP1 = next(i for i in range(35, len(cds)) if cds[i].h >= TP1) # prima bară peste 1:1
cds[I_TP1].note = (f"ținta 1:1 ({TP1:.2f}) e atinsă pe bara {I_TP1}: acolo vinzi o treime, "
"restul merge mai departe — de asta nu vinzi tot la 1:1")
# --- assert-urile din specificație (toate, ca assert reale) ----------------
# 1. pivot 86.00 e straddled de doji
assert cds[33].l <= PIVOT <= cds[33].h, "doji-ul nu straddlează 86.00"
assert cds[I_DOJI].l <= PIVOT <= cds[I_DOJI].h, "doji-ul nu straddlează 86.00"
# corpul dojiului stă pe pivot, nu la un dolar sub el (eticheta spune „exact pe")
assert min(cds[I_DOJI].o, cds[I_DOJI].c) <= PIVOT <= max(cds[I_DOJI].o, cds[I_DOJI].c) + 0.15, \
f"corpul dojiului ({cds[I_DOJI].o}/{cds[I_DOJI].c}) nu e pe pivotul {PIVOT}"
# 2. confirmarea: close[34] == 89.50 == intrare și > high[33]
assert abs(cds[34].c - ENTRY) < 1e-9, f"close[34]={cds[34].c} != intrare 89.50"
assert cds[34].c > cds[33].h, "confirmarea nu închide peste high-ul dojiului"
# 2. confirmarea: close[34] == 89.50 == intrare și > high-ul dojiului
assert abs(cds[I_CONF].c - ENTRY) < 1e-9, f"close[{I_CONF}]={cds[I_CONF].c} != intrare 89.50"
assert cds[I_CONF].c > cds[I_DOJI].h, "confirmarea nu închide peste high-ul dojiului"
# 3. SL = min(low[30:35]) (regula: extrema ultimelor 4 candele de la confirmare)
min_30_35 = min(c.l for c in cds[30:35])
assert abs(min_30_35 - SL) < 1e-9, f"min low[30:35]={min_30_35} != SL {SL}"
# 3. SL = extrema ultimelor 4 candele de la confirmare
min_win = min(c.l for c in cds[I_CONF - 4:I_CONF + 1])
assert abs(min_win - SL) < 1e-9, f"min low[{I_CONF - 4}:{I_CONF + 1}]={min_win} != SL {SL}"
# 4./5. procentele REALE ale cursului
assert round((ENTRY - SL) / ENTRY * 100, 1) == 9.0, "stopul nu iese −9 %"
assert round((TP - ENTRY) / ENTRY * 100, 1) == 30.0, "TP nu iese +30 %"
# 6. triple bottom: exact trei minime locale sub 86.00, în zona 81-83,
# al doilea și al treilea fără low nou semnificativ față de primul
# 6. triple bottom, dar pivotul atins de două ori — aserțiunea care ține
# laolaltă cele două formulări din capitol („trei minime aproape egale" și
# „doji la al doilea test al pivotului 86.00").
lows = [c.l for c in cds]
bottom_idx = [i for i in range(1, len(cds) - 1)
if lows[i] < lows[i - 1] and lows[i] < lows[i + 1]
and lows[i] < PIVOT and 81.0 <= lows[i] <= 83.0]
assert bottom_idx == [15, 23, 31], f"triple bottom la {bottom_idx}, nu [15, 23, 31]"
b1, b2, b3 = lows[15], lows[23], lows[31]
tol = 0.02 * b1 # „semnificativ" = > 2 % sub primul low
assert b2 >= b1 - tol and b3 >= b1 - tol, \
f"al doilea/treilea picior coboară semnificativ sub primul: {b1}/{b2}/{b3}"
assert abs(b1 - 82.40) < 1e-9 and abs(b2 - SL) < 1e-9 and abs(b3 - SL) < 1e-9, \
f"low-urile triple bottom: {b1}/{b2}/{b3}"
assert bottom_idx == [B1, B2, B3], f"minimele fundului: {bottom_idx}, aștept [{B1}, {B2}, {B3}]"
assert len(bottom_idx) == 3, f"{len(bottom_idx)} minime locale în zona fundului, aștept 3"
b1, b2, b3 = (lows[i] for i in bottom_idx)
# „aproape egale": nici unul nu e cu mai mult de 2 % sub primul
assert max(b1, b2, b3) - min(b1, b2, b3) <= 0.02 * b1, \
f"minimele nu sunt aproape egale: {b1}/{b2}/{b3}"
assert abs(b1 - 82.40) < 1e-9 and abs(b2 - 82.00) < 1e-9 and abs(b3 - SL) < 1e-9, \
f"low-urile triplului fund: {b1}/{b2}/{b3}"
# un minim e „atingere a pivotului" doar dacă prețul a fost peste 86.00 după
# minimul dinainte: coboară prin pivot ca să ajungă acolo. Al treilea nu e.
tests = []
for k, i in enumerate(bottom_idx):
prev = bottom_idx[k - 1] + 1 if k else 0
if max(c.h for c in cds[prev:i]) >= PIVOT:
tests.append(i)
assert tests == [B1, B2], f"atingeri ale pivotului la {tests}, aștept [{B1}, {B2}]"
assert len(tests) == 2, f"{len(tests)} atingeri ale pivotului 86.00, aștept 2"
# între primele două picioare prețul urcă clar peste pivot (al doilea test)
assert max(c.h for c in cds[B1 + 1:B2]) > PIVOT + 1.5, "nu e revenire peste pivot înainte de B2"
# între al doilea și al treilea NU mai ajunge la pivot: al treilea nu e test
assert max(c.h for c in cds[B2 + 1:B3]) < PIVOT, \
f"pull-up-ul dintre B2 și B3 atinge pivotul ({max(c.h for c in cds[B2 + 1:B3]):.2f})"
# 7. TP atins: există i > 34 cu high[i] >= 116.35
assert any(c.h >= TP for c in cds[35:]), "TP 116.35 nu e atins după intrare"
# 7. TP atins la ~o lună de bursă de la confirmare (capitolul: „într-o lună")
assert abs(cds[I_TP].c - TP) < 1e-9, f"close[{I_TP}]={cds[I_TP].c} != {TP}"
assert max(c.h for c in cds[I_CONF + 1:I_TP]) < TP, "TP atins mai devreme de bara 55"
bars_to_tp = I_TP - I_CONF
assert 20 <= bars_to_tp <= 22, f"{bars_to_tp} bare până la +30 %, aștept ~21 (o lună)"
# 8. doji: corp <= 10 % din amplitudine
assert abs(cds[33].o - cds[33].c) <= 0.10 * (cds[33].h - cds[33].l), "bara 33 nu e doji"
assert abs(cds[33].h - DOJI_H) < 1e-9 and abs(cds[33].l - DOJI_L) < 1e-9, \
"doji h/l nu ies 86.30/84.20"
assert abs(cds[I_DOJI].o - cds[I_DOJI].c) <= 0.10 * (cds[I_DOJI].h - cds[I_DOJI].l), \
"bara doji nu e doji"
assert abs(cds[I_DOJI].h - DOJI_H) < 1e-9 and abs(cds[I_DOJI].l - DOJI_L) < 1e-9, \
"doji h/l nu ies 86.80/84.90"
# în plus: confirmarea vine cu volum peste medie (cerut de spec)
# 9. retestul: revine până pe intrare și ține (nu o rupe)
assert ENTRY <= cds[I_RETEST].l <= ENTRY + 0.5, \
f"retestul nu atinge intrarea: low {cds[I_RETEST].l}"
assert min(c.l for c in cds[I_CONF + 1:]) >= ENTRY, "prețul cade sub intrare după confirmare"
# 10. bull flag: 4 candele strânse, sub high-ul barei dinainte, urmate de breakout
f0, f1 = FLAG
flag_h = max(c.h for c in cds[f0:f1 + 1])
flag_l = min(c.l for c in cds[f0:f1 + 1])
assert flag_h - flag_l <= 2.5, f"flag prea larg: {flag_h - flag_l:.2f}"
assert flag_h <= cds[f0 - 1].h, "flagul face high nou — nu mai e consolidare"
assert cds[f1 + 1].c > flag_h, "nu există breakout după flag"
# în plus: confirmarea vine cu volum peste medie, flagul cu volum sub medie
mean_vol = sum(vols) / len(vols)
assert vols[34] > mean_vol, f"volumul confirmării {vols[34]} <= media {mean_vol:.0f}"
assert vols[I_CONF] > mean_vol, f"volumul confirmării {vols[I_CONF]} <= media {mean_vol:.0f}"
assert max(vols[f0:f1 + 1]) < mean_vol, "flagul nu vine pe volum scăzut"
entry = cds[34].c
w = 820 # lățime mărită: 49 bare × gap 15 + etichetele din dreapta
# (spec sugera 760, dar ultima candelă ajunge la x=764)
w = 990 # 57 bare × gap 15 + loc pentru etichetele din dreapta
ch = Chart(
candles=cds,
levels=[Level(PIVOT, "pivot monthly 86.00 (construit)", "#777",
dash="4 3", label_at="left"),
Level(SL, "SL 81.45 (construit) = −9 % (procent real)", "#c00",
label_at="left"),
Level(ENTRY, "intrare 89.50 (construit)", "#188a3e"),
Level(TP, "TP 116.35 (construit) = +30 % (procent real)", "#1a5fb4")],
marks=[Mark(15, f"bottom 1 {lows[15]:.2f}", "#c00", "below"),
Mark(23, f"bottom 2 {lows[23]:.2f}", "#c00", "below"),
Mark(31, f"bottom 3 {lows[31]:.2f}", "#c00", "below"),
Mark(33, "doji", "#b06000", "above"),
Mark(34, "confirmare (intrare)", "#188a3e", "above", dy=-14),
Mark(48, "higher high — TP atins", "#188a3e", "above")],
levels=[Level(PIVOT, "pivot lunar 86.00", "#777", dash="4 3", label_at="left"),
Level(SL, "stop 81.45 = 9 % sub intrare (procent real)", "#c00", label_at="left"),
Level(ENTRY, "intrare 89.50", "#188a3e"),
Level(TP1, f"ținta 1:1 {TP1:.2f}", "#777", dash="2 3", label_at="left"),
Level(TP, "116.35 = +30 % față de intrare (procent real)", "#1a5fb4", label_at="left")],
zones=[Zone(0, B3, "1. setup: scădere lungă, apoi trei minime aproape egale — pivotul 86.00 atins de două ori", "#777"),
Zone(I_DOJI, I_CONF, "2. doji + confirmare", "#b06000"),
# p_top sub 116.35: altfel eticheta zonei 3 se așază peste linia țintei
Zone(I_CONF + 1, I_TP - 1, "3. trendul pornește", "#188a3e", p_top=113.0),
Zone(I_TP, len(cds) - 1, "4. ținta", "#1a5fb4")],
arrows=[Arrow(I_CONF, "aici intri, la close 89.50:\nabia acum știi că au câștigat cumpărătorii",
ENTRY, where="above", color="#188a3e", dx=-150),
Arrow(B3, "al treilea minim: 81.45,\nfără o nouă atingere a pivotului\naici pui stopul, sub minime",
SL, where="below", color="#c00", dx=-40),
Arrow(I_RETEST, "retest: cade înapoi pe intrare\nși ține — trendul e sănătos",
cds[I_RETEST].l, where="below", color="#188a3e", dx=110, dy=56),
Arrow(FLAG[0] + 1, "aici se odihnește, nu se strică:\nbull flag, pe volum mic",
cds[FLAG[0] + 1].h, where="above", color="#188a3e", dx=-20),
Arrow(I_TP, f"a ajuns la 116.35: +30 % în 21 de zile de bursă,\ncam {R:.1f}R din cât ai riscat".replace("3.3R", "3,3R"),
TP, where="left", color="#1a5fb4", dx=-30, dy=-40)],
marks=[Mark(B1, f"test 1 · {lows[B1]:.2f}", "#c00", "below"),
Mark(B2, f"test 2 · {lows[B2]:.2f}", "#c00", "below")],
mas=[MA(20, "#b06000", dash="4 3", text="SMA-20")],
scale=8.0, gap=15, body_w=9, left=44, width=w, vol_h=70,
vol_label="volum", title="LABU — daily",
caption=("Procentele (stop 9 %, +30 %) sunt ale cursului; nivelurile de "
"preț sunt construite de sumarizator (18_2025-09-23.md:713)."),
caption=("Procentele (stop 9 %, +30 %) sunt ale cursului; "
"nivelurile de preț sunt puse de sumarizator."),
)
svg = ch.render()
assert "\n\n" not in svg and "<svg" in svg, "SVG invalid (linie goală?)"
# --- citirea SVG-ului: etichete în panză, fără suprapuneri -----------------
TEXT = re.compile(r'<text x="([-\d.]+)" y="([-\d.]+)"([^>]*)>(.*?)</text>', re.S)
H = float(re.search(r'viewBox="0 0 (\d+) ([\d.]+)"', svg).group(2))
W_SVG, H = (float(x) for x in re.search(r'viewBox="0 0 (\d+) ([\d.]+)"', svg).groups())
labels = []
for m in TEXT.finditer(svg):
x, y, attrs, s = float(m.group(1)), float(m.group(2)), m.group(3), m.group(4)
@@ -165,7 +260,7 @@ for m in TEXT.finditer(svg):
labels.append((left, left + wpx, y, s))
for left, right, y, s in labels:
assert left >= -2 and right <= w + 2, f"text iese din panză: {s!r} [{left:.0f},{right:.0f}]"
assert left >= -2 and right <= W_SVG + 2, f"text iese din panză: {s!r} [{left:.0f},{right:.0f}]"
assert 0 <= y <= H, f"text în afara înălțimii: {s!r} (y={y:.0f})"
for i in range(len(labels)):
@@ -177,14 +272,16 @@ for i in range(len(labels)):
# candelele sunt o serie continuă, lipită
xs = [ch._cx(i) for i in range(len(cds))]
assert xs[-1] + ch.body_w / 2 < w, f"ultima candelă iese din panză (x={xs[-1]})"
assert ".md:" not in svg and "Surse" not in svg, "trimiteri la surse în SVG"
assert xs[-1] + ch.body_w / 2 < W_SVG, f"ultima candelă iese din panză (x={xs[-1]})"
assert all(xs[i + 1] - xs[i] == ch.gap for i in range(len(xs) - 1)), "serie cu goluri"
for a, b in zip(cds, cds[1:]):
assert abs(a.c - b.o) < 1e-9, "open != close-ul barei anterioare"
print(f"LABU: {len(cds)} bare, doji {cds[33].l:.2f}-{cds[33].h:.2f} peste pivot "
f"{PIVOT:.2f}, intrare {entry:.2f}, SL {SL:.2f} (−9 %), TP {TP:.2f} (+30 %)")
print(f"triple bottom: {b1:.2f} / {b2:.2f} / {b3:.2f} "
print(f"triple bottom: {b1:.2f} / {b2:.2f} / {b3:.2f}; pivotul 86.00 atins de "
f"{len(tests)} ori (barele {tests}); +30 % după {bars_to_tp} bare "
f"volum confirmare {vols[34]} > medie {mean_vol:.0f}")
print(f"scris {OUT} ({w}x{H:.0f}); {len(labels)} etichete verificate, fără suprapuneri")
print(f"scris {OUT} ({W_SVG:.0f}x{H:.0f}); {len(labels)} etichete verificate, fără suprapuneri")
OUT.write_text(svg, encoding="utf-8")

View File

@@ -4,8 +4,9 @@ TITLU: LABU — daily, Buy Doji la pivotul monthly (Nivel 2.5)
MARCAJ .md: <!-- DIAGRAMA: labu --> (Nivel 2, §2.5 Exemplul complet)
CE ARATĂ
Exemplul complet din material: downtrend → consolidare → triple bottom →
doji la pivotul monthly 86.00 → candela verde care închide peste high-ul
Exemplul complet din material: downtrend → consolidare → triple bottom (trei
minime aproape egale, dar pivotul monthly atins doar de două ori — „al doilea
test") → doji la pivotul monthly 86.00 → candela verde care închide peste high-ul
dojiului (intrare 89.50) → bull reversal pe candela mare → retest → bull
flag → breakout → higher high, higher low. SL 81.45 (−9 %), TP 116.35
(+30 %), atins într-o lună.
@@ -17,12 +18,38 @@ CE E REAL ȘI CE E CONSTRUIT (obligatoriu în legendă)
higher high/higher low), `18_2025-09-23.md:716-719`; „al doilea test al
pivotului monthly, fără low nou" și „corp mic exact pe pivotul monthly:
indecizie la suport", `18_2025-09-23.md:710-712`.
- REZOLVAT (19.09.2026): transcrierea și capitolul spun și „triple bottom"
(`:716-719`), și „al doilea test al pivotului monthly" (`:710-712`). Nu se
contrazic: sunt trei minime de PREȚ, dar nivelul 86.00 e atins doar de două
ori. Versiunea dinainte desena doar două minime și contrazicea „triple
bottom"; seria a fost reconstruită cu TREI minime aproape egale (82.40 /
82.00 / 81.45), dintre care doar primele două vin după o urcare peste 86.00.
Între minimul 2 și minimul 3 prețul se ridică doar până la 85.80 — sub
pivot, deci al treilea minim nu e un test nou. Generatorul asertează
explicit: 3 minime locale în zona 81-83 și 2 atingeri ale lui 86.00.
- CONSTRUITE de sumarizator (nu prețuri de curs): pivot 86.00, intrare
89.50, SL 81.45, TP 116.35 — marcate ca „nivelurile sunt ale mele"
(`18_2025-09-23.md:713`). Legenda diagramei trebuie să spună exact asta.
- Materialul nu dă niciun exemplu numeric complet de la intrare la ieșire
(`13_strategia_3_byh.md:298-308`; `byh.md:256-280`).
ADNOTĂRI (patru zone numerotate, ca subsecțiunile capitolului)
- Zona 1 (barele 0-31): „1. setup: scădere lungă, apoi trei minime aproape
egale — pivotul 86.00 atins de două ori"; Zona 2 (33-34): „2. doji + confirmare"; Zona 3 (35-54):
„3. trendul pornește"; Zona 4 (55-56): „4. ținta".
- Marcaje sub minimele 1 și 2 („test 1 · 82.40", „test 2 · 82.00") — doar
ele sunt atingeri ale pivotului; al treilea minim e numit de săgeata stopului.
- Săgeți: retestul („retest: cade înapoi pe intrare și ține — trendul e
sănătos"), bull flag-ul („aici se odihnește, nu se strică: bull flag, pe
volum mic"), intrarea („aici intri, la close 89.50: abia acum știi că au
câștigat cumpărătorii"), stopul, pe al treilea minim („al treilea minim:
81.45, fără o nouă atingere a pivotului, aici pui stopul, sub minime"), rezultatul („a ajuns la 116.35: +30 % într-o
lună, cam 3,3R din cât ai riscat").
- Linie punctată pentru ținta 1:1 (97.55), cu nota de dedesubt: acolo vinzi
o treime, restul merge mai departe.
- Fără trimiteri fișier:linie în SVG; legenda „procentele sunt ale cursului,
prețurile sunt puse de sumarizator" rămâne.
NIVELURILE ȘI ETICHETELE (cu trimitere)
- „pivot monthly 86.00" (`18_2025-09-23.md:615`)
- „intrare 89.50" (`18_2025-09-23.md:619`)
@@ -30,22 +57,37 @@ NIVELURILE ȘI ETICHETELE (cu trimitere)
- „TP +30 % = 116.35" (`18_2025-09-23.md:620-621`)
Etichete marcate „(construit)" sau „(procent real)" în legendă.
STRUCTURA SERIEI (49 candele daily, open = close-ul precedentului)
Sugestie de close-uri:
Etapa downtrend + triple bottom (0-33):
STRUCTURA SERIEI (57 candele daily, open = close-ul precedentului)
Seria e reconstruită după textul capitolului (19.09.2026): triple bottom cu
DOUĂ atingeri ale pivotului („al doilea test"), 21 de bare de la confirmare la +30 % („într-o
lună"), retest al intrării la bara 37 și bull flag la barele 42-45. Corpul
dojiului stă pe pivot (o 86.10, c 86.00, h 86.80, l 84.90), nu cu un dolar
sub el. Nivelurile din capitol rămân: 86.00 / 89.50 / 81.45 / 97.55 / 116.35.
Close-uri:
[108.0, 106.5, 105.0, 103.0, 101.5, 100.0, 98.0, 96.5, 95.0, 93.5,
92.5, 91.0, 89.5, 87.5, 85.5, 82.80, 84.5, 86.5, 88.0, 88.50,
87.0, 85.0, 83.0, 81.50, 83.5, 85.5, 87.0, 87.80, 87.0, 85.0,
83.0, 81.60, 85.00,
84.90, # 33 = doji (o 85.00, c 84.90, h 86.30, l 84.20); straddlează 86.00
89.50, # 34 = confirmare, close > 86.30 => intrare
91.0, 93.0, 92.0, 95.0, 97.0, 96.0, 99.0, 102.0, 101.0, 105.0, 108.0,
112.0, 116.35, 118.0]
Mecioni: barele 15, 23, 31 au low-urile triple bottom-ului — bara 15 low
82.40, bara 23 low 81.45, bara 31 low 81.45; bara 32 (revenirea) wd=0.10
(low 81.50, nu sub 81.45); bara 33 (doji) high 86.30, low 84.20; restul
(0.4, 0.5). Ajustează wick-urile ca low-urile/high-urile cerute la asserts
să iasă exact (în special min(low[30:35]) == 81.45).
92.5, 91.0, 89.5, 87.5, 85.5,
83.5, 82.80, # 16 = primul test (low 82.40)
84.5, 86.5, 88.0, 88.5, # 17-20 = urcare peste pivot (high 88.90)
87.0, 85.5, 84.0, 82.8, # 21-24 = coborâre prin pivot = testul 2
82.30, # 25 = minimul 2 (low 82.00)
83.5, 84.8, 85.4, 84.2, # 26-29 = pull-up sub pivot (high max 85.80)
83.0, # 30 = alunecă iar, fără test nou
81.90, # 31 = minimul 3 (low 81.45 = stopul)
86.10, # 32 = bara de întoarcere, peste pivot
86.00, # 33 = doji (o 86.10, h 86.80, l 84.90)
89.50, # 34 = confirmare => intrare
92.0, 94.0,
91.0, # 37 = retest (low 89.60, peste intrare)
93.5, 95.5, 98.5, 100.0, # 40 = prima bară peste ținta 1:1
99.2, 99.8, 98.9, 99.5, # 42-45 = bull flag, volum mic
102.5, 104.0, 103.0, 106.0, 108.5, 107.5, 110.5, 112.5, 114.0,
116.35, 117.5] # 55 = +30 %, la 21 de bare de confirmare
Wick-uri: implicit (0.4, 0.5); bara 16 (0.4, 0.40) => low 82.40; bara 17
(0.4, 0.00) ca primul picior să rămână minim local; bara 25 (0.4, 0.30) =>
low 82.00; bara 26 (0.4, 0.00) ca al doilea picior să rămână minim local;
bara 31 (0.4, 0.45) => low 81.45; bara 32 (0.4, 0.00) ca să nu coboare sub stop; bara 33
(0.70, 1.10) = doji; bara 35 (0.4, 0.00) și bara 37 (0.4, 1.40) => retestul
atinge 89.60 și ține.
CE VERIFICĂ GENERATORUL CU assert
1. pivot 86.00 e straddled de doji: low[33] <= 86.00 <= high[33]
@@ -54,13 +96,22 @@ CE VERIFICĂ GENERATORUL CU assert
confirmare, regula din `13_strategia_3_byh.md:192-193`)
4. round((entry - sl) / entry * 100, 1) == 9.0 (procentul REAL al cursului)
5. round((tp - entry) / entry * 100, 1) == 30.0 (procentul REAL al cursului)
6. triple bottom: există trei minime locale succesive sub 86.00, în zona
81-83, al doilea și al treilea fără low nou semnificativ față de primul
7. există i>34 cu high[i] >= 116.35
6. triple bottom cu două teste: exact TREI minime locale sub 86.00, în zona
81-83 (barele 16, 25 și 31), diferența dintre ele <= 2 % („aproape
egale"); dintre ele, exact DOUĂ sunt atingeri ale pivotului 86.00 —
minimele precedate de un high >= 86.00 (barele 16 și 25). Între 16 și 25
prețul urcă peste 86.00 + 1.5; între 25 și 31 maximul rămâne sub 86.00,
deci al treilea minim nu e un test nou.
7. close[55] == 116.35, nimic peste 116.35 înainte, și 20 <= 55-34 <= 22
(„într-o lună")
9. retestul (bara 37) atinge 89.50-90.00 și nicio bară de după confirmare nu
închide/coboară sub intrare
10. bull flag (42-45): amplitudine <= 2.5, fără high nou față de bara 41,
breakout pe bara 46, volum sub medie
8. doji: abs(o-c) <= 0.10*(h-l)
STIL: gap=15, body_w=9, left=44, width=760, vol_h=70 (volumul confirmă:
STIL: gap=15, body_w=9, left=44, width=990, vol_h=70 (volumul confirmă:
„cel mai mare volum din serie" e în varianta MICI, nu obligatoriu aici — dar
confirmarea are volum peste medie). scale astfel încât 86.00 → 116.35 să
încapă; linie punctată pentru pivotul 86.00. Legendă obligatorie:
„Procentele (stop 9 %, +30 %) sunt ale cursului; nivelurile de preț sunt
construite de sumarizator (18_2025-09-23.md:713)." Fără linie goală în SVG.
puse de sumarizator." (fără trimitere fișier:linie în SVG) Fără linie goală în SVG.

View File

@@ -1,170 +1,222 @@
<svg viewBox="0 0 820 507" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif">
<text x="24" y="48" fill="#333" style="font-weight:bold">LABU — daily</text>
<line x1="24" y1="315.2" x2="806" y2="315.2" stroke="#777" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30" y="309.2" fill="#777">pivot monthly 86.00 (construit)</text>
<line x1="24" y1="351.6" x2="806" y2="351.6" stroke="#c00" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30" y="345.6" fill="#c00">SL 81.45 (construit) = −9 % (procent real)</text>
<line x1="24" y1="287.2" x2="806" y2="287.2" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="792" y="281.2" fill="#188a3e" text-anchor="end">intrare 89.50 (construit)</text>
<line x1="24" y1="72.4" x2="806" y2="72.4" stroke="#1a5fb4" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="792" y="66.4" fill="#1a5fb4" text-anchor="end">TP 116.35 (construit) = +30 % (procent real)</text>
<polyline points="329.0,249.9 344.0,258.3 359.0,266.9 374.0,275.7 389.0,284.3 404.0,291.5 419.0,297.3 434.0,301.7 449.0,305.2 464.0,308.4 479.0,311.8 494.0,315.6 509.0,319.3 524.0,321.1 539.0,322.2 554.0,320.6 569.0,317.3 584.0,313.9 599.0,311.7 614.0,308.9 629.0,305.5 644.0,301.9 659.0,296.3 674.0,288.7 689.0,280.9 704.0,272.3 719.0,263.3 734.0,253.3 749.0,241.9 764.0,229.5" fill="none" stroke="#b06000" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="770" y="224" fill="#b06000">SMA-20</text>
<line x1="44.0" y1="120.0" x2="44.0" y2="143.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="39.5" y="123.2" width="9" height="16.0" fill="#c00"/>
<line x1="59.0" y1="136.0" x2="59.0" y2="155.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="54.5" y="139.2" width="9" height="12.0" fill="#c00"/>
<line x1="74.0" y1="148.0" x2="74.0" y2="167.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="69.5" y="151.2" width="9" height="12.0" fill="#c00"/>
<line x1="89.0" y1="160.0" x2="89.0" y2="183.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="84.5" y="163.2" width="9" height="16.0" fill="#c00"/>
<line x1="104.0" y1="176.0" x2="104.0" y2="195.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="99.5" y="179.2" width="9" height="12.0" fill="#c00"/>
<line x1="119.0" y1="188.0" x2="119.0" y2="207.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="114.5" y="191.2" width="9" height="12.0" fill="#c00"/>
<line x1="134.0" y1="200.0" x2="134.0" y2="223.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="129.5" y="203.2" width="9" height="16.0" fill="#c00"/>
<line x1="149.0" y1="216.0" x2="149.0" y2="235.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="144.5" y="219.2" width="9" height="12.0" fill="#c00"/>
<line x1="164.0" y1="228.0" x2="164.0" y2="247.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="159.5" y="231.2" width="9" height="12.0" fill="#c00"/>
<line x1="179.0" y1="240.0" x2="179.0" y2="259.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="174.5" y="243.2" width="9" height="12.0" fill="#c00"/>
<line x1="194.0" y1="252.0" x2="194.0" y2="267.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="189.5" y="255.2" width="9" height="8.0" fill="#c00"/>
<line x1="209.0" y1="260.0" x2="209.0" y2="279.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="204.5" y="263.2" width="9" height="12.0" fill="#c00"/>
<line x1="224.0" y1="272.0" x2="224.0" y2="291.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="219.5" y="275.2" width="9" height="12.0" fill="#c00"/>
<line x1="239.0" y1="284.0" x2="239.0" y2="307.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="234.5" y="287.2" width="9" height="16.0" fill="#c00"/>
<line x1="254.0" y1="300.0" x2="254.0" y2="323.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="249.5" y="303.2" width="9" height="16.0" fill="#c00"/>
<line x1="269.0" y1="316.0" x2="269.0" y2="344.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="264.5" y="319.2" width="9" height="21.6" fill="#c00"/>
<line x1="284.0" y1="324.0" x2="284.0" y2="342.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="279.5" y="327.2" width="9" height="13.6" fill="#188a3e"/>
<line x1="299.0" y1="308.0" x2="299.0" y2="331.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="294.5" y="311.2" width="9" height="16.0" fill="#188a3e"/>
<line x1="314.0" y1="296.0" x2="314.0" y2="315.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="309.5" y="299.2" width="9" height="12.0" fill="#188a3e"/>
<line x1="329.0" y1="292.0" x2="329.0" y2="303.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="324.5" y="295.2" width="9" height="4.0" fill="#188a3e"/>
<line x1="344.0" y1="292.0" x2="344.0" y2="311.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="339.5" y="295.2" width="9" height="12.0" fill="#c00"/>
<line x1="359.0" y1="304.0" x2="359.0" y2="327.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="354.5" y="307.2" width="9" height="16.0" fill="#c00"/>
<line x1="374.0" y1="320.0" x2="374.0" y2="343.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="369.5" y="323.2" width="9" height="16.0" fill="#c00"/>
<line x1="389.0" y1="336.0" x2="389.0" y2="351.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="384.5" y="339.2" width="9" height="12.0" fill="#c00"/>
<line x1="404.0" y1="332.0" x2="404.0" y2="351.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="399.5" y="335.2" width="9" height="16.0" fill="#188a3e"/>
<line x1="419.0" y1="316.0" x2="419.0" y2="339.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="414.5" y="319.2" width="9" height="16.0" fill="#188a3e"/>
<line x1="434.0" y1="304.0" x2="434.0" y2="323.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="429.5" y="307.2" width="9" height="12.0" fill="#188a3e"/>
<line x1="449.0" y1="297.6" x2="449.0" y2="311.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="444.5" y="300.8" width="9" height="6.4" fill="#188a3e"/>
<line x1="464.0" y1="297.6" x2="464.0" y2="311.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="459.5" y="300.8" width="9" height="6.4" fill="#c00"/>
<line x1="479.0" y1="304.0" x2="479.0" y2="327.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="474.5" y="307.2" width="9" height="16.0" fill="#c00"/>
<line x1="494.0" y1="320.0" x2="494.0" y2="343.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="489.5" y="323.2" width="9" height="16.0" fill="#c00"/>
<line x1="509.0" y1="336.0" x2="509.0" y2="351.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="504.5" y="339.2" width="9" height="11.2" fill="#c00"/>
<line x1="524.0" y1="320.0" x2="524.0" y2="351.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="519.5" y="323.2" width="9" height="27.2" fill="#188a3e"/>
<line x1="539.0" y1="312.8" x2="539.0" y2="329.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="534.5" y="323.2" width="9" height="1.6" fill="#c00"/>
<line x1="554.0" y1="284.0" x2="554.0" y2="328.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="549.5" y="287.2" width="9" height="36.8" fill="#188a3e"/>
<line x1="569.0" y1="272.0" x2="569.0" y2="291.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="564.5" y="275.2" width="9" height="12.0" fill="#188a3e"/>
<line x1="584.0" y1="256.0" x2="584.0" y2="279.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="579.5" y="259.2" width="9" height="16.0" fill="#188a3e"/>
<line x1="599.0" y1="256.0" x2="599.0" y2="271.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="594.5" y="259.2" width="9" height="8.0" fill="#c00"/>
<line x1="614.0" y1="240.0" x2="614.0" y2="271.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="609.5" y="243.2" width="9" height="24.0" fill="#188a3e"/>
<line x1="629.0" y1="224.0" x2="629.0" y2="247.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="624.5" y="227.2" width="9" height="16.0" fill="#188a3e"/>
<line x1="644.0" y1="224.0" x2="644.0" y2="239.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="639.5" y="227.2" width="9" height="8.0" fill="#c00"/>
<line x1="659.0" y1="208.0" x2="659.0" y2="239.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="654.5" y="211.2" width="9" height="24.0" fill="#188a3e"/>
<line x1="674.0" y1="184.0" x2="674.0" y2="215.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="669.5" y="187.2" width="9" height="24.0" fill="#188a3e"/>
<line x1="689.0" y1="184.0" x2="689.0" y2="199.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="684.5" y="187.2" width="9" height="8.0" fill="#c00"/>
<line x1="704.0" y1="160.0" x2="704.0" y2="199.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="699.5" y="163.2" width="9" height="32.0" fill="#188a3e"/>
<line x1="719.0" y1="136.0" x2="719.0" y2="167.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="714.5" y="139.2" width="9" height="24.0" fill="#188a3e"/>
<line x1="734.0" y1="104.0" x2="734.0" y2="143.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="729.5" y="107.2" width="9" height="32.0" fill="#188a3e"/>
<line x1="749.0" y1="69.2" x2="749.0" y2="111.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="744.5" y="72.4" width="9" height="34.8" fill="#188a3e"/>
<line x1="764.0" y1="56.0" x2="764.0" y2="76.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="759.5" y="59.2" width="9" height="13.2" fill="#188a3e"/>
<line x1="24" y1="447.6" x2="806" y2="447.6" stroke="#888"/>
<rect x="39.5" y="408.3" width="9" height="39.3" fill="#c00" opacity="0.55"/>
<rect x="54.5" y="410.5" width="9" height="37.1" fill="#c00" opacity="0.55"/>
<rect x="69.5" y="413.3" width="9" height="34.3" fill="#c00" opacity="0.55"/>
<rect x="84.5" y="411.9" width="9" height="35.7" fill="#c00" opacity="0.55"/>
<rect x="99.5" y="415.5" width="9" height="32.1" fill="#c00" opacity="0.55"/>
<rect x="114.5" y="414.0" width="9" height="33.6" fill="#c00" opacity="0.55"/>
<rect x="129.5" y="416.2" width="9" height="31.4" fill="#c00" opacity="0.55"/>
<rect x="144.5" y="414.7" width="9" height="32.9" fill="#c00" opacity="0.55"/>
<rect x="159.5" y="417.6" width="9" height="30.0" fill="#c00" opacity="0.55"/>
<rect x="174.5" y="416.2" width="9" height="31.4" fill="#c00" opacity="0.55"/>
<rect x="189.5" y="419.0" width="9" height="28.6" fill="#c00" opacity="0.55"/>
<rect x="204.5" y="417.6" width="9" height="30.0" fill="#c00" opacity="0.55"/>
<rect x="219.5" y="420.5" width="9" height="27.1" fill="#c00" opacity="0.55"/>
<rect x="234.5" y="418.3" width="9" height="29.3" fill="#c00" opacity="0.55"/>
<rect x="249.5" y="406.2" width="9" height="41.4" fill="#c00" opacity="0.55"/>
<rect x="264.5" y="403.3" width="9" height="44.3" fill="#c00" opacity="0.55"/>
<rect x="279.5" y="411.9" width="9" height="35.7" fill="#188a3e" opacity="0.55"/>
<rect x="294.5" y="414.7" width="9" height="32.9" fill="#188a3e" opacity="0.55"/>
<rect x="309.5" y="416.2" width="9" height="31.4" fill="#188a3e" opacity="0.55"/>
<rect x="324.5" y="416.9" width="9" height="30.7" fill="#188a3e" opacity="0.55"/>
<rect x="339.5" y="415.5" width="9" height="32.1" fill="#c00" opacity="0.55"/>
<rect x="354.5" y="416.2" width="9" height="31.4" fill="#c00" opacity="0.55"/>
<rect x="369.5" y="414.0" width="9" height="33.6" fill="#c00" opacity="0.55"/>
<rect x="384.5" y="400.5" width="9" height="47.1" fill="#c00" opacity="0.55"/>
<rect x="399.5" y="408.3" width="9" height="39.3" fill="#188a3e" opacity="0.55"/>
<rect x="414.5" y="411.9" width="9" height="35.7" fill="#188a3e" opacity="0.55"/>
<rect x="429.5" y="414.0" width="9" height="33.6" fill="#188a3e" opacity="0.55"/>
<rect x="444.5" y="415.5" width="9" height="32.1" fill="#188a3e" opacity="0.55"/>
<rect x="459.5" y="416.2" width="9" height="31.4" fill="#c00" opacity="0.55"/>
<rect x="474.5" y="417.6" width="9" height="30.0" fill="#c00" opacity="0.55"/>
<rect x="489.5" y="416.9" width="9" height="30.7" fill="#c00" opacity="0.55"/>
<rect x="504.5" y="415.5" width="9" height="32.1" fill="#c00" opacity="0.55"/>
<rect x="519.5" y="404.7" width="9" height="42.9" fill="#188a3e" opacity="0.55"/>
<rect x="534.5" y="396.2" width="9" height="51.4" fill="#c00" opacity="0.55"/>
<rect x="549.5" y="387.6" width="9" height="60.0" fill="#188a3e" opacity="0.55"/>
<rect x="564.5" y="391.9" width="9" height="55.7" fill="#188a3e" opacity="0.55"/>
<rect x="579.5" y="397.6" width="9" height="50.0" fill="#188a3e" opacity="0.55"/>
<rect x="594.5" y="401.9" width="9" height="45.7" fill="#c00" opacity="0.55"/>
<rect x="609.5" y="404.7" width="9" height="42.9" fill="#188a3e" opacity="0.55"/>
<rect x="624.5" y="406.2" width="9" height="41.4" fill="#188a3e" opacity="0.55"/>
<rect x="639.5" y="409.0" width="9" height="38.6" fill="#c00" opacity="0.55"/>
<rect x="654.5" y="410.5" width="9" height="37.1" fill="#188a3e" opacity="0.55"/>
<rect x="669.5" y="407.6" width="9" height="40.0" fill="#188a3e" opacity="0.55"/>
<rect x="684.5" y="404.7" width="9" height="42.9" fill="#c00" opacity="0.55"/>
<rect x="699.5" y="400.5" width="9" height="47.1" fill="#188a3e" opacity="0.55"/>
<rect x="714.5" y="394.7" width="9" height="52.9" fill="#188a3e" opacity="0.55"/>
<rect x="729.5" y="389.0" width="9" height="58.6" fill="#188a3e" opacity="0.55"/>
<rect x="744.5" y="383.3" width="9" height="64.3" fill="#188a3e" opacity="0.55"/>
<rect x="759.5" y="377.6" width="9" height="70.0" fill="#188a3e" opacity="0.55"/>
<text x="24" y="371.6" fill="#555">volum</text>
<text x="269.0" y="364.0" fill="#c00" text-anchor="middle" style="font-weight:bold">bottom 1 82.40</text>
<text x="389.0" y="365.6" fill="#c00" text-anchor="middle" style="font-weight:bold">bottom 2 81.45</text>
<text x="509.0" y="365.6" fill="#c00" text-anchor="middle" style="font-weight:bold">bottom 3 81.45</text>
<text x="539.0" y="302.8" fill="#b06000" text-anchor="middle" style="font-weight:bold">doji</text>
<text x="554.0" y="260.0" fill="#188a3e" text-anchor="middle" style="font-weight:bold">confirmare (intrare)</text>
<text x="776.0" y="46.0" fill="#188a3e" text-anchor="end" style="font-weight:bold">higher high — TP atins</text>
<text x="24" y="469.6" fill="#c00">bara 33 = doji: o 85.00, c 84.90, h 86.30, l 84.20 — corp mic exact pe pivotul monthly 86.00 (indecizie la suport)</text>
<text x="24" y="495" fill="#555">Procentele (stop 9 %, +30 %) sunt ale cursului; nivelurile de preț sunt construite de sumarizator (18_2025-09-23.md:713).</text>
<svg viewBox="0 0 990 622" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif">
<text x="24" y="70" fill="#333" style="font-weight:bold">LABU — daily</text>
<rect x="34.5" y="129.6" width="484.0" height="247.6" fill="#777" fill-opacity="0.08" stroke="#777" stroke-width="1"/>
<text x="34.5" y="124.6" fill="#777" style="font-weight:bold">1. setup: scădere lungă, apoi trei minime aproape egale — pivotul 86.00 atins de două ori</text>
<rect x="529.5" y="293.6" width="34.0" height="56.0" fill="#b06000" fill-opacity="0.08" stroke="#b06000" stroke-width="1"/>
<text x="529.5" y="220.6" fill="#b06000" style="font-weight:bold">2. doji + confirmare</text>
<rect x="559.5" y="116.8" width="304.0" height="196.0" fill="#188a3e" fill-opacity="0.08" stroke="#188a3e" stroke-width="1"/>
<text x="559.5" y="111.8" fill="#188a3e" style="font-weight:bold">3. trendul pornește</text>
<rect x="859.5" y="69.6" width="34.0" height="51.2" fill="#1a5fb4" fill-opacity="0.08" stroke="#1a5fb4" stroke-width="1"/>
<text x="859.5" y="64.6" fill="#1a5fb4" style="font-weight:bold">4. ținta</text>
<line x1="24" y1="332.8" x2="976" y2="332.8" stroke="#777" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30" y="326.8" fill="#777">pivot lunar 86.00</text>
<line x1="24" y1="369.2" x2="976" y2="369.2" stroke="#c00" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30" y="363.2" fill="#c00">stop 81.45 = 9 % sub intrare (procent real)</text>
<line x1="24" y1="304.8" x2="976" y2="304.8" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="962" y="298.8" fill="#188a3e" text-anchor="end">intrare 89.50</text>
<line x1="24" y1="240.4" x2="976" y2="240.4" stroke="#777" stroke-width="1.5" stroke-dasharray="2 3"/>
<text x="30" y="234.4" fill="#777">ținta 1:1 97.55</text>
<line x1="24" y1="90.0" x2="976" y2="90.0" stroke="#1a5fb4" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30" y="84.0" fill="#1a5fb4">116.35 = +30 % față de intrare (procent real)</text>
<polyline points="329.0,269.5 344.0,277.3 359.0,285.1 374.0,292.9 389.0,300.5 404.0,308.0 419.0,315.0 434.0,320.8 449.0,325.5 464.0,329.4 479.0,333.1 494.0,336.9 509.0,340.5 524.0,341.9 539.0,342.5 554.0,340.9 569.0,337.5 584.0,333.0 599.0,330.4 614.0,327.6 629.0,324.6 644.0,320.6 659.0,315.4 674.0,309.9 689.0,303.6 704.0,297.2 719.0,290.3 734.0,282.7 749.0,275.0 764.0,268.0 779.0,259.2 794.0,249.0 809.0,238.8 824.0,229.0 839.0,218.4 854.0,208.6 869.0,198.9 884.0,189.5" fill="none" stroke="#b06000" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="890" y="184" fill="#b06000">SMA-20</text>
<line x1="44.0" y1="137.6" x2="44.0" y2="160.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="39.5" y="140.8" width="9" height="16.0" fill="#c00"/>
<line x1="59.0" y1="153.6" x2="59.0" y2="172.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="54.5" y="156.8" width="9" height="12.0" fill="#c00"/>
<line x1="74.0" y1="165.6" x2="74.0" y2="184.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="69.5" y="168.8" width="9" height="12.0" fill="#c00"/>
<line x1="89.0" y1="177.6" x2="89.0" y2="200.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="84.5" y="180.8" width="9" height="16.0" fill="#c00"/>
<line x1="104.0" y1="193.6" x2="104.0" y2="212.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="99.5" y="196.8" width="9" height="12.0" fill="#c00"/>
<line x1="119.0" y1="205.6" x2="119.0" y2="224.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="114.5" y="208.8" width="9" height="12.0" fill="#c00"/>
<line x1="134.0" y1="217.6" x2="134.0" y2="240.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="129.5" y="220.8" width="9" height="16.0" fill="#c00"/>
<line x1="149.0" y1="233.6" x2="149.0" y2="252.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="144.5" y="236.8" width="9" height="12.0" fill="#c00"/>
<line x1="164.0" y1="245.6" x2="164.0" y2="264.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="159.5" y="248.8" width="9" height="12.0" fill="#c00"/>
<line x1="179.0" y1="257.6" x2="179.0" y2="276.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="174.5" y="260.8" width="9" height="12.0" fill="#c00"/>
<line x1="194.0" y1="269.6" x2="194.0" y2="284.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="189.5" y="272.8" width="9" height="8.0" fill="#c00"/>
<line x1="209.0" y1="277.6" x2="209.0" y2="296.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="204.5" y="280.8" width="9" height="12.0" fill="#c00"/>
<line x1="224.0" y1="289.6" x2="224.0" y2="308.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="219.5" y="292.8" width="9" height="12.0" fill="#c00"/>
<line x1="239.0" y1="301.6" x2="239.0" y2="324.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="234.5" y="304.8" width="9" height="16.0" fill="#c00"/>
<line x1="254.0" y1="317.6" x2="254.0" y2="340.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="249.5" y="320.8" width="9" height="16.0" fill="#c00"/>
<line x1="269.0" y1="333.6" x2="269.0" y2="356.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="264.5" y="336.8" width="9" height="16.0" fill="#c00"/>
<line x1="284.0" y1="349.6" x2="284.0" y2="361.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="279.5" y="352.8" width="9" height="5.6" fill="#c00"/>
<line x1="299.0" y1="341.6" x2="299.0" y2="358.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="294.5" y="344.8" width="9" height="13.6" fill="#188a3e"/>
<line x1="314.0" y1="325.6" x2="314.0" y2="348.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="309.5" y="328.8" width="9" height="16.0" fill="#188a3e"/>
<line x1="329.0" y1="313.6" x2="329.0" y2="332.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="324.5" y="316.8" width="9" height="12.0" fill="#188a3e"/>
<line x1="344.0" y1="309.6" x2="344.0" y2="320.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="339.5" y="312.8" width="9" height="4.0" fill="#188a3e"/>
<line x1="359.0" y1="309.6" x2="359.0" y2="328.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="354.5" y="312.8" width="9" height="12.0" fill="#c00"/>
<line x1="374.0" y1="321.6" x2="374.0" y2="340.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="369.5" y="324.8" width="9" height="12.0" fill="#c00"/>
<line x1="389.0" y1="333.6" x2="389.0" y2="352.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="384.5" y="336.8" width="9" height="12.0" fill="#c00"/>
<line x1="404.0" y1="345.6" x2="404.0" y2="362.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="399.5" y="348.8" width="9" height="9.6" fill="#c00"/>
<line x1="419.0" y1="355.2" x2="419.0" y2="364.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="414.5" y="358.4" width="9" height="4.0" fill="#c00"/>
<line x1="434.0" y1="349.6" x2="434.0" y2="362.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="429.5" y="352.8" width="9" height="9.6" fill="#188a3e"/>
<line x1="449.0" y1="339.2" x2="449.0" y2="356.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="444.5" y="342.4" width="9" height="10.4" fill="#188a3e"/>
<line x1="464.0" y1="334.4" x2="464.0" y2="346.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="459.5" y="337.6" width="9" height="4.8" fill="#188a3e"/>
<line x1="479.0" y1="334.4" x2="479.0" y2="351.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="474.5" y="337.6" width="9" height="9.6" fill="#c00"/>
<line x1="494.0" y1="344.0" x2="494.0" y2="360.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="489.5" y="347.2" width="9" height="9.6" fill="#c00"/>
<line x1="509.0" y1="353.6" x2="509.0" y2="369.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="504.5" y="356.8" width="9" height="8.8" fill="#c00"/>
<line x1="524.0" y1="328.8" x2="524.0" y2="365.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="519.5" y="332.0" width="9" height="33.6" fill="#188a3e"/>
<line x1="539.0" y1="326.4" x2="539.0" y2="341.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="534.5" y="332.0" width="9" height="1.6" fill="#c00"/>
<line x1="554.0" y1="301.6" x2="554.0" y2="336.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="549.5" y="304.8" width="9" height="28.0" fill="#188a3e"/>
<line x1="569.0" y1="281.6" x2="569.0" y2="304.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="564.5" y="284.8" width="9" height="20.0" fill="#188a3e"/>
<line x1="584.0" y1="265.6" x2="584.0" y2="288.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="579.5" y="268.8" width="9" height="16.0" fill="#188a3e"/>
<line x1="599.0" y1="265.6" x2="599.0" y2="304.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="594.5" y="268.8" width="9" height="24.0" fill="#c00"/>
<line x1="614.0" y1="269.6" x2="614.0" y2="296.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="609.5" y="272.8" width="9" height="20.0" fill="#188a3e"/>
<line x1="629.0" y1="253.6" x2="629.0" y2="276.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="624.5" y="256.8" width="9" height="16.0" fill="#188a3e"/>
<line x1="644.0" y1="229.6" x2="644.0" y2="260.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="639.5" y="232.8" width="9" height="24.0" fill="#188a3e"/>
<line x1="659.0" y1="217.6" x2="659.0" y2="236.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="654.5" y="220.8" width="9" height="12.0" fill="#188a3e"/>
<line x1="674.0" y1="217.6" x2="674.0" y2="231.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="669.5" y="220.8" width="9" height="6.4" fill="#c00"/>
<line x1="689.0" y1="219.2" x2="689.0" y2="231.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="684.5" y="222.4" width="9" height="4.8" fill="#188a3e"/>
<line x1="704.0" y1="219.2" x2="704.0" y2="233.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="699.5" y="222.4" width="9" height="7.2" fill="#c00"/>
<line x1="719.0" y1="221.6" x2="719.0" y2="233.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="714.5" y="224.8" width="9" height="4.8" fill="#188a3e"/>
<line x1="734.0" y1="197.6" x2="734.0" y2="228.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="729.5" y="200.8" width="9" height="24.0" fill="#188a3e"/>
<line x1="749.0" y1="185.6" x2="749.0" y2="204.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="744.5" y="188.8" width="9" height="12.0" fill="#188a3e"/>
<line x1="764.0" y1="185.6" x2="764.0" y2="200.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="759.5" y="188.8" width="9" height="8.0" fill="#c00"/>
<line x1="779.0" y1="169.6" x2="779.0" y2="200.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="774.5" y="172.8" width="9" height="24.0" fill="#188a3e"/>
<line x1="794.0" y1="149.6" x2="794.0" y2="176.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="789.5" y="152.8" width="9" height="20.0" fill="#188a3e"/>
<line x1="809.0" y1="149.6" x2="809.0" y2="164.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="804.5" y="152.8" width="9" height="8.0" fill="#c00"/>
<line x1="824.0" y1="133.6" x2="824.0" y2="164.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="819.5" y="136.8" width="9" height="24.0" fill="#188a3e"/>
<line x1="839.0" y1="117.6" x2="839.0" y2="140.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="834.5" y="120.8" width="9" height="16.0" fill="#188a3e"/>
<line x1="854.0" y1="105.6" x2="854.0" y2="124.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="849.5" y="108.8" width="9" height="12.0" fill="#188a3e"/>
<line x1="869.0" y1="86.8" x2="869.0" y2="112.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="864.5" y="90.0" width="9" height="18.8" fill="#188a3e"/>
<line x1="884.0" y1="77.6" x2="884.0" y2="94.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="879.5" y="80.8" width="9" height="9.2" fill="#188a3e"/>
<line x1="24" y1="546.2" x2="976" y2="546.2" stroke="#888"/>
<rect x="39.5" y="506.1" width="9" height="40.1" fill="#c00" opacity="0.55"/>
<rect x="54.5" y="508.3" width="9" height="37.9" fill="#c00" opacity="0.55"/>
<rect x="69.5" y="511.2" width="9" height="35.0" fill="#c00" opacity="0.55"/>
<rect x="84.5" y="509.7" width="9" height="36.5" fill="#c00" opacity="0.55"/>
<rect x="99.5" y="513.4" width="9" height="32.8" fill="#c00" opacity="0.55"/>
<rect x="114.5" y="511.9" width="9" height="34.3" fill="#c00" opacity="0.55"/>
<rect x="129.5" y="514.1" width="9" height="32.1" fill="#c00" opacity="0.55"/>
<rect x="144.5" y="512.7" width="9" height="33.5" fill="#c00" opacity="0.55"/>
<rect x="159.5" y="515.6" width="9" height="30.6" fill="#c00" opacity="0.55"/>
<rect x="174.5" y="514.1" width="9" height="32.1" fill="#c00" opacity="0.55"/>
<rect x="189.5" y="517.0" width="9" height="29.2" fill="#c00" opacity="0.55"/>
<rect x="204.5" y="515.6" width="9" height="30.6" fill="#c00" opacity="0.55"/>
<rect x="219.5" y="518.5" width="9" height="27.7" fill="#c00" opacity="0.55"/>
<rect x="234.5" y="516.3" width="9" height="29.9" fill="#c00" opacity="0.55"/>
<rect x="249.5" y="503.9" width="9" height="42.3" fill="#c00" opacity="0.55"/>
<rect x="264.5" y="501.0" width="9" height="45.2" fill="#c00" opacity="0.55"/>
<rect x="279.5" y="496.6" width="9" height="49.6" fill="#c00" opacity="0.55"/>
<rect x="294.5" y="509.7" width="9" height="36.5" fill="#188a3e" opacity="0.55"/>
<rect x="309.5" y="512.7" width="9" height="33.5" fill="#188a3e" opacity="0.55"/>
<rect x="324.5" y="514.1" width="9" height="32.1" fill="#188a3e" opacity="0.55"/>
<rect x="339.5" y="514.8" width="9" height="31.4" fill="#188a3e" opacity="0.55"/>
<rect x="354.5" y="513.4" width="9" height="32.8" fill="#c00" opacity="0.55"/>
<rect x="369.5" y="514.1" width="9" height="32.1" fill="#c00" opacity="0.55"/>
<rect x="384.5" y="511.9" width="9" height="34.3" fill="#c00" opacity="0.55"/>
<rect x="399.5" y="512.7" width="9" height="33.5" fill="#c00" opacity="0.55"/>
<rect x="414.5" y="513.4" width="9" height="32.8" fill="#c00" opacity="0.55"/>
<rect x="429.5" y="511.9" width="9" height="34.3" fill="#188a3e" opacity="0.55"/>
<rect x="444.5" y="508.3" width="9" height="37.9" fill="#188a3e" opacity="0.55"/>
<rect x="459.5" y="513.4" width="9" height="32.8" fill="#188a3e" opacity="0.55"/>
<rect x="474.5" y="514.1" width="9" height="32.1" fill="#c00" opacity="0.55"/>
<rect x="489.5" y="511.2" width="9" height="35.0" fill="#c00" opacity="0.55"/>
<rect x="504.5" y="495.2" width="9" height="51.0" fill="#c00" opacity="0.55"/>
<rect x="519.5" y="501.0" width="9" height="45.2" fill="#188a3e" opacity="0.55"/>
<rect x="534.5" y="503.9" width="9" height="42.3" fill="#c00" opacity="0.55"/>
<rect x="549.5" y="482.0" width="9" height="64.2" fill="#188a3e" opacity="0.55"/>
<rect x="564.5" y="490.8" width="9" height="55.4" fill="#188a3e" opacity="0.55"/>
<rect x="579.5" y="495.2" width="9" height="51.0" fill="#188a3e" opacity="0.55"/>
<rect x="594.5" y="503.9" width="9" height="42.3" fill="#c00" opacity="0.55"/>
<rect x="609.5" y="501.0" width="9" height="45.2" fill="#188a3e" opacity="0.55"/>
<rect x="624.5" y="498.1" width="9" height="48.1" fill="#188a3e" opacity="0.55"/>
<rect x="639.5" y="493.7" width="9" height="52.5" fill="#188a3e" opacity="0.55"/>
<rect x="654.5" y="495.2" width="9" height="51.0" fill="#188a3e" opacity="0.55"/>
<rect x="669.5" y="514.1" width="9" height="32.1" fill="#c00" opacity="0.55"/>
<rect x="684.5" y="517.0" width="9" height="29.2" fill="#188a3e" opacity="0.55"/>
<rect x="699.5" y="518.5" width="9" height="27.7" fill="#c00" opacity="0.55"/>
<rect x="714.5" y="515.6" width="9" height="30.6" fill="#188a3e" opacity="0.55"/>
<rect x="729.5" y="492.2" width="9" height="54.0" fill="#188a3e" opacity="0.55"/>
<rect x="744.5" y="495.2" width="9" height="51.0" fill="#188a3e" opacity="0.55"/>
<rect x="759.5" y="499.5" width="9" height="46.7" fill="#c00" opacity="0.55"/>
<rect x="774.5" y="496.6" width="9" height="49.6" fill="#188a3e" opacity="0.55"/>
<rect x="789.5" y="493.7" width="9" height="52.5" fill="#188a3e" opacity="0.55"/>
<rect x="804.5" y="498.1" width="9" height="48.1" fill="#c00" opacity="0.55"/>
<rect x="819.5" y="492.2" width="9" height="54.0" fill="#188a3e" opacity="0.55"/>
<rect x="834.5" y="489.3" width="9" height="56.9" fill="#188a3e" opacity="0.55"/>
<rect x="849.5" y="486.4" width="9" height="59.8" fill="#188a3e" opacity="0.55"/>
<rect x="864.5" y="480.6" width="9" height="65.6" fill="#188a3e" opacity="0.55"/>
<rect x="879.5" y="476.2" width="9" height="70.0" fill="#188a3e" opacity="0.55"/>
<text x="24" y="470.2" fill="#555">volum</text>
<text x="284.0" y="381.6" fill="#c00" text-anchor="middle" style="font-weight:bold">test 1 · 82.40</text>
<text x="419.0" y="383.2" fill="#c00" text-anchor="middle" style="font-weight:bold">test 2 · 82.00</text>
<line x1="404.0" y1="274.8" x2="546.1" y2="299.4" stroke="#188a3e" stroke-width="1.8"/>
<polygon points="554.0,300.8 545.4,303.4 546.8,295.5" fill="#188a3e"/>
<text x="404.0" y="255.8" fill="#188a3e" text-anchor="middle" style="font-weight:bold">aici intri, la close 89.50:</text>
<text x="404.0" y="269.8" fill="#188a3e" text-anchor="middle" style="font-weight:bold">abia acum știi că au câștigat cumpărătorii</text>
<line x1="469.0" y1="399.2" x2="502.3" y2="377.6" stroke="#c00" stroke-width="1.8"/>
<polygon points="509.0,373.2 504.5,380.9 500.1,374.2" fill="#c00"/>
<text x="469.0" y="413.2" fill="#c00" text-anchor="middle" style="font-weight:bold">al treilea minim: 81.45,</text>
<text x="469.0" y="427.2" fill="#c00" text-anchor="middle" style="font-weight:bold">fără o nouă atingere a pivotului</text>
<text x="469.0" y="441.2" fill="#c00" text-anchor="middle" style="font-weight:bold">aici pui stopul, sub minime</text>
<line x1="709.0" y1="390.0" x2="605.4" y2="312.8" stroke="#188a3e" stroke-width="1.8"/>
<polygon points="599.0,308.0 607.8,309.6 603.0,316.0" fill="#188a3e"/>
<text x="709.0" y="404.0" fill="#188a3e" text-anchor="middle" style="font-weight:bold">retest: cade înapoi pe intrare</text>
<text x="709.0" y="418.0" fill="#188a3e" text-anchor="middle" style="font-weight:bold">și ține — trendul e sănătos</text>
<line x1="669.0" y1="177.6" x2="685.2" y2="208.1" stroke="#188a3e" stroke-width="1.8"/>
<polygon points="689.0,215.2 681.7,210.0 688.8,206.3" fill="#188a3e"/>
<text x="669.0" y="158.6" fill="#188a3e" text-anchor="middle" style="font-weight:bold">aici se odihnește, nu se strică:</text>
<text x="669.0" y="172.6" fill="#188a3e" text-anchor="middle" style="font-weight:bold">bull flag, pe volum mic</text>
<line x1="800.5" y1="50.0" x2="853.8" y2="85.6" stroke="#1a5fb4" stroke-width="1.8"/>
<polygon points="860.5,90.0 851.6,88.9 856.1,82.2" fill="#1a5fb4"/>
<text x="796.5" y="47.0" fill="#1a5fb4" text-anchor="end" style="font-weight:bold">a ajuns la 116.35: +30 % în 21 de zile de bursă,</text>
<text x="796.5" y="61.0" fill="#1a5fb4" text-anchor="end" style="font-weight:bold">cam 3,3R din cât ai riscat</text>
<text x="24" y="568.2" fill="#c00">doji = corp mic (o 86.10, c 86.00): cumpărătorii și vânzătorii sunt la egalitate, exact pe pivotul lunar 86.00</text>
<text x="24" y="585.2" fill="#188a3e">ținta 1:1 (97.55) e atinsă pe bara 40: acolo vinzi o treime, restul merge mai departe — de asta nu vinzi tot la 1:1</text>
<text x="24" y="610" fill="#555">Procentele (stop 9 %, +30 %) sunt ale cursului; nivelurile de preț sunt puse de sumarizator.</text>
</svg>

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

@@ -3,9 +3,9 @@
Citește `gen/strategii/buy_doji_locatie.spec.txt`. Două panouri alăturate cu
ACEEAȘI serie de 10 bare, pe aceeași scară și aceeași axă de preț (candelele
stau la aceleași y). Stânga: pivot monthly S1 49.00, la 0,41 % sub low-ul
stau la aceleași y). Stânga: pivot lunar 49.00, la 0,51 % sub low-ul
dojiului. Dreapta: S1 46.00 și PP 53.50 — cel mai apropiat nivel sub doji e
la 6,96 %. Nivelurile se desenează de mână, cu coordonate absolute (liniile
la 7,07 %. Nivelurile se desenează de mână, cu coordonate absolute (liniile
din Chart pornesc mereu de la x=24, ar trece peste panoul vecin).
Rulare: python3 gen/strategii/buy_doji_locatie.py
@@ -13,13 +13,13 @@ Rulare: python3 gen/strategii/buy_doji_locatie.py
import re
import sys
sys.path.insert(0, "/workspace/atm-curs-dl")
from svg_candles import Chart, Mark, from_closes # noqa: E402
from svg_candles import Arrow, Chart, Mark, from_closes # noqa: E402
OUT = "/workspace/atm-curs-dl/gen/strategii/buy_doji_locatie.svg"
CLOSES = [52.20, 51.40, 50.60, 49.65, 49.60, 49.90, 50.40, 50.80, 51.10, 51.50]
wicks = [(0.15, 0.15)] * len(CLOSES)
wicks[4] = (0.45, 0.40) # doji: h 50.10 / l 49.20
wicks[4] = (0.45, 0.35) # doji: h 50.10 / l 49.25
cds = from_closes(CLOSES, wicks=wicks, start=53.00)
doji = cds[4]
S1_DA, S1_NU, PP_NU = 49.00, 46.00, 53.50
@@ -28,16 +28,16 @@ NIVELURI_NU = [S1_NU, PP_NU]
# --- assert-urile din spec ---------------------------------------------------
for i in range(1, len(cds)): # 1
assert cds[i].o == cds[i - 1].c, f"open[{i}] != close[{i-1}]"
assert abs(doji.h - 50.10) < 1e-9 and abs(doji.l - 49.20) < 1e-9
assert abs(doji.h - 50.10) < 1e-9 and abs(doji.l - 49.25) < 1e-9
assert abs(doji.o - doji.c) <= 0.10 * (doji.h - doji.l), "bara 4 nu e doji"
assert cds[6].c > doji.h, "bara 6 nu confirmă"
d_da = round((doji.l - S1_DA) / S1_DA * 100, 2) # 2
assert d_da == 0.41 and d_da <= 2
assert d_da == 0.51 and d_da <= 2
d_nu = round((doji.l - S1_NU) / S1_NU * 100, 2) # 3
assert d_nu == 6.96 and d_nu > 2 and (PP_NU - doji.h) > 0
assert d_nu == 7.07 and d_nu > 2 and (PP_NU - doji.h) > 0
assert not any(S1_NU < p < PP_NU for p in NIVELURI_NU)
d_pp = round((PP_NU - doji.l) / doji.l * 100, 2) # PP e deasupra, mai departe
assert d_pp == 8.74 and d_pp > d_nu
assert d_pp == 8.63 and d_pp > d_nu
# --- layout: două panouri, aceeași axă --------------------------------------
BLUE, GREEN, RED, ORANGE, GREY = "#1a5fb4", "#188a3e", "#c00", "#b06000", "#555"
@@ -45,61 +45,67 @@ W, PW = 760, 350 # lățime totală, lățime panou
PX = [24, 24 + PW + 28] # x-ul stâng al fiecărui panou
SCALE, TOP = 36.0, 96 # px/unitate și y-ul celui mai mare preț
ARR = {
PX[0]: Arrow(8, "pivot lunar: nivel urmărit\nde mulți — aici apar\ncumpărătorii",
price=S1_DA, where="below", color=BLUE),
PX[1]: Arrow(4, "aceeași formă, dar nimic sub el\nnu are cine să-l susțină",
where="below", color=RED, dx=100),
}
charts = []
for px in PX:
ch = Chart(candles=cds, marks=[Mark(4, "doji", ORANGE, "above", dy=-16),
Mark(6, "confirmare", GREEN, "above", dy=-26)],
arrows=[ARR[px]],
scale=SCALE, gap=17, body_w=10, left=px + 34, width=px + PW, top=TOP)
body = ch.render()
# `_render()`, nu `render()`: al doilea restaurează top/left, iar zonele și
# etichetele desenate de mână ar pica deplasate față de body-ul randat
body = ch._render()
assert f'viewBox="0 0 {px + PW} ' in body, "textul unei săgeți iese din panou"
assert (ch.top, ch.left) == (TOP, px + 34), "Chart a mutat graficul: panourile s-ar dezalinia"
charts.append((ch, body.split(">", 1)[1].rsplit("</svg>", 1)[0].strip()))
(ch_da, body_da), (ch_nu, body_nu) = charts
assert ch_da.scale == ch_nu.scale and ch_da._pmax == ch_nu._pmax, "scări diferite" # 4
y = ch_da._y # axa e comună: același y pe ambele panouri
def level(px, price, text, color):
def level(px, price, text, color, below=False):
yy = y(price)
ty, anchor, tx = (yy + 14, "start", px + 6) if below else (yy - 6, "end", px + PW - 4)
return [f'<line x1="{px}" y1="{yy:.1f}" x2="{px + PW}" y2="{yy:.1f}" stroke="{color}" '
f'stroke-width="1.5" stroke-dasharray="4 3"/>',
f'<text x="{px + PW - 4}" y="{yy - 6:.1f}" fill="{color}" text-anchor="end">{text}</text>']
f'<text x="{tx}" y="{ty:.1f}" fill="{color}" text-anchor="{anchor}">{text}</text>']
def arrow(x, y1, y2, color): # săgeată dublă verticală între y1 și y2
return [f'<line x1="{x:.1f}" y1="{y1:.1f}" x2="{x:.1f}" y2="{y2:.1f}" stroke="{color}" stroke-width="1.5"/>',
f'<polygon points="{x - 4:.1f},{y1 + 7:.1f} {x + 4:.1f},{y1 + 7:.1f} {x:.1f},{y1:.1f}" fill="{color}"/>',
f'<polygon points="{x - 4:.1f},{y2 - 7:.1f} {x + 4:.1f},{y2 - 7:.1f} {x:.1f},{y2:.1f}" fill="{color}"/>']
def zone(px, p_top, p_bot, label, color, label_at_bottom=False):
"""Dreptunghi de evidențiere pe toată lățimea panoului, între două prețuri."""
y0, y1 = y(p_top), y(p_bot)
ly, anchor, lx = ((y1 - 12, "start", px + 8) if label_at_bottom
else (y0 - 6, "end", px + PW - 4))
return [f'<rect x="{px}" y="{y0:.1f}" width="{PW}" height="{y1 - y0:.1f}" fill="{color}" '
f'fill-opacity="0.12" stroke="{color}" stroke-width="1"/>',
f'<text x="{lx}" y="{ly:.1f}" fill="{color}" text-anchor="{anchor}" '
f'style="font-weight:bold">{label}</text>']
xd_da, xd_nu = ch_da._cx(4), ch_nu._cx(4)
y_low, y_bot = y(doji.l), y(S1_NU)
ly = y(S1_DA) + 24 # textul de distanță, sub linia 49.00
y_bot = y(S1_NU)
parts = [
f'<svg viewBox="0 0 {W} {y_bot + 62:.0f}" xmlns="http://www.w3.org/2000/svg" '
f'style="width:100%;height:auto;font:12px sans-serif">',
f'<text x="24" y="22" fill="#333" style="font-weight:bold">'
f'Doji la nivel vs. doji în aer — daily, pivoți monthly (exemplu construit)</text>',
f'Doji la nivel vs. doji în aer — daily, pivoți lunari (exemplu construit)</text>',
f'<text x="{PX[0]}" y="48" fill="{GREEN}" style="font-weight:bold">DA — doji la nivel</text>',
f'<text x="{PX[1]}" y="48" fill="{RED}" style="font-weight:bold">NU — doji în aer</text>',
f'<line x1="{PX[1] - 14}" y1="36" x2="{PX[1] - 14}" y2="{y_bot + 8:.0f}" stroke="#ccc"/>',
*level(PX[0], S1_DA, "pivot monthly S1 49.00", BLUE),
*level(PX[1], PP_NU, "PP 53.50", BLUE),
*level(PX[1], S1_NU, "S1 46.00", BLUE),
*zone(PX[0], doji.l, S1_DA, f"{d_da:.2f} % — la nivel".replace(".", ","), GREEN),
*zone(PX[1], doji.l, S1_NU, f"gol de {d_nu:.2f} % sub doji — doji în aer".replace(".", ","),
RED, label_at_bottom=True),
*level(PX[0], S1_DA, "pivotul lunar 49.00", BLUE, below=True),
*level(PX[1], PP_NU, "pivotul lunar 53.50", BLUE),
*level(PX[1], S1_NU, "pivotul lunar 46.00", BLUE, below=True),
body_da, body_nu,
# DA: low-ul dojiului atinge practic linia
f'<circle cx="{xd_da:.1f}" cy="{y_low:.1f}" r="5" fill="none" stroke="{BLUE}" stroke-width="1.5"/>',
f'<text x="{PX[0] + 8}" y="{ly:.1f}" fill="{BLUE}">low 49.20 = +0,41 % față de 49.00</text>',
f'<text x="{PX[0] + 8}" y="{ly + 16:.1f}" fill="{GREEN}" style="font-weight:bold">'
f'→ la nivel (daily: ≤ 1-2 %)</text>',
# NU: distanța până la cel mai apropiat nivel
*arrow(xd_nu, y_low + 3, y_bot - 2, RED),
f'<text x="{xd_nu + 12:.1f}" y="{(y_low + y_bot) / 2 - 8:.1f}" fill="{BLUE}">'
f'cel mai apropiat nivel: 46.00, la 6,96 %</text>',
f'<text x="{xd_nu + 12:.1f}" y="{(y_low + y_bot) / 2 + 8:.1f}" fill="{RED}" '
f'style="font-weight:bold">→ doji în aer</text>',
f'<text x="{xd_nu + 12:.1f}" y="{(y_low + y_bot) / 2 + 26:.1f}" fill="{GREY}">'
f'(PP 53.50 e deasupra, la 8,74 % de low)</text>',
f'<text x="24" y="{y_bot + 30:.0f}" fill="{GREY}">60 min: prag ≤ 0,5 %, pivoți weekly · '
f'daily: 1-2 %, pivoți monthly · weekly: pivoți quarterly</text>',
f'<text x="24" y="{y_bot + 30:.0f}" fill="{GREY}">daily: e „la nivel" dacă low-ul '
f'dojiului e la cel mult 1-2 % de pivotul lunar (aici {d_da:.2f} %; în dreapta '
f'{d_nu:.2f} %).</text>'.replace("0.51 %", "0,51 %").replace("7.07 %", "7,07 %"),
f'<text x="24" y="{y_bot + 48:.0f}" fill="{GREY}">Aceeași serie, aceeași scară; '
f'nivelurile 49.00 / 46.00 / 53.50 sunt construite.</text>',
"</svg>",

View File

@@ -3,39 +3,44 @@ SPEC DIAGRAMĂ — buy_doji_locatie
tip: PRET, două panouri cu ACEEAȘI serie, niveluri diferite
destinație: summaries/17_STRATEGII/01_buy_doji.md, Pasul 4
cheie markdown: <!-- DIAGRAMA: locatie -->
titlu SVG: „Doji la nivel vs. doji în aer — daily, pivoți monthly (exemplu construit)"
titlu SVG: „Doji la nivel vs. doji în aer — daily, pivoți lunari (exemplu construit)"
stil: candele lipite (gap 15-18, body_w 9-10), fără volum; open = close anterior.
CE TREBUIE SĂ DEMONSTREZE
-------------------------
Aceeași formă (trend → doji → confirmare), dar în stânga low-ul dojiului e
la 0,41 % de pivotul monthly (sub pragul de 1-2 % pe daily), iar în dreapta
cel mai apropiat nivel e la 6,96 % dedesubt. Pattern-ul nu te ajută să vezi
la 0,51 % de pivotul lunar (sub pragul de 1-2 % pe daily), iar în dreapta
cel mai apropiat nivel e la 7,07 % dedesubt. Pattern-ul nu te ajută să vezi
diferența; doar măsurătoarea.
SERIA (identică pe ambele panouri, 10 bare)
-------------------------------------------
Seria panoului DA din buy_doji_fereastra.spec.txt, extinsă cu 3 bare:
close-uri 52.20, 51.40, 50.60, 49.65, 49.60 (doji: o 49.65 h 50.10 l 49.20),
close-uri 52.20, 51.40, 50.60, 49.65, 49.60 (doji: o 49.65 h 50.10 l 49.25),
49.90, 50.40 (confirmare), 50.80, 51.10, 51.50; open[0] = 53.00; fitile 0.15.
NIVELURI
--------
Stânga (DA): „pivot monthly S1 49.00" (albastru), eticheta de distanță lângă
doji: „low 49.20 = +0,41 % față de 49.00 → la nivel (daily: ≤ 1-2 %)".
Dreapta (NU): „S1 46.00" jos, „PP 53.50" sus; eticheta: „cel mai apropiat
nivel: 46.00, la 6,96 % → doji în aer".
Sub ambele, text mic: „60 min: prag ≤ 0,5 %, pivoți weekly · daily: 1-2 %,
pivoți monthly · weekly: pivoți quarterly".
Stânga (DA): „pivotul lunar 49.00" (albastru) + ZONĂ verde între low-ul dojiului
(49.25) și 49.00, etichetă „0,51 % — la nivel"; SĂGEATĂ spre linia 49.00:
„pivot lunar: nivel urmărit / de mulți — aici apar / cumpărătorii".
Dreapta (NU): „pivotul lunar 46.00" jos, „pivotul lunar 53.50" sus; ZONĂ roșie
între 49.25 și 46.00, etichetă „gol de 7,07 % sub doji — doji în aer"; SĂGEATĂ
spre doji: „aceeași formă, dar nimic sub el / nu are cine să-l susțină".
Sub ambele, un singur rând: „daily: e «la nivel» dacă low-ul dojiului e la cel
mult 1-2 % de pivotul lunar (aici 0,51 %; în dreapta 7,07 %)". Rândul cu
pragurile pe 60 min / weekly s-a mutat la nivelul 3.
ASSERT-URI
----------
1. open[i] == close[i-1]; doji abs(o-c) <= 0.10*(h-l); close[6] > 50.10.
2. round((49.20-49.00)/49.00*100, 2) == 0.41 și <= 2.
3. round((49.20-46.00)/46.00*100, 2) == 6.96 și > 2; (53.50-50.10) > 0
1. open[i] == close[i-1]; doji h 50.10 / l 49.25; abs(o-c) <= 0.10*(h-l);
close[6] > 50.10.
2. round((49.25-49.00)/49.00*100, 2) == 0.51 și <= 2.
3. round((49.25-46.00)/46.00*100, 2) == 7.07 și > 2; (53.50-50.10) > 0
(niciun nivel între 46.00 și 53.50 pe panoul NU).
4. Scara (px/unitate) identică pe cele două panouri (ca să se vadă că forma e
aceeași).
aceeași); Chart nu are voie să mute graficul (ar dezalinia panourile) — se
randează cu `_render()` și se verifică top/left/lățimea.
SURSA
-----

View File

@@ -1,14 +1,18 @@
<svg viewBox="0 0 760 415" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif">
<text x="24" y="22" fill="#333" style="font-weight:bold">Doji la nivel vs. doji în aer — daily, pivoți monthly (exemplu construit)</text>
<text x="24" y="22" fill="#333" style="font-weight:bold">Doji la nivel vs. doji în aer — daily, pivoți lunari (exemplu construit)</text>
<text x="24" y="48" fill="#188a3e" style="font-weight:bold">DA — doji la nivel</text>
<text x="402" y="48" fill="#c00" style="font-weight:bold">NU — doji în aer</text>
<line x1="388" y1="36" x2="388" y2="361" stroke="#ccc"/>
<rect x="24" y="236.4" width="350" height="9.0" fill="#188a3e" fill-opacity="0.12" stroke="#188a3e" stroke-width="1"/>
<text x="370" y="230.4" fill="#188a3e" text-anchor="end" style="font-weight:bold">0,51 % — la nivel</text>
<rect x="402" y="236.4" width="350" height="117.0" fill="#c00" fill-opacity="0.12" stroke="#c00" stroke-width="1"/>
<text x="410" y="341.4" fill="#c00" text-anchor="start" style="font-weight:bold">gol de 7,07 % sub doji — doji în aer</text>
<line x1="24" y1="245.4" x2="374" y2="245.4" stroke="#1a5fb4" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="370" y="239.4" fill="#1a5fb4" text-anchor="end">pivot monthly S1 49.00</text>
<text x="30" y="259.4" fill="#1a5fb4" text-anchor="start">pivotul lunar 49.00</text>
<line x1="402" y1="83.4" x2="752" y2="83.4" stroke="#1a5fb4" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="748" y="77.4" fill="#1a5fb4" text-anchor="end">PP 53.50</text>
<text x="748" y="77.4" fill="#1a5fb4" text-anchor="end">pivotul lunar 53.50</text>
<line x1="402" y1="353.4" x2="752" y2="353.4" stroke="#1a5fb4" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="748" y="347.4" fill="#1a5fb4" text-anchor="end">S1 46.00</text>
<text x="408" y="367.4" fill="#1a5fb4" text-anchor="start">pivotul lunar 46.00</text>
<line x1="58.0" y1="96.0" x2="58.0" y2="135.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="53.0" y="101.4" width="10" height="28.8" fill="#c00"/>
<line x1="75.0" y1="124.8" x2="75.0" y2="164.4" stroke="#1a1a1a" stroke-width="1.2"/>
@@ -17,7 +21,7 @@
<rect x="87.0" y="159.0" width="10" height="28.8" fill="#c00"/>
<line x1="109.0" y1="182.4" x2="109.0" y2="227.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="104.0" y="187.8" width="10" height="34.2" fill="#c00"/>
<line x1="126.0" y1="205.8" x2="126.0" y2="238.2" stroke="#1a1a1a" stroke-width="1.2"/>
<line x1="126.0" y1="205.8" x2="126.0" y2="236.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="121.0" y="222.0" width="10" height="1.8" fill="#c00"/>
<line x1="143.0" y1="207.6" x2="143.0" y2="229.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="138.0" y="213.0" width="10" height="10.8" fill="#188a3e"/>
@@ -31,6 +35,11 @@
<rect x="206.0" y="155.4" width="10" height="14.4" fill="#188a3e"/>
<text x="126.0" y="179.8" fill="#b06000" text-anchor="middle" style="font-weight:bold">doji</text>
<text x="160.0" y="153.6" fill="#188a3e" text-anchor="middle" style="font-weight:bold">confirmare</text>
<line x1="194.0" y1="275.4" x2="194.0" y2="257.4" stroke="#1a5fb4" stroke-width="1.8"/>
<polygon points="194.0,249.4 198.0,257.4 190.0,257.4" fill="#1a5fb4"/>
<text x="194.0" y="289.4" fill="#1a5fb4" text-anchor="middle" style="font-weight:bold">pivot lunar: nivel urmărit</text>
<text x="194.0" y="303.4" fill="#1a5fb4" text-anchor="middle" style="font-weight:bold">de mulți — aici apar</text>
<text x="194.0" y="317.4" fill="#1a5fb4" text-anchor="middle" style="font-weight:bold">cumpărătorii</text>
<line x1="436.0" y1="96.0" x2="436.0" y2="135.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="431.0" y="101.4" width="10" height="28.8" fill="#c00"/>
<line x1="453.0" y1="124.8" x2="453.0" y2="164.4" stroke="#1a1a1a" stroke-width="1.2"/>
@@ -39,7 +48,7 @@
<rect x="465.0" y="159.0" width="10" height="28.8" fill="#c00"/>
<line x1="487.0" y1="182.4" x2="487.0" y2="227.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="482.0" y="187.8" width="10" height="34.2" fill="#c00"/>
<line x1="504.0" y1="205.8" x2="504.0" y2="238.2" stroke="#1a1a1a" stroke-width="1.2"/>
<line x1="504.0" y1="205.8" x2="504.0" y2="236.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="499.0" y="222.0" width="10" height="1.8" fill="#c00"/>
<line x1="521.0" y1="207.6" x2="521.0" y2="229.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="516.0" y="213.0" width="10" height="10.8" fill="#188a3e"/>
@@ -53,15 +62,10 @@
<rect x="584.0" y="155.4" width="10" height="14.4" fill="#188a3e"/>
<text x="504.0" y="179.8" fill="#b06000" text-anchor="middle" style="font-weight:bold">doji</text>
<text x="538.0" y="153.6" fill="#188a3e" text-anchor="middle" style="font-weight:bold">confirmare</text>
<circle cx="126.0" cy="238.2" r="5" fill="none" stroke="#1a5fb4" stroke-width="1.5"/>
<text x="32" y="269.4" fill="#1a5fb4">low 49.20 = +0,41 % față de 49.00</text>
<text x="32" y="285.4" fill="#188a3e" style="font-weight:bold">→ la nivel (daily: ≤ 1-2 %)</text>
<line x1="504.0" y1="241.2" x2="504.0" y2="351.4" stroke="#c00" stroke-width="1.5"/>
<polygon points="500.0,248.2 508.0,248.2 504.0,241.2" fill="#c00"/>
<polygon points="500.0,344.4 508.0,344.4 504.0,351.4" fill="#c00"/>
<text x="516.0" y="287.8" fill="#1a5fb4">cel mai apropiat nivel: 46.00, la 6,96 %</text>
<text x="516.0" y="303.8" fill="#c00" style="font-weight:bold">→ doji în aer</text>
<text x="516.0" y="321.8" fill="#555">(PP 53.50 e deasupra, la 8,74 % de low)</text>
<text x="24" y="383" fill="#555">60 min: prag ≤ 0,5 %, pivoți weekly · daily: 1-2 %, pivoți monthly · weekly: pivoți quarterly</text>
<line x1="604.0" y1="266.4" x2="511.7" y2="242.4" stroke="#c00" stroke-width="1.8"/>
<polygon points="504.0,240.4 512.7,238.5 510.7,246.3" fill="#c00"/>
<text x="604.0" y="280.4" fill="#c00" text-anchor="middle" style="font-weight:bold">aceeași formă, dar nimic sub el</text>
<text x="604.0" y="294.4" fill="#c00" text-anchor="middle" style="font-weight:bold">nu are cine să-l susțină</text>
<text x="24" y="383" fill="#555">daily: e „la nivel" dacă low-ul dojiului e la cel mult 1-2 % de pivotul lunar (aici 0,51 %; în dreapta 7,07 %).</text>
<text x="24" y="401" fill="#555">Aceeași serie, aceeași scară; nivelurile 49.00 / 46.00 / 53.50 sunt construite.</text>
</svg>

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

@@ -133,14 +133,28 @@ def candles(bars, x0, gap, yf):
out.append('<defs><marker id="pt-arr" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" '
'markerHeight="7" orient="auto"><path d="M0,0 L10,5 L0,10 z" fill="#555"/></marker></defs>')
'markerHeight="7" orient="auto"><path d="M0,0 L10,5 L0,10 z" fill="#555"/></marker>'
'<marker id="pt-red" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" '
'markerHeight="7" orient="auto"><path d="M0,0 L10,5 L0,10 z" fill="#c00"/></marker></defs>')
text(20, 22, "Aceeași regulă pe trei perechi — exemplu construit (fără ticker)", bold=True, size=14)
def zone(x0, y0_, x1, y1, color):
out.append(f'<rect x="{x0:.1f}" y="{y0_:.1f}" width="{x1 - x0:.1f}" height="{y1 - y0_:.1f}" '
f'fill="{color}" fill-opacity="0.10" stroke="{color}" stroke-width="1"/>')
def bracket(x, ya, yb_, color, label):
"""Paranteză verticală între două prețuri, cu eticheta la dreapta."""
out.append(f'<path d="M{x - 5:.1f},{ya:.1f} H{x:.1f} V{yb_:.1f} H{x - 5:.1f}" '
f'fill="none" stroke="{color}" stroke-width="1.6"/>')
text(x + 5, (ya + yb_) / 2 + 4, label, fill=color, bold=True)
y0 = 40
ROW_H = 290
for key, f, tf_big, tf_small, cap, exp in ROWS:
big, small = scaled(BIG_A, f), scaled(SMALL_A, f)
g = check(key, big, small, exp)
first = key == "A"
# titlu rând + subtitluri
text(20, y0 + 14, f"{key}. {tf_big} → {tf_small}", bold=True, size=13)
@@ -155,60 +169,79 @@ for key, f, tf_big, tf_small, cap, exp in ROWS:
yb = lambda p, t=top, m=bmax, s=bs: t + (m - p) * s # noqa: E731
ys = lambda p, t=top, m=smax, s=ss: t + (m - p) * s # noqa: E731
# TF mare
# TF mare: zonă peste doji + confirmare, eticheta dedesubt
zx0, zx1 = BX0 + 9 * BGAP - 9, BX0 + 10 * BGAP + 9
zone(zx0, yb(big[10][1]) - 5, zx1, yb(g["dl"]) + 5, GREEN)
text((zx0 + zx1) / 2, yb(g["dl"]) + 20, "doji + confirmare:", fill=GREEN, anchor="middle", bold=True)
text((zx0 + zx1) / 2, yb(g["dl"]) + 34, "aici se decide direcția", fill=GREEN,
anchor="middle", bold=True)
hline(BX0 - 16, BX0 + 10 * BGAP + 12, yb(g["dh"]), GRAY, "3 3")
text(BX0 - 14, yb(g["dh"]) + 14, f"high doji {tf_big} {g['dh']:.2f}", fill="#666")
candles(big, BX0, BGAP, yb)
text(BX0 + 9 * BGAP, yb(g["dl"]) + 15, "doji", fill="#b06000", anchor="middle", bold=True)
text(BX0 + 10 * BGAP - 4, yb(big[10][2]) + 15, "confirmare: long permis",
fill=GREEN, bold=True)
# zoom: de la close-ul confirmării mari la open-ul primei bare mici (același preț)
# săgeata-zoom: de la close-ul confirmării mari la open-ul primei bare mici (același preț)
x1, y1 = BX0 + 10 * BGAP + 8, yb(g["conf"])
x2, y2 = SX0 - 10, ys(g["conf"])
out.append(f'<line x1="{x1:.1f}" y1="{y1:.1f}" x2="{x2:.1f}" y2="{y2:.1f}" stroke="#555" '
f'stroke-width="1.3" stroke-dasharray="5 3" marker-end="url(#pt-arr)"/>')
text(300, y1 + 2, f"zoom pe {tf_small},", fill="#555")
text(300, y1 + 16, "după confirmare", fill="#555")
text(290, y1 + 2, "apoi cobori", fill="#555")
text(290, y1 + 16, "pe graficul mic", fill="#555")
# TF mic: niveluri
y_dh, y_e, y_sl, y_tp = ys(g["dh"]), ys(g["entry"]), ys(g["sl"]), ys(g["tp"])
assert abs((y_sl - y_e) / (y_e - y_tp) - 1) < 1e-6, f"{key}: SL-intrare != intrare-TP1 în px"
# zonă peste doji-ul mic + confirmare, eticheta dedesubt
sx0, sx1 = SX0 + 8 * SGAP - 9, SX0 + 9 * SGAP + 9
zone(sx0, y_e - 6, sx1, y_sl + 5, GREEN)
text((sx0 + sx1) / 2, y_sl + 20, "doji la nivel:", fill=GREEN, anchor="middle", bold=True)
text((sx0 + sx1) / 2, y_sl + 34, "aici intri", fill=GREEN, anchor="middle", bold=True)
hline(SL_X1, SL_X2, y_dh, GRAY, "3 3")
hline(SL_X1, SL_X2, y_e, GREEN, "6 3")
hline(SL_X1, SL_X2, y_sl, RED, "6 3")
hline(SL_X1, SL_X2, y_tp, GREEN, "2 3")
text(COL_X, y_tp + 4, f"TP1 1:1 {g['tp']:.2f}", fill=GREEN, size=11)
text(COL_X, y_tp + 4, f"ținta 1:1 {g['tp']:.2f}", fill=GREEN, size=11)
text(COL_X, y_e + 4, f"intrare {g['entry']:.2f}", fill=GREEN, size=11)
text(COL_X, y_dh - 5, f"high doji {g['dh']:.2f}", fill="#666", size=11)
text(COL_X, y_sl + 12, f"SL {g['sl']:.2f}", fill=RED, size=11)
text(COL_X, y_sl + 25, "= low 4 candele", fill=RED, size=11)
text(COL_X, y_sl + 12, f"stop {g['sl']:.2f}", fill=RED, size=11)
if first:
text(COL_X, y_sl + 25, "sub ultimele", fill=RED, size=11)
text(COL_X, y_sl + 38, "4 candele", fill=RED, size=11)
candles(small, SX0, SGAP, ys)
# paranteză peste pullback-ul de 8 candele (barele 0..7)
yb8 = y_tp - 12
xa, xb = SX0 - 5, SX0 + 7 * SGAP + 5
out.append(f'<path d="M{xa:.1f},{yb8 + 6:.1f} V{yb8:.1f} H{xb:.1f} V{yb8 + 6:.1f}" '
f'fill="none" stroke="#555" stroke-width="1"/>')
text((xa + xb) / 2, yb8 - 5, "pullback: 8 candele", fill="#555", anchor="middle")
text(SX0 + 8 * SGAP + 4, y_sl + 15, "doji la nivel", fill="#b06000", anchor="end", bold=True)
text(SX0 + 9 * SGAP - 8, y_e - 5, "intrare", fill=GREEN, anchor="end", bold=True)
# text sub rând
text(20, top + PLOT_H + 50, cap.format(p=g["pct"], pb=g["b_pct"]), fill=INK, bold=True)
if first:
# paranteză peste pullback-ul de 8 candele (barele 0..7), doar pe primul rând
yb8 = y_tp - 12
xa, xb = SX0 - 5, SX0 + 7 * SGAP + 5
out.append(f'<path d="M{xa:.1f},{yb8 + 6:.1f} V{yb8:.1f} H{xb:.1f} V{yb8 + 6:.1f}" '
f'fill="none" stroke="#555" stroke-width="1"/>')
text((xa + xb) / 2, yb8 - 5, "pullback: 8 candele", fill="#555", anchor="middle")
# parantezele de stop: același setup, măsurat pe TF mare și pe TF mic
bx = zx1 + 8
bracket(bx, yb(g["b_entry"]), yb(g["b_sl"]), RED, f"stop {g['b_pct']:.2f} %".replace(".", ","))
kx = SX0 + 9 * SGAP + 14
bracket(kx, y_e, y_sl, RED, f"stop {g['pct']:.2f} %".replace(".", ","))
ratio = g["b_pct"] / g["pct"]
assert 4 <= ratio < 4.5, f"raportul stopurilor {ratio:.2f} nu e „de 4 ori”"
# săgeata dintre ele, sub rând
ya = top + PLOT_H + 58
out.append(f'<line x1="{bx + 20:.1f}" y1="{ya:.1f}" x2="{kx + 20:.1f}" y2="{ya:.1f}" '
f'stroke="{RED}" stroke-width="1.6" marker-end="url(#pt-red)"/>')
text((bx + kx) / 2 + 20, ya + 17, "același setup, stop de 4 ori mai mic", fill=RED,
anchor="middle", bold=True)
text((bx + kx) / 2 + 20, ya + 31, "→ de 4 ori mai multe acțiuni la același risc", fill=RED,
anchor="middle", bold=True)
print(f"{key}: doji mare {g['dh']:.2f}/{g['dl']:.2f} conf {g['conf']:.2f} | intrare {g['entry']:.2f} "
f"SL {g['sl']:.2f} risc {g['risk']:.2f} ({g['pct']:.2f} %) TP1 {g['tp']:.2f} | "
f"doar mare: risc {g['b_risk']:.2f} ({g['b_pct']:.2f} %)")
y0 += ROW_H
y0 += 320 if first else 270
if key != "C":
out.append(f'<line x1="20" y1="{y0 - 14:.0f}" x2="{W - 20}" y2="{y0 - 14:.0f}" stroke="#ddd"/>')
text(20, y0 + 4, "Cifre construite, aceeași formă scalată pe trei perechi.", fill="#555")
text(20, y0 + 21, "Procentele reale depind de simbol (LABU daily: stop 9 %).", fill="#555")
H = y0 + 32
H = y0 - 20
svg = (f'<svg viewBox="0 0 {W} {H:.0f}" xmlns="http://www.w3.org/2000/svg" '
f'style="width:100%;height:auto;font:12px sans-serif">\n ' + "\n ".join(out) + "\n</svg>")
assert "\n\n" not in svg
assert ".md:" not in svg and "Surse" not in svg, "trimiteri la surse în SVG"
OUT.write_text(svg, encoding="utf-8")
print(f"scris {OUT} ({W}x{H:.0f})")

View File

@@ -63,15 +63,17 @@ intrare verde; SL roșu; TP1 verde punctat.
ETICHETE
--------
Titlu rând: A „weekly → daily" B „monthly → weekly" C „daily → 60 min"
Pe graficul mare: Mark(9, "doji"), Mark(10, "confirmare: long permis").
Pe graficul mic: Mark(8, "doji la nivel"), Mark(9, "intrare"),
Level SL „SL = low 4 candele", Level TP „TP1 1:1".
Sub fiecare rând, un text de o linie:
A: „stop 1.13 % (pe weekly ar fi 4.77 %) · 8 candele = 8 zile de bursă"
B: „stop 2.59 % (pe monthly ar fi 10.85 %) · 8 candele = 8 săptămâni"
C: „stop 0.47 % (pe daily ar fi 1.98 %) · 8 candele ≈ 1,2 zile de bursă (7 bare/zi)"
Legendă jos: „Cifre construite, aceeași formă scalată pe trei perechi.
Procentele reale depind de simbol (LABU daily: stop 9 %)."
Pe graficul mare: zonă peste doji + confirmare, etichetată dedesubt
„doji + confirmare: aici se decide direcția".
Pe graficul mic: zonă peste doji + confirmare, etichetată „doji la nivel:
aici intri"; Level „stop <preț>" (pe rândul A și „sub ultimele 4 candele"),
Level „ținta 1:1 <preț>", Level „intrare <preț>".
Săgeata-zoom dintre grafice: „apoi cobori pe graficul mic".
Doar pe rândul A: paranteză de stop pe TF-ul mare („stop 4,77 %") și pe cel
mic („stop 1,13 %"), cu o săgeată între ele: „același setup, stop de 4 ori
mai mic → de 4 ori mai multe acțiuni la același risc".
Restul cifrelor (praguri, „8 candele" pe fiecare pereche, cât ții) stau în
tabelul din capitol, nu în SVG: diagrama nu repetă tabelul.
ASSERT-URI OBLIGATORII ÎN GENERATOR
-----------------------------------

View File

@@ -1,9 +1,12 @@
<svg viewBox="0 0 720 942" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif">
<defs><marker id="pt-arr" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto"><path d="M0,0 L10,5 L0,10 z" fill="#555"/></marker></defs>
<svg viewBox="0 0 720 880" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif">
<defs><marker id="pt-arr" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto"><path d="M0,0 L10,5 L0,10 z" fill="#555"/></marker><marker id="pt-red" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto"><path d="M0,0 L10,5 L0,10 z" fill="#c00"/></marker></defs>
<text x="20.0" y="22.0" fill="#333" style="font-weight:bold;font-size:14px">Aceeași regulă pe trei perechi — exemplu construit (fără ticker)</text>
<text x="20.0" y="54.0" fill="#333" style="font-weight:bold;font-size:13px">A. weekly → daily</text>
<text x="24.0" y="72.0" fill="#555">weekly: direcția</text>
<text x="380.0" y="72.0" fill="#555">daily: intrarea</text>
<rect x="175.0" y="202.5" width="34.0" height="52.5" fill="#188a3e" fill-opacity="0.10" stroke="#188a3e" stroke-width="1"/>
<text x="192.0" y="270.0" fill="#188a3e" text-anchor="middle" style="font-weight:bold">doji + confirmare:</text>
<text x="192.0" y="284.0" fill="#188a3e" text-anchor="middle" style="font-weight:bold">aici se decide direcția</text>
<line x1="24.0" y1="224.5" x2="212.0" y2="224.5" stroke="#888" stroke-width="1.5" stroke-dasharray="3 3"/>
<text x="26.0" y="238.5" fill="#666">high doji weekly 105.20</text>
<line x1="40.0" y1="90.0" x2="40.0" y2="114.7" stroke="#1a1a1a" stroke-width="1.2"/>
@@ -28,20 +31,22 @@
<rect x="179.5" y="233.8" width="9" height="1.6" fill="#c00"/>
<line x1="200.0" y1="207.5" x2="200.0" y2="237.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="195.5" y="210.6" width="9" height="24.7" fill="#188a3e"/>
<text x="184.0" y="265.0" fill="#b06000" text-anchor="middle" style="font-weight:bold">doji</text>
<text x="196.0" y="252.6" fill="#188a3e" style="font-weight:bold">confirmare: long permis</text>
<line x1="208.0" y1="210.6" x2="382.0" y2="163.1" stroke="#555" stroke-width="1.3" stroke-dasharray="5 3" marker-end="url(#pt-arr)"/>
<text x="300.0" y="212.6" fill="#555">zoom pe daily,</text>
<text x="300.0" y="226.6" fill="#555">după confirmare</text>
<text x="290.0" y="212.6" fill="#555">apoi cobori</text>
<text x="290.0" y="226.6" fill="#555">pe graficul mic</text>
<rect x="503.0" y="189.1" width="33.0" height="65.9" fill="#188a3e" fill-opacity="0.10" stroke="#188a3e" stroke-width="1"/>
<text x="519.5" y="270.0" fill="#188a3e" text-anchor="middle" style="font-weight:bold">doji la nivel:</text>
<text x="519.5" y="284.0" fill="#188a3e" text-anchor="middle" style="font-weight:bold">aici intri</text>
<line x1="380.0" y1="245.4" x2="614.0" y2="245.4" stroke="#888" stroke-width="1.5" stroke-dasharray="3 3"/>
<line x1="380.0" y1="195.1" x2="614.0" y2="195.1" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="6 3"/>
<line x1="380.0" y1="250.0" x2="614.0" y2="250.0" stroke="#c00" stroke-width="1.5" stroke-dasharray="6 3"/>
<line x1="380.0" y1="140.3" x2="614.0" y2="140.3" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="2 3"/>
<text x="620.0" y="144.3" fill="#188a3e" style="font-size:11px">TP1 1:1 107.50</text>
<text x="620.0" y="144.3" fill="#188a3e" style="font-size:11px">ținta 1:1 107.50</text>
<text x="620.0" y="199.1" fill="#188a3e" style="font-size:11px">intrare 106.30</text>
<text x="620.0" y="240.4" fill="#666" style="font-size:11px">high doji 105.20</text>
<text x="620.0" y="262.0" fill="#c00" style="font-size:11px">SL 105.10</text>
<text x="620.0" y="275.0" fill="#c00" style="font-size:11px">= low 4 candele</text>
<text x="620.0" y="262.0" fill="#c00" style="font-size:11px">stop 105.10</text>
<text x="620.0" y="275.0" fill="#c00" style="font-size:11px">sub ultimele</text>
<text x="620.0" y="288.0" fill="#c00" style="font-size:11px">4 candele</text>
<line x1="392.0" y1="154.0" x2="392.0" y2="190.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="387.5" y="163.1" width="9" height="18.3" fill="#c00"/>
<line x1="407.0" y1="172.3" x2="407.0" y2="208.9" stroke="#1a1a1a" stroke-width="1.2"/>
@@ -74,163 +79,161 @@
<rect x="597.5" y="94.6" width="9" height="27.4" fill="#188a3e"/>
<path d="M387.0,134.3 V128.3 H502.0 V134.3" fill="none" stroke="#555" stroke-width="1"/>
<text x="444.5" y="123.3" fill="#555" text-anchor="middle">pullback: 8 candele</text>
<text x="516.0" y="265.0" fill="#b06000" text-anchor="end" style="font-weight:bold">doji la nivel</text>
<text x="519.0" y="190.1" fill="#188a3e" text-anchor="end" style="font-weight:bold">intrare</text>
<text x="20.0" y="300.0" fill="#333" style="font-weight:bold">stop 1.13 % (pe weekly ar fi 4.77 %) · 8 candele = 8 zile de bursă</text>
<line x1="20" y1="316" x2="700" y2="316" stroke="#ddd"/>
<text x="20.0" y="344.0" fill="#333" style="font-weight:bold;font-size:13px">B. monthly → weekly</text>
<text x="24.0" y="362.0" fill="#555">monthly: direcția</text>
<text x="380.0" y="362.0" fill="#555">weekly: intrarea</text>
<line x1="24.0" y1="514.5" x2="212.0" y2="514.5" stroke="#888" stroke-width="1.5" stroke-dasharray="3 3"/>
<text x="26.0" y="528.5" fill="#666">high doji monthly 113.00</text>
<line x1="40.0" y1="380.0" x2="40.0" y2="404.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="35.5" y="384.6" width="9" height="15.5" fill="#c00"/>
<line x1="56.0" y1="396.2" x2="56.0" y2="423.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="51.5" y="400.1" width="9" height="19.3" fill="#c00"/>
<line x1="72.0" y1="407.8" x2="72.0" y2="422.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="67.5" y="412.5" width="9" height="7.0" fill="#188a3e"/>
<line x1="88.0" y1="409.4" x2="88.0" y2="444.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="83.5" y="412.5" width="9" height="27.8" fill="#c00"/>
<line x1="104.0" y1="436.4" x2="104.0" y2="465.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="99.5" y="440.3" width="9" height="21.6" fill="#c00"/>
<line x1="120.0" y1="451.1" x2="120.0" y2="465.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="115.5" y="455.0" width="9" height="7.0" fill="#188a3e"/>
<line x1="136.0" y1="452.7" x2="136.0" y2="484.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="131.5" y="455.0" width="9" height="25.5" fill="#c00"/>
<line x1="152.0" y1="477.4" x2="152.0" y2="506.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="147.5" y="480.5" width="9" height="21.6" fill="#c00"/>
<line x1="168.0" y1="499.0" x2="168.0" y2="526.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="163.5" y="502.1" width="9" height="21.6" fill="#c00"/>
<line x1="184.0" y1="514.5" x2="184.0" y2="540.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="179.5" y="523.8" width="9" height="1.6" fill="#c00"/>
<line x1="200.0" y1="497.5" x2="200.0" y2="527.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="195.5" y="500.6" width="9" height="24.7" fill="#188a3e"/>
<text x="184.0" y="555.0" fill="#b06000" text-anchor="middle" style="font-weight:bold">doji</text>
<text x="196.0" y="542.6" fill="#188a3e" style="font-weight:bold">confirmare: long permis</text>
<line x1="208.0" y1="500.6" x2="382.0" y2="453.1" stroke="#555" stroke-width="1.3" stroke-dasharray="5 3" marker-end="url(#pt-arr)"/>
<text x="300.0" y="502.6" fill="#555">zoom pe weekly,</text>
<text x="300.0" y="516.6" fill="#555">după confirmare</text>
<line x1="380.0" y1="535.4" x2="614.0" y2="535.4" stroke="#888" stroke-width="1.5" stroke-dasharray="3 3"/>
<line x1="380.0" y1="485.1" x2="614.0" y2="485.1" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="6 3"/>
<line x1="380.0" y1="540.0" x2="614.0" y2="540.0" stroke="#c00" stroke-width="1.5" stroke-dasharray="6 3"/>
<line x1="380.0" y1="430.3" x2="614.0" y2="430.3" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="2 3"/>
<text x="620.0" y="434.3" fill="#188a3e" style="font-size:11px">TP1 1:1 118.75</text>
<text x="620.0" y="489.1" fill="#188a3e" style="font-size:11px">intrare 115.75</text>
<text x="620.0" y="530.4" fill="#666" style="font-size:11px">high doji 113.00</text>
<text x="620.0" y="552.0" fill="#c00" style="font-size:11px">SL 112.75</text>
<text x="620.0" y="565.0" fill="#c00" style="font-size:11px">= low 4 candele</text>
<line x1="392.0" y1="444.0" x2="392.0" y2="480.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="387.5" y="453.1" width="9" height="18.3" fill="#c00"/>
<line x1="407.0" y1="462.3" x2="407.0" y2="498.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="402.5" y="471.4" width="9" height="22.9" fill="#c00"/>
<line x1="422.0" y1="471.4" x2="422.0" y2="501.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="417.5" y="480.6" width="9" height="13.7" fill="#188a3e"/>
<line x1="437.0" y1="476.0" x2="437.0" y2="508.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="432.5" y="480.6" width="9" height="22.9" fill="#c00"/>
<line x1="452.0" y1="498.9" x2="452.0" y2="521.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="447.5" y="503.4" width="9" height="13.7" fill="#c00"/>
<line x1="467.0" y1="501.1" x2="467.0" y2="521.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="462.5" y="508.0" width="9" height="9.1" fill="#188a3e"/>
<line x1="482.0" y1="503.4" x2="482.0" y2="526.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="477.5" y="508.0" width="9" height="13.7" fill="#c00"/>
<line x1="497.0" y1="517.1" x2="497.0" y2="533.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="492.5" y="521.7" width="9" height="6.9" fill="#c00"/>
<line x1="512.0" y1="510.2" x2="512.0" y2="540.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="507.5" y="526.3" width="9" height="2.4" fill="#188a3e"/>
<line x1="527.0" y1="480.6" x2="527.0" y2="530.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="522.5" y="485.1" width="9" height="41.1" fill="#188a3e"/>
<line x1="542.0" y1="453.1" x2="542.0" y2="489.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="537.5" y="457.7" width="9" height="27.4" fill="#188a3e"/>
<line x1="557.0" y1="430.3" x2="557.0" y2="466.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="552.5" y="434.9" width="9" height="22.9" fill="#188a3e"/>
<line x1="572.0" y1="427.9" x2="572.0" y2="453.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="567.5" y="434.9" width="9" height="9.1" fill="#c00"/>
<line x1="587.0" y1="407.4" x2="587.0" y2="448.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="582.5" y="412.0" width="9" height="32.0" fill="#188a3e"/>
<line x1="602.0" y1="380.0" x2="602.0" y2="416.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="597.5" y="384.6" width="9" height="27.4" fill="#188a3e"/>
<path d="M387.0,424.3 V418.3 H502.0 V424.3" fill="none" stroke="#555" stroke-width="1"/>
<text x="444.5" y="413.3" fill="#555" text-anchor="middle">pullback: 8 candele</text>
<text x="516.0" y="555.0" fill="#b06000" text-anchor="end" style="font-weight:bold">doji la nivel</text>
<text x="519.0" y="480.1" fill="#188a3e" text-anchor="end" style="font-weight:bold">intrare</text>
<text x="20.0" y="590.0" fill="#333" style="font-weight:bold">stop 2.59 % (pe monthly ar fi 10.85 %) · 8 candele = 8 săptămâni</text>
<line x1="20" y1="606" x2="700" y2="606" stroke="#ddd"/>
<text x="20.0" y="634.0" fill="#333" style="font-weight:bold;font-size:13px">C. daily → 60 min</text>
<text x="24.0" y="652.0" fill="#555">daily: direcția</text>
<text x="380.0" y="652.0" fill="#555">60 min: intrarea</text>
<line x1="24.0" y1="804.5" x2="212.0" y2="804.5" stroke="#888" stroke-width="1.5" stroke-dasharray="3 3"/>
<text x="26.0" y="818.5" fill="#666">high doji daily 102.08</text>
<line x1="40.0" y1="670.0" x2="40.0" y2="694.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="35.5" y="674.6" width="9" height="15.5" fill="#c00"/>
<line x1="56.0" y1="686.2" x2="56.0" y2="713.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="51.5" y="690.1" width="9" height="19.3" fill="#c00"/>
<line x1="72.0" y1="697.8" x2="72.0" y2="712.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="67.5" y="702.5" width="9" height="7.0" fill="#188a3e"/>
<line x1="88.0" y1="699.4" x2="88.0" y2="734.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="83.5" y="702.5" width="9" height="27.8" fill="#c00"/>
<line x1="104.0" y1="726.4" x2="104.0" y2="755.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="99.5" y="730.3" width="9" height="21.6" fill="#c00"/>
<line x1="120.0" y1="741.1" x2="120.0" y2="755.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="115.5" y="745.0" width="9" height="7.0" fill="#188a3e"/>
<line x1="136.0" y1="742.7" x2="136.0" y2="774.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="131.5" y="745.0" width="9" height="25.5" fill="#c00"/>
<line x1="152.0" y1="767.4" x2="152.0" y2="796.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="147.5" y="770.5" width="9" height="21.6" fill="#c00"/>
<line x1="168.0" y1="789.0" x2="168.0" y2="816.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="163.5" y="792.1" width="9" height="21.6" fill="#c00"/>
<line x1="184.0" y1="804.5" x2="184.0" y2="830.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="179.5" y="813.8" width="9" height="1.6" fill="#c00"/>
<line x1="200.0" y1="787.5" x2="200.0" y2="817.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="195.5" y="790.6" width="9" height="24.7" fill="#188a3e"/>
<text x="184.0" y="845.0" fill="#b06000" text-anchor="middle" style="font-weight:bold">doji</text>
<text x="196.0" y="832.6" fill="#188a3e" style="font-weight:bold">confirmare: long permis</text>
<line x1="208.0" y1="790.6" x2="382.0" y2="743.1" stroke="#555" stroke-width="1.3" stroke-dasharray="5 3" marker-end="url(#pt-arr)"/>
<text x="300.0" y="792.6" fill="#555">zoom pe 60 min,</text>
<text x="300.0" y="806.6" fill="#555">după confirmare</text>
<line x1="380.0" y1="825.4" x2="614.0" y2="825.4" stroke="#888" stroke-width="1.5" stroke-dasharray="3 3"/>
<line x1="380.0" y1="775.1" x2="614.0" y2="775.1" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="6 3"/>
<line x1="380.0" y1="830.0" x2="614.0" y2="830.0" stroke="#c00" stroke-width="1.5" stroke-dasharray="6 3"/>
<line x1="380.0" y1="720.3" x2="614.0" y2="720.3" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="2 3"/>
<text x="620.0" y="724.3" fill="#188a3e" style="font-size:11px">TP1 1:1 103.00</text>
<text x="620.0" y="779.1" fill="#188a3e" style="font-size:11px">intrare 102.52</text>
<text x="620.0" y="820.4" fill="#666" style="font-size:11px">high doji 102.08</text>
<text x="620.0" y="842.0" fill="#c00" style="font-size:11px">SL 102.04</text>
<text x="620.0" y="855.0" fill="#c00" style="font-size:11px">= low 4 candele</text>
<line x1="392.0" y1="734.0" x2="392.0" y2="770.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="387.5" y="743.1" width="9" height="18.3" fill="#c00"/>
<line x1="407.0" y1="752.3" x2="407.0" y2="788.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="402.5" y="761.4" width="9" height="22.9" fill="#c00"/>
<line x1="422.0" y1="761.4" x2="422.0" y2="791.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="417.5" y="770.6" width="9" height="13.7" fill="#188a3e"/>
<line x1="437.0" y1="766.0" x2="437.0" y2="798.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="432.5" y="770.6" width="9" height="22.9" fill="#c00"/>
<line x1="452.0" y1="788.9" x2="452.0" y2="811.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="447.5" y="793.4" width="9" height="13.7" fill="#c00"/>
<line x1="467.0" y1="791.1" x2="467.0" y2="811.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="462.5" y="798.0" width="9" height="9.1" fill="#188a3e"/>
<line x1="482.0" y1="793.4" x2="482.0" y2="816.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="477.5" y="798.0" width="9" height="13.7" fill="#c00"/>
<line x1="497.0" y1="807.1" x2="497.0" y2="823.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="492.5" y="811.7" width="9" height="6.9" fill="#c00"/>
<line x1="512.0" y1="800.3" x2="512.0" y2="830.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="507.5" y="816.3" width="9" height="2.3" fill="#188a3e"/>
<line x1="527.0" y1="770.6" x2="527.0" y2="820.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="522.5" y="775.1" width="9" height="41.1" fill="#188a3e"/>
<line x1="542.0" y1="743.1" x2="542.0" y2="779.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="537.5" y="747.7" width="9" height="27.4" fill="#188a3e"/>
<line x1="557.0" y1="720.3" x2="557.0" y2="756.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="552.5" y="724.9" width="9" height="22.9" fill="#188a3e"/>
<line x1="572.0" y1="718.0" x2="572.0" y2="743.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="567.5" y="724.9" width="9" height="9.1" fill="#c00"/>
<line x1="587.0" y1="697.4" x2="587.0" y2="738.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="582.5" y="702.0" width="9" height="32.0" fill="#188a3e"/>
<line x1="602.0" y1="670.0" x2="602.0" y2="706.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="597.5" y="674.6" width="9" height="27.4" fill="#188a3e"/>
<path d="M387.0,714.3 V708.3 H502.0 V714.3" fill="none" stroke="#555" stroke-width="1"/>
<text x="444.5" y="703.3" fill="#555" text-anchor="middle">pullback: 8 candele</text>
<text x="516.0" y="845.0" fill="#b06000" text-anchor="end" style="font-weight:bold">doji la nivel</text>
<text x="519.0" y="770.1" fill="#188a3e" text-anchor="end" style="font-weight:bold">intrare</text>
<text x="20.0" y="880.0" fill="#333" style="font-weight:bold">stop 0.47 % (pe daily ar fi 1.98 %) · 8 candele ≈ 1,2 zile de bursă (7 bare/zi)</text>
<text x="20.0" y="914.0" fill="#555">Cifre construite, aceeași formă scalată pe trei perechi.</text>
<text x="20.0" y="931.0" fill="#555">Procentele reale depind de simbol (LABU daily: stop 9 %).</text>
<path d="M212.0,210.6 H217.0 V250.0 H212.0" fill="none" stroke="#c00" stroke-width="1.6"/>
<text x="222.0" y="234.3" fill="#c00" style="font-weight:bold">stop 4,77 %</text>
<path d="M536.0,195.1 H541.0 V250.0 H536.0" fill="none" stroke="#c00" stroke-width="1.6"/>
<text x="546.0" y="226.6" fill="#c00" style="font-weight:bold">stop 1,13 %</text>
<line x1="237.0" y1="308.0" x2="561.0" y2="308.0" stroke="#c00" stroke-width="1.6" marker-end="url(#pt-red)"/>
<text x="399.0" y="325.0" fill="#c00" text-anchor="middle" style="font-weight:bold">același setup, stop de 4 ori mai mic</text>
<text x="399.0" y="339.0" fill="#c00" text-anchor="middle" style="font-weight:bold">→ de 4 ori mai multe acțiuni la același risc</text>
<line x1="20" y1="346" x2="700" y2="346" stroke="#ddd"/>
<text x="20.0" y="374.0" fill="#333" style="font-weight:bold;font-size:13px">B. monthly → weekly</text>
<text x="24.0" y="392.0" fill="#555">monthly: direcția</text>
<text x="380.0" y="392.0" fill="#555">weekly: intrarea</text>
<rect x="175.0" y="522.5" width="34.0" height="52.5" fill="#188a3e" fill-opacity="0.10" stroke="#188a3e" stroke-width="1"/>
<text x="192.0" y="590.0" fill="#188a3e" text-anchor="middle" style="font-weight:bold">doji + confirmare:</text>
<text x="192.0" y="604.0" fill="#188a3e" text-anchor="middle" style="font-weight:bold">aici se decide direcția</text>
<line x1="24.0" y1="544.5" x2="212.0" y2="544.5" stroke="#888" stroke-width="1.5" stroke-dasharray="3 3"/>
<text x="26.0" y="558.5" fill="#666">high doji monthly 113.00</text>
<line x1="40.0" y1="410.0" x2="40.0" y2="434.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="35.5" y="414.6" width="9" height="15.5" fill="#c00"/>
<line x1="56.0" y1="426.2" x2="56.0" y2="453.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="51.5" y="430.1" width="9" height="19.3" fill="#c00"/>
<line x1="72.0" y1="437.8" x2="72.0" y2="452.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="67.5" y="442.5" width="9" height="7.0" fill="#188a3e"/>
<line x1="88.0" y1="439.4" x2="88.0" y2="474.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="83.5" y="442.5" width="9" height="27.8" fill="#c00"/>
<line x1="104.0" y1="466.4" x2="104.0" y2="495.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="99.5" y="470.3" width="9" height="21.6" fill="#c00"/>
<line x1="120.0" y1="481.1" x2="120.0" y2="495.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="115.5" y="485.0" width="9" height="7.0" fill="#188a3e"/>
<line x1="136.0" y1="482.7" x2="136.0" y2="514.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="131.5" y="485.0" width="9" height="25.5" fill="#c00"/>
<line x1="152.0" y1="507.4" x2="152.0" y2="536.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="147.5" y="510.5" width="9" height="21.6" fill="#c00"/>
<line x1="168.0" y1="529.0" x2="168.0" y2="556.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="163.5" y="532.1" width="9" height="21.6" fill="#c00"/>
<line x1="184.0" y1="544.5" x2="184.0" y2="570.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="179.5" y="553.8" width="9" height="1.6" fill="#c00"/>
<line x1="200.0" y1="527.5" x2="200.0" y2="557.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="195.5" y="530.6" width="9" height="24.7" fill="#188a3e"/>
<line x1="208.0" y1="530.6" x2="382.0" y2="483.1" stroke="#555" stroke-width="1.3" stroke-dasharray="5 3" marker-end="url(#pt-arr)"/>
<text x="290.0" y="532.6" fill="#555">apoi cobori</text>
<text x="290.0" y="546.6" fill="#555">pe graficul mic</text>
<rect x="503.0" y="509.1" width="33.0" height="65.9" fill="#188a3e" fill-opacity="0.10" stroke="#188a3e" stroke-width="1"/>
<text x="519.5" y="590.0" fill="#188a3e" text-anchor="middle" style="font-weight:bold">doji la nivel:</text>
<text x="519.5" y="604.0" fill="#188a3e" text-anchor="middle" style="font-weight:bold">aici intri</text>
<line x1="380.0" y1="565.4" x2="614.0" y2="565.4" stroke="#888" stroke-width="1.5" stroke-dasharray="3 3"/>
<line x1="380.0" y1="515.1" x2="614.0" y2="515.1" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="6 3"/>
<line x1="380.0" y1="570.0" x2="614.0" y2="570.0" stroke="#c00" stroke-width="1.5" stroke-dasharray="6 3"/>
<line x1="380.0" y1="460.3" x2="614.0" y2="460.3" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="2 3"/>
<text x="620.0" y="464.3" fill="#188a3e" style="font-size:11px">ținta 1:1 118.75</text>
<text x="620.0" y="519.1" fill="#188a3e" style="font-size:11px">intrare 115.75</text>
<text x="620.0" y="560.4" fill="#666" style="font-size:11px">high doji 113.00</text>
<text x="620.0" y="582.0" fill="#c00" style="font-size:11px">stop 112.75</text>
<line x1="392.0" y1="474.0" x2="392.0" y2="510.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="387.5" y="483.1" width="9" height="18.3" fill="#c00"/>
<line x1="407.0" y1="492.3" x2="407.0" y2="528.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="402.5" y="501.4" width="9" height="22.9" fill="#c00"/>
<line x1="422.0" y1="501.4" x2="422.0" y2="531.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="417.5" y="510.6" width="9" height="13.7" fill="#188a3e"/>
<line x1="437.0" y1="506.0" x2="437.0" y2="538.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="432.5" y="510.6" width="9" height="22.9" fill="#c00"/>
<line x1="452.0" y1="528.9" x2="452.0" y2="551.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="447.5" y="533.4" width="9" height="13.7" fill="#c00"/>
<line x1="467.0" y1="531.1" x2="467.0" y2="551.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="462.5" y="538.0" width="9" height="9.1" fill="#188a3e"/>
<line x1="482.0" y1="533.4" x2="482.0" y2="556.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="477.5" y="538.0" width="9" height="13.7" fill="#c00"/>
<line x1="497.0" y1="547.1" x2="497.0" y2="563.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="492.5" y="551.7" width="9" height="6.9" fill="#c00"/>
<line x1="512.0" y1="540.2" x2="512.0" y2="570.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="507.5" y="556.3" width="9" height="2.4" fill="#188a3e"/>
<line x1="527.0" y1="510.6" x2="527.0" y2="560.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="522.5" y="515.1" width="9" height="41.1" fill="#188a3e"/>
<line x1="542.0" y1="483.1" x2="542.0" y2="519.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="537.5" y="487.7" width="9" height="27.4" fill="#188a3e"/>
<line x1="557.0" y1="460.3" x2="557.0" y2="496.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="552.5" y="464.9" width="9" height="22.9" fill="#188a3e"/>
<line x1="572.0" y1="457.9" x2="572.0" y2="483.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="567.5" y="464.9" width="9" height="9.1" fill="#c00"/>
<line x1="587.0" y1="437.4" x2="587.0" y2="478.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="582.5" y="442.0" width="9" height="32.0" fill="#188a3e"/>
<line x1="602.0" y1="410.0" x2="602.0" y2="446.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="597.5" y="414.6" width="9" height="27.4" fill="#188a3e"/>
<line x1="20" y1="616" x2="700" y2="616" stroke="#ddd"/>
<text x="20.0" y="644.0" fill="#333" style="font-weight:bold;font-size:13px">C. daily → 60 min</text>
<text x="24.0" y="662.0" fill="#555">daily: direcția</text>
<text x="380.0" y="662.0" fill="#555">60 min: intrarea</text>
<rect x="175.0" y="792.5" width="34.0" height="52.5" fill="#188a3e" fill-opacity="0.10" stroke="#188a3e" stroke-width="1"/>
<text x="192.0" y="860.0" fill="#188a3e" text-anchor="middle" style="font-weight:bold">doji + confirmare:</text>
<text x="192.0" y="874.0" fill="#188a3e" text-anchor="middle" style="font-weight:bold">aici se decide direcția</text>
<line x1="24.0" y1="814.5" x2="212.0" y2="814.5" stroke="#888" stroke-width="1.5" stroke-dasharray="3 3"/>
<text x="26.0" y="828.5" fill="#666">high doji daily 102.08</text>
<line x1="40.0" y1="680.0" x2="40.0" y2="704.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="35.5" y="684.6" width="9" height="15.5" fill="#c00"/>
<line x1="56.0" y1="696.2" x2="56.0" y2="723.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="51.5" y="700.1" width="9" height="19.3" fill="#c00"/>
<line x1="72.0" y1="707.8" x2="72.0" y2="722.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="67.5" y="712.5" width="9" height="7.0" fill="#188a3e"/>
<line x1="88.0" y1="709.4" x2="88.0" y2="744.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="83.5" y="712.5" width="9" height="27.8" fill="#c00"/>
<line x1="104.0" y1="736.4" x2="104.0" y2="765.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="99.5" y="740.3" width="9" height="21.6" fill="#c00"/>
<line x1="120.0" y1="751.1" x2="120.0" y2="765.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="115.5" y="755.0" width="9" height="7.0" fill="#188a3e"/>
<line x1="136.0" y1="752.7" x2="136.0" y2="784.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="131.5" y="755.0" width="9" height="25.5" fill="#c00"/>
<line x1="152.0" y1="777.4" x2="152.0" y2="806.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="147.5" y="780.5" width="9" height="21.6" fill="#c00"/>
<line x1="168.0" y1="799.0" x2="168.0" y2="826.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="163.5" y="802.1" width="9" height="21.6" fill="#c00"/>
<line x1="184.0" y1="814.5" x2="184.0" y2="840.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="179.5" y="823.8" width="9" height="1.6" fill="#c00"/>
<line x1="200.0" y1="797.5" x2="200.0" y2="827.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="195.5" y="800.6" width="9" height="24.7" fill="#188a3e"/>
<line x1="208.0" y1="800.6" x2="382.0" y2="753.1" stroke="#555" stroke-width="1.3" stroke-dasharray="5 3" marker-end="url(#pt-arr)"/>
<text x="290.0" y="802.6" fill="#555">apoi cobori</text>
<text x="290.0" y="816.6" fill="#555">pe graficul mic</text>
<rect x="503.0" y="779.1" width="33.0" height="65.9" fill="#188a3e" fill-opacity="0.10" stroke="#188a3e" stroke-width="1"/>
<text x="519.5" y="860.0" fill="#188a3e" text-anchor="middle" style="font-weight:bold">doji la nivel:</text>
<text x="519.5" y="874.0" fill="#188a3e" text-anchor="middle" style="font-weight:bold">aici intri</text>
<line x1="380.0" y1="835.4" x2="614.0" y2="835.4" stroke="#888" stroke-width="1.5" stroke-dasharray="3 3"/>
<line x1="380.0" y1="785.1" x2="614.0" y2="785.1" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="6 3"/>
<line x1="380.0" y1="840.0" x2="614.0" y2="840.0" stroke="#c00" stroke-width="1.5" stroke-dasharray="6 3"/>
<line x1="380.0" y1="730.3" x2="614.0" y2="730.3" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="2 3"/>
<text x="620.0" y="734.3" fill="#188a3e" style="font-size:11px">ținta 1:1 103.00</text>
<text x="620.0" y="789.1" fill="#188a3e" style="font-size:11px">intrare 102.52</text>
<text x="620.0" y="830.4" fill="#666" style="font-size:11px">high doji 102.08</text>
<text x="620.0" y="852.0" fill="#c00" style="font-size:11px">stop 102.04</text>
<line x1="392.0" y1="744.0" x2="392.0" y2="780.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="387.5" y="753.1" width="9" height="18.3" fill="#c00"/>
<line x1="407.0" y1="762.3" x2="407.0" y2="798.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="402.5" y="771.4" width="9" height="22.9" fill="#c00"/>
<line x1="422.0" y1="771.4" x2="422.0" y2="801.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="417.5" y="780.6" width="9" height="13.7" fill="#188a3e"/>
<line x1="437.0" y1="776.0" x2="437.0" y2="808.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="432.5" y="780.6" width="9" height="22.9" fill="#c00"/>
<line x1="452.0" y1="798.9" x2="452.0" y2="821.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="447.5" y="803.4" width="9" height="13.7" fill="#c00"/>
<line x1="467.0" y1="801.1" x2="467.0" y2="821.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="462.5" y="808.0" width="9" height="9.1" fill="#188a3e"/>
<line x1="482.0" y1="803.4" x2="482.0" y2="826.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="477.5" y="808.0" width="9" height="13.7" fill="#c00"/>
<line x1="497.0" y1="817.1" x2="497.0" y2="833.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="492.5" y="821.7" width="9" height="6.9" fill="#c00"/>
<line x1="512.0" y1="810.3" x2="512.0" y2="840.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="507.5" y="826.3" width="9" height="2.3" fill="#188a3e"/>
<line x1="527.0" y1="780.6" x2="527.0" y2="830.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="522.5" y="785.1" width="9" height="41.1" fill="#188a3e"/>
<line x1="542.0" y1="753.1" x2="542.0" y2="789.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="537.5" y="757.7" width="9" height="27.4" fill="#188a3e"/>
<line x1="557.0" y1="730.3" x2="557.0" y2="766.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="552.5" y="734.9" width="9" height="22.9" fill="#188a3e"/>
<line x1="572.0" y1="728.0" x2="572.0" y2="753.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="567.5" y="734.9" width="9" height="9.1" fill="#c00"/>
<line x1="587.0" y1="707.4" x2="587.0" y2="748.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="582.5" y="712.0" width="9" height="32.0" fill="#188a3e"/>
<line x1="602.0" y1="680.0" x2="602.0" y2="716.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="597.5" y="684.6" width="9" height="27.4" fill="#188a3e"/>
</svg>

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

@@ -27,24 +27,21 @@ WIDTHS = [300, 280, 260, 240, 220, 200]
# (linii în cutie, [(tip, text)]); tip: "n" = notă gri, "c" = capcană
BOXES = [
(["Univers:", "All Stocks (~13.000)", "S&P 500 · Russell 3000"],
[("n", "mai mare = găsește mai mult, durează mai mult")]),
[("n", "mai mare = mai mulți candidați, scanare mai lentă")]),
(["Trigger: jbtgrshdATM", "BDATM = 0", "(Sell Doji: SDATM = 0)"],
[("c", "Interval = TF-ul scanerului, setat manual"),
("c", "0 = ultima candelă închisă; 1 = cu o zi în urmă")]),
[("c", "intervalul nu se aliniază singur cu TF-ul: îl pui de mână"),
("c", "vede doar candela închisă: daily rulat la prânz arată ieri")]),
(["Nivel: RSV1ATM", "% of PP ≤ 0.5 (60 min)", "% of PP ≤ 2 (daily)"],
[("n", "Pivot Interval: 2 = weekly (pe 60 min), 3 = monthly (pe daily)"),
("c", "RS/SR = 1 la filtrare; cu 100, pragul se scrie ×100")]),
("c", "RS/SR: 1 la filtrare, 100 doar la afișare")]),
(["Lichiditate: Volume Colors", "Average Volume ≥ 500.000",
"Average Length = 10"],
[("n", "volum daily, indiferent de TF-ul scanerului")]),
(["Opțional:", "Since Bear ≥ 8", "Bull Reversal = 1", "RVOL doar Display"],
[("c", "Bear Reversal e selectat implicit — comută pe Bull"),
("c", "în zile extreme, pragurile rigide golesc lista")]),
[("c", "pornește pe Bear Reversal: comută pe Bull")]),
(["Lista de candidați", "→ o verifici pe grafic", "(pașii 2-6).",
"Scanerul nu e undă verde."], []),
]
FOOT = ("Delay: scanerul vede candela închisă — daily rulat la 12:00 "
"arată triggerul de ieri.")
def est_w(s, fs, bold=False):
@@ -94,10 +91,18 @@ for i, (lines, notes) in enumerate(BOXES):
assert x0 >= x + 6 and x1 <= x + w - 6, f"textul nu încape în cutia {i}: {ln!r}"
if note_lines:
assert x + w + 24 <= NOTE_X, f"cutia {i} prea aproape de note"
svg.append(f'<line x1="{x + w + 4:g}" y1="{y + h / 2:g}" x2="{NOTE_X - 8}" '
f'y2="{y + h / 2:g}" stroke="#bbbbbb" stroke-dasharray="3 3"/>')
ny = y + (h - n_note * LH) / 2 + 12
for group in note_lines:
kind0 = group[0][0]
cy = ny - 4
# capcana arată spre filtrul pe care îl strică (vârful pe cutie)
col = RED if kind0 == "c" else "#bbbbbb"
dash = '' if kind0 == "c" else ' stroke-dasharray="3 3"'
svg.append(f'<line x1="{NOTE_X - 10}" y1="{cy:g}" x2="{x + w + 12:g}" y2="{cy:g}" '
f'stroke="{col}" stroke-width="{1.6 if kind0 == "c" else 1}"{dash}/>')
if kind0 == "c":
svg.append(f'<path d="M {x + w + 4:g} {cy:g} L {x + w + 13:g} {cy - 4:g} '
f'L {x + w + 13:g} {cy + 4:g} Z" fill="{RED}"/>')
for kind, ln in group:
put(NOTE_X, ny, ln, NOTE_FS, RED if kind == "c" else GRAY)
ny += LH
@@ -108,10 +113,7 @@ for i, (lines, notes) in enumerate(BOXES):
f'L {BOX_CX} {y + 14:g} Z" fill="{BLUE}"/>')
y += 18
y += 30
for j, ln in enumerate(textwrap.wrap(FOOT, 88)):
put(20, y + j * LH, ln, 12.5, BLACK)
H = int(y + LH + 20)
H = int(y + 20)
# ------------------------------------------------------------------ verificare
assert all(a > b for a, b in zip(WIDTHS, WIDTHS[1:])), "lățimile nu scad strict"
@@ -133,6 +135,7 @@ out = "\n".join([
f'ordinea filtrelor și capcanele">',
f'<rect x="0" y="0" width="{W}" height="{H}" fill="#ffffff"/>',
*svg, "</svg>"]) + "\n"
assert ".md:" not in out and "Surse" not in out, "trimiteri la surse în SVG"
assert "\n\n" not in out and not any(not ln.strip() for ln in out.splitlines()), "linie goală"
OUT.write_text(out, encoding="utf-8")
print(f"scris {OUT} ({W}x{H}), verificare OK")

View File

@@ -5,28 +5,28 @@ destinație: summaries/17_STRATEGII/01_buy_doji.md, Pasul 1
cheie markdown: <!-- DIAGRAMA: scaner -->
titlu SVG: „Scanerul Buy Doji în TradeStation — ordinea filtrelor și capcanele"
stil: cutii dreptunghiulare stivuite, tot mai înguste (pâlnie), lățime 640;
în dreapta fiecărei cutii, o notă roșie „capcană" unde există.
în dreapta fiecărei cutii, o notă roșie „capcană" unde există,
legată de cutie printr-o săgeată roșie (vârful pe filtrul
pe care îl strică).
Fără cifre de „câte simboluri rămân" — materialul nu le dă.
CUTIILE (text exact, de sus în jos)
-----------------------------------
1. „Univers: All Stocks (~13.000) · S&P 500 · Russell 3000"
notă gri: „mai mare = găsește mai mult, durează mai mult"
notă gri: „mai mare = mai mulți candidați, scanare mai lentă"
2. „Trigger: jbtgrshdATM → BDATM = 0 (Sell Doji: SDATM = 0)"
capcană: „Interval = TF-ul scanerului, setat manual"
capcană: „0 = ultima candelă închisă; 1 = cu o zi în urmă"
capcană: „intervalul nu se aliniază singur cu TF-ul: îl pui de mână"
capcană: „vede doar candela închisă: daily rulat la prânz arată ieri"
3. „Nivel: RSV1ATM → % of PP ≤ 0.5 (60 min) / ≤ 2 (daily)"
notă: „Pivot Interval: 2 = weekly (pe 60 min), 3 = monthly (pe daily)"
capcană: „RS/SR = 1 la filtrare; cu 100, pragul se scrie ×100"
capcană: „RS/SR: 1 la filtrare, 100 doar la afișare"
4. „Lichiditate: Volume Colors → Average Volume ≥ 500.000, Average Length = 10"
notă: „volum daily, indiferent de TF-ul scanerului"
5. „Opțional: Since Bear ≥ 8 · Bull Reversal = 1 · RVOL doar Display"
capcană: „Bear Reversal e selectat implicit — comută pe Bull"
capcană: „în zile extreme, pragurile rigide golesc lista"
capcană: „pornește pe Bear Reversal: comută pe Bull"
6. (cutie verde, cea mai îngustă) „Lista de candidați → o verifici pe grafic
(pașii 2-6). Scanerul nu e undă verde."
Sub pâlnie, o linie: „Delay: scanerul vede candela închisă — daily rulat la
12:00 arată triggerul de ieri."
Fără linie de subsol: întârzierea scanerului e capcana de la cutia 2.
ASSERT-URI
----------

View File

@@ -1,57 +1,60 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 723" width="640" height="723" role="img" aria-label="Scanerul Buy Doji în TradeStation — ordinea filtrelor și capcanele">
<rect x="0" y="0" width="640" height="723" fill="#ffffff"/>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 670" width="640" height="670" role="img" aria-label="Scanerul Buy Doji în TradeStation — ordinea filtrelor și capcanele">
<rect x="0" y="0" width="640" height="670" fill="#ffffff"/>
<text x="320" y="30" font-family="system-ui, sans-serif" font-size="18" font-weight="700" fill="#000000" text-anchor="middle">Scanerul Buy Doji în TradeStation</text>
<text x="320" y="52" font-family="system-ui, sans-serif" font-size="13" font-weight="400" fill="#666666" text-anchor="middle">ordinea filtrelor și capcanele</text>
<rect x="15" y="76" width="300" height="68" rx="6" fill="#eef3fb" stroke="#1a5fb4" stroke-width="1.5"/>
<text x="165" y="98" font-family="system-ui, sans-serif" font-size="13" font-weight="700" fill="#000000" text-anchor="middle">Univers:</text>
<text x="165" y="114" font-family="system-ui, sans-serif" font-size="13" font-weight="400" fill="#000000" text-anchor="middle">All Stocks (~13.000)</text>
<text x="165" y="130" font-family="system-ui, sans-serif" font-size="13" font-weight="400" fill="#000000" text-anchor="middle">S&amp;P 500 · Russell 3000</text>
<line x1="319" y1="110" x2="332" y2="110" stroke="#bbbbbb" stroke-dasharray="3 3"/>
<text x="340" y="106" font-family="system-ui, sans-serif" font-size="12" font-weight="400" fill="#666666" text-anchor="start">mai mare = găsește mai mult, durează mai</text>
<text x="340" y="122" font-family="system-ui, sans-serif" font-size="12" font-weight="400" fill="#666666" text-anchor="start">mult</text>
<line x1="330" y1="102" x2="327" y2="102" stroke="#bbbbbb" stroke-width="1" stroke-dasharray="3 3"/>
<text x="340" y="106" font-family="system-ui, sans-serif" font-size="12" font-weight="400" fill="#666666" text-anchor="start">mai mare = mai mulți candidați, scanare mai</text>
<text x="340" y="122" font-family="system-ui, sans-serif" font-size="12" font-weight="400" fill="#666666" text-anchor="start">lentă</text>
<path d="M 157 148 L 173 148 L 165 158 Z" fill="#1a5fb4"/>
<rect x="25" y="162" width="280" height="90.4" rx="6" fill="#eef3fb" stroke="#1a5fb4" stroke-width="1.5"/>
<text x="165" y="195.2" font-family="system-ui, sans-serif" font-size="13" font-weight="700" fill="#000000" text-anchor="middle">Trigger: jbtgrshdATM</text>
<text x="165" y="211.2" font-family="system-ui, sans-serif" font-size="13" font-weight="400" fill="#000000" text-anchor="middle">BDATM = 0</text>
<text x="165" y="227.2" font-family="system-ui, sans-serif" font-size="13" font-weight="400" fill="#000000" text-anchor="middle">(Sell Doji: SDATM = 0)</text>
<line x1="309" y1="207.2" x2="332" y2="207.2" stroke="#bbbbbb" stroke-dasharray="3 3"/>
<text x="340" y="184" font-family="system-ui, sans-serif" font-size="12" font-weight="400" fill="#c00" text-anchor="start">capcană: Interval = TF-ul scanerului, setat</text>
<text x="340" y="200" font-family="system-ui, sans-serif" font-size="12" font-weight="400" fill="#c00" text-anchor="start">manual</text>
<text x="340" y="222.4" font-family="system-ui, sans-serif" font-size="12" font-weight="400" fill="#c00" text-anchor="start">capcană: 0 = ultima candelă închisă; 1 = cu</text>
<text x="340" y="238.4" font-family="system-ui, sans-serif" font-size="12" font-weight="400" fill="#c00" text-anchor="start">o zi în urmă</text>
<line x1="330" y1="180" x2="317" y2="180" stroke="#c00" stroke-width="1.6"/>
<path d="M 309 180 L 318 176 L 318 184 Z" fill="#c00"/>
<text x="340" y="184" font-family="system-ui, sans-serif" font-size="12" font-weight="400" fill="#c00" text-anchor="start">capcană: intervalul nu se aliniază singur cu</text>
<text x="340" y="200" font-family="system-ui, sans-serif" font-size="12" font-weight="400" fill="#c00" text-anchor="start">TF-ul: îl pui de mână</text>
<line x1="330" y1="218.4" x2="317" y2="218.4" stroke="#c00" stroke-width="1.6"/>
<path d="M 309 218.4 L 318 214.4 L 318 222.4 Z" fill="#c00"/>
<text x="340" y="222.4" font-family="system-ui, sans-serif" font-size="12" font-weight="400" fill="#c00" text-anchor="start">capcană: vede doar candela închisă: daily</text>
<text x="340" y="238.4" font-family="system-ui, sans-serif" font-size="12" font-weight="400" fill="#c00" text-anchor="start">rulat la prânz arată ieri</text>
<path d="M 157 256.4 L 173 256.4 L 165 266.4 Z" fill="#1a5fb4"/>
<rect x="35" y="270.4" width="260" height="90.4" rx="6" fill="#eef3fb" stroke="#1a5fb4" stroke-width="1.5"/>
<text x="165" y="303.6" font-family="system-ui, sans-serif" font-size="13" font-weight="700" fill="#000000" text-anchor="middle">Nivel: RSV1ATM</text>
<text x="165" y="319.6" font-family="system-ui, sans-serif" font-size="13" font-weight="400" fill="#000000" text-anchor="middle">% of PP ≤ 0.5 (60 min)</text>
<text x="165" y="335.6" font-family="system-ui, sans-serif" font-size="13" font-weight="400" fill="#000000" text-anchor="middle">% of PP ≤ 2 (daily)</text>
<line x1="299" y1="315.6" x2="332" y2="315.6" stroke="#bbbbbb" stroke-dasharray="3 3"/>
<line x1="330" y1="288.4" x2="307" y2="288.4" stroke="#bbbbbb" stroke-width="1" stroke-dasharray="3 3"/>
<text x="340" y="292.4" font-family="system-ui, sans-serif" font-size="12" font-weight="400" fill="#666666" text-anchor="start">Pivot Interval: 2 = weekly (pe 60 min), 3 =</text>
<text x="340" y="308.4" font-family="system-ui, sans-serif" font-size="12" font-weight="400" fill="#666666" text-anchor="start">monthly (pe daily)</text>
<text x="340" y="330.8" font-family="system-ui, sans-serif" font-size="12" font-weight="400" fill="#c00" text-anchor="start">capcană: RS/SR = 1 la filtrare; cu 100,</text>
<text x="340" y="346.8" font-family="system-ui, sans-serif" font-size="12" font-weight="400" fill="#c00" text-anchor="start">pragul se scrie ×100</text>
<line x1="330" y1="326.8" x2="307" y2="326.8" stroke="#c00" stroke-width="1.6"/>
<path d="M 299 326.8 L 308 322.8 L 308 330.8 Z" fill="#c00"/>
<text x="340" y="330.8" font-family="system-ui, sans-serif" font-size="12" font-weight="400" fill="#c00" text-anchor="start">capcană: RS/SR: 1 la filtrare, 100 doar la</text>
<text x="340" y="346.8" font-family="system-ui, sans-serif" font-size="12" font-weight="400" fill="#c00" text-anchor="start">afișare</text>
<path d="M 157 364.8 L 173 364.8 L 165 374.8 Z" fill="#1a5fb4"/>
<rect x="45" y="378.8" width="240" height="68" rx="6" fill="#eef3fb" stroke="#1a5fb4" stroke-width="1.5"/>
<text x="165" y="400.8" font-family="system-ui, sans-serif" font-size="13" font-weight="700" fill="#000000" text-anchor="middle">Lichiditate: Volume Colors</text>
<text x="165" y="416.8" font-family="system-ui, sans-serif" font-size="13" font-weight="400" fill="#000000" text-anchor="middle">Average Volume ≥ 500.000</text>
<text x="165" y="432.8" font-family="system-ui, sans-serif" font-size="13" font-weight="400" fill="#000000" text-anchor="middle">Average Length = 10</text>
<line x1="289" y1="412.8" x2="332" y2="412.8" stroke="#bbbbbb" stroke-dasharray="3 3"/>
<line x1="330" y1="412.8" x2="297" y2="412.8" stroke="#bbbbbb" stroke-width="1" stroke-dasharray="3 3"/>
<text x="340" y="416.8" font-family="system-ui, sans-serif" font-size="12" font-weight="400" fill="#666666" text-anchor="start">volum daily, indiferent de TF-ul scanerului</text>
<path d="M 157 450.8 L 173 450.8 L 165 460.8 Z" fill="#1a5fb4"/>
<rect x="55" y="464.8" width="220" height="90.4" rx="6" fill="#eef3fb" stroke="#1a5fb4" stroke-width="1.5"/>
<text x="165" y="490" font-family="system-ui, sans-serif" font-size="13" font-weight="700" fill="#000000" text-anchor="middle">Opțional:</text>
<text x="165" y="506" font-family="system-ui, sans-serif" font-size="13" font-weight="400" fill="#000000" text-anchor="middle">Since Bear ≥ 8</text>
<text x="165" y="522" font-family="system-ui, sans-serif" font-size="13" font-weight="400" fill="#000000" text-anchor="middle">Bull Reversal = 1</text>
<text x="165" y="538" font-family="system-ui, sans-serif" font-size="13" font-weight="400" fill="#000000" text-anchor="middle">RVOL doar Display</text>
<line x1="279" y1="510" x2="332" y2="510" stroke="#bbbbbb" stroke-dasharray="3 3"/>
<text x="340" y="486.8" font-family="system-ui, sans-serif" font-size="12" font-weight="400" fill="#c00" text-anchor="start">capcană: Bear Reversal e selectat implicit —</text>
<text x="340" y="502.8" font-family="system-ui, sans-serif" font-size="12" font-weight="400" fill="#c00" text-anchor="start">comută pe Bull</text>
<text x="340" y="525.2" font-family="system-ui, sans-serif" font-size="12" font-weight="400" fill="#c00" text-anchor="start">capcană: în zile extreme, pragurile rigide</text>
<text x="340" y="541.2" font-family="system-ui, sans-serif" font-size="12" font-weight="400" fill="#c00" text-anchor="start">golesc lista</text>
<path d="M 157 559.2 L 173 559.2 L 165 569.2 Z" fill="#1a5fb4"/>
<rect x="65" y="573.2" width="200" height="84" rx="6" fill="#eef7f0" stroke="#188a3e" stroke-width="2"/>
<text x="165" y="595.2" font-family="system-ui, sans-serif" font-size="13" font-weight="700" fill="#188a3e" text-anchor="middle">Lista de candidați</text>
<text x="165" y="611.2" font-family="system-ui, sans-serif" font-size="13" font-weight="400" fill="#188a3e" text-anchor="middle">→ o verifici pe grafic</text>
<text x="165" y="627.2" font-family="system-ui, sans-serif" font-size="13" font-weight="400" fill="#188a3e" text-anchor="middle">(pașii 2-6).</text>
<text x="165" y="643.2" font-family="system-ui, sans-serif" font-size="13" font-weight="400" fill="#188a3e" text-anchor="middle">Scanerul nu e undă verde.</text>
<text x="20" y="687.2" font-family="system-ui, sans-serif" font-size="12.5" font-weight="400" fill="#000000" text-anchor="start">Delay: scanerul vede candela închisă — daily rulat la 12:00 arată triggerul de ieri.</text>
<rect x="55" y="464.8" width="220" height="84" rx="6" fill="#eef3fb" stroke="#1a5fb4" stroke-width="1.5"/>
<text x="165" y="486.8" font-family="system-ui, sans-serif" font-size="13" font-weight="700" fill="#000000" text-anchor="middle">Opțional:</text>
<text x="165" y="502.8" font-family="system-ui, sans-serif" font-size="13" font-weight="400" fill="#000000" text-anchor="middle">Since Bear ≥ 8</text>
<text x="165" y="518.8" font-family="system-ui, sans-serif" font-size="13" font-weight="400" fill="#000000" text-anchor="middle">Bull Reversal = 1</text>
<text x="165" y="534.8" font-family="system-ui, sans-serif" font-size="13" font-weight="400" fill="#000000" text-anchor="middle">RVOL doar Display</text>
<line x1="330" y1="498.8" x2="287" y2="498.8" stroke="#c00" stroke-width="1.6"/>
<path d="M 279 498.8 L 288 494.8 L 288 502.8 Z" fill="#c00"/>
<text x="340" y="502.8" font-family="system-ui, sans-serif" font-size="12" font-weight="400" fill="#c00" text-anchor="start">capcană: pornește pe Bear Reversal: comută</text>
<text x="340" y="518.8" font-family="system-ui, sans-serif" font-size="12" font-weight="400" fill="#c00" text-anchor="start">pe Bull</text>
<path d="M 157 552.8 L 173 552.8 L 165 562.8 Z" fill="#1a5fb4"/>
<rect x="65" y="566.8" width="200" height="84" rx="6" fill="#eef7f0" stroke="#188a3e" stroke-width="2"/>
<text x="165" y="588.8" font-family="system-ui, sans-serif" font-size="13" font-weight="700" fill="#188a3e" text-anchor="middle">Lista de candidați</text>
<text x="165" y="604.8" font-family="system-ui, sans-serif" font-size="13" font-weight="400" fill="#188a3e" text-anchor="middle">→ o verifici pe grafic</text>
<text x="165" y="620.8" font-family="system-ui, sans-serif" font-size="13" font-weight="400" fill="#188a3e" text-anchor="middle">(pașii 2-6).</text>
<text x="165" y="636.8" font-family="system-ui, sans-serif" font-size="13" font-weight="400" fill="#188a3e" text-anchor="middle">Scanerul nu e undă verde.</text>
</svg>

Before

Width:  |  Height:  |  Size: 7.6 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

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()

View File

@@ -1,16 +1,23 @@
TIP: PRET
CHEIE: sell
TITLU: Sell Doji — daily (exemplu construit, fără ticker)
TITLU: Sell Doji pe short — daily (exemplu construit)
MARCAJ .md: <!-- DIAGRAMA: sell --> (Nivel 1, §1.3 Trigger, oglinda short)
CE ARATĂ
Graficul întreg al unui trade Sell Doji short, oglinda ansamblului long:
uptrend de 14 candele, doji, o bară de așteptare care NU confirmă, apoi o
bară care închide sub low, intrare short la close, SL deasupra high-ului
ultimelor 4 candele, TP 1:1 în jos, apoi trailing. Panou de volum dedesubt.
bară care închide sub low, intrare short la close, SL 5 cenți deasupra
high-ului ultimelor 4 candele, TP 1:1 în jos, apoi trailing. Panou de volum.
Format tutorial v2: zone de evidențiere („1. creștere de 10 candele",
„2. doji", cutie roșie = riscul, între intrare și stop, cutie verde = câștigul,
între intrare și țintă — ca unealta „short position" din TradingView; segment
gri = linia de trail) și 4 săgeți care spun ce ȘI de ce: stop, intrare, țintă,
ieșire pe trail. Etichetele nivelurilor în dreapta, dincolo de ultima candelă.
NIVELURILE ȘI ETICHETELE (cu trimitere)
- doji 99.20-100.10, intrare short 99.00, SL 100.10, TP 97.90 (1:1).
- doji 99.20-100.10, intrare short 99.00, SL 100.15, TP 97.85 (1:1, 1R = 1.15).
SL mutat de la 100.10 (exact pe high) la 100.15, ca oglinda pasului 5 din
capitol, unde stopul long stă „puțin sub" low (51.60 -> 51.55).
Sursa principală construiește exact aceste cifre:
`13_strategia_3_byh.md:258-259` („short: doji 99.20–100.10, intrare
99.00, SL 100.10, TP 97.90, trail ~97.30").
@@ -37,16 +44,16 @@ Mecioni (up, down) implicite (0.30, 0.25); excepții:
Volum: peste medie pe doji și pe confirmare (distribuție), apoi normal.
CE VERIFICĂ GENERATORUL CU assert
1. max(high[13:17]) == 100.10 == SL (cel mai înalt high din 4 candele)
1. max(high[13:17]) == 100.10 și SL == 100.10 + 0.05 == 100.15
2. close[16] == 99.00 == intrare
3. close[16] < low[14] == 99.20 (confirmarea chiar închide sub low)
4. close[15] >= low[14] (bara +1 NU confirmă)
5. abs(sl - entry) == abs(entry - tp) == 1.10 (1:1 exact)
6. primul i>16 cu low[i] <= 97.90 este bara 19 (low[18]=98.05, low[19]=97.55)
5. abs(sl - entry) == abs(entry - tp) == 1.15 (1:1 exact)
6. primul i>16 cu low[i] <= 97.85 este bara 19 (low[18]=98.05, low[19]=97.55)
7. linia de trail = high[25] = 96.45; primul close > 96.45 este barul 27
(96.60); și 96.60 < intrare (profit pe short)
8. doji: abs(o-c) <= 0.10*(h-l)
9. trend: close[13] > close[0] + 5
STIL: gap=15, body_w=9, left=44, width=640, vol_h=70, scale ~30. Etichete
„SL 100.10 (high 4 candele)", „intrare short 99.00", „TP 97.90 = 1R".
STIL: gap=20, body_w=9, left=44, width=790, vol_h=60, scale 45. Etichete
„stop 100.15", „intrare short 99.00", „ținta 97.85".
Fără linie goală în SVG.

View File

@@ -1,111 +1,129 @@
<svg viewBox="0 0 640 460" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif">
<text x="24" y="48" fill="#333" style="font-weight:bold">Sell Doji — daily (exemplu construit, fără ticker)</text>
<line x1="24" y1="68.0" x2="626" y2="68.0" stroke="#c00" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="612" y="62.0" fill="#c00" text-anchor="end">SL 100.10 (high 4 candele)</text>
<line x1="24" y1="101.0" x2="626" y2="101.0" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="612" y="95.0" fill="#188a3e" text-anchor="end">intrare short 99.00</text>
<line x1="24" y1="134.0" x2="626" y2="134.0" stroke="#1a5fb4" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="612" y="128.0" fill="#1a5fb4" text-anchor="end">TP 97.90 = 1R</text>
<line x1="24" y1="177.5" x2="626" y2="177.5" stroke="#b06000" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="612" y="171.5" fill="#b06000" text-anchor="end">trail 96.45</text>
<line x1="44.0" y1="272.0" x2="44.0" y2="288.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="39.5" y="281.0" width="9" height="1.6" fill="#188a3e"/>
<line x1="59.0" y1="239.0" x2="59.0" y2="288.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="54.5" y="248.0" width="9" height="33.0" fill="#188a3e"/>
<line x1="74.0" y1="239.0" x2="74.0" y2="267.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="69.5" y="248.0" width="9" height="12.0" fill="#c00"/>
<line x1="89.0" y1="212.0" x2="89.0" y2="267.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="84.5" y="221.0" width="9" height="39.0" fill="#188a3e"/>
<line x1="104.0" y1="179.0" x2="104.0" y2="228.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="99.5" y="188.0" width="9" height="33.0" fill="#188a3e"/>
<line x1="119.0" y1="179.0" x2="119.0" y2="204.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="114.5" y="188.0" width="9" height="9.0" fill="#c00"/>
<line x1="134.0" y1="152.0" x2="134.0" y2="204.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="129.5" y="161.0" width="9" height="36.0" fill="#188a3e"/>
<line x1="149.0" y1="119.0" x2="149.0" y2="168.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="144.5" y="128.0" width="9" height="33.0" fill="#188a3e"/>
<line x1="164.0" y1="119.0" x2="164.0" y2="144.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="159.5" y="128.0" width="9" height="9.0" fill="#c00"/>
<line x1="179.0" y1="95.0" x2="179.0" y2="144.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="174.5" y="104.0" width="9" height="33.0" fill="#188a3e"/>
<line x1="194.0" y1="68.0" x2="194.0" y2="111.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="189.5" y="77.0" width="9" height="27.0" fill="#188a3e"/>
<line x1="209.0" y1="56.0" x2="209.0" y2="84.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="204.5" y="65.0" width="9" height="12.0" fill="#188a3e"/>
<line x1="224.0" y1="56.0" x2="224.0" y2="81.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="219.5" y="65.0" width="9" height="9.0" fill="#c00"/>
<line x1="239.0" y1="68.0" x2="239.0" y2="89.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="234.5" y="74.0" width="9" height="7.5" fill="#c00"/>
<line x1="254.0" y1="68.0" x2="254.0" y2="95.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="249.5" y="81.5" width="9" height="1.6" fill="#c00"/>
<line x1="269.0" y1="77.0" x2="269.0" y2="93.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="264.5" y="83.0" width="9" height="6.0" fill="#777"/>
<line x1="284.0" y1="83.0" x2="284.0" y2="105.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="279.5" y="89.0" width="9" height="12.0" fill="#c00"/>
<line x1="299.0" y1="92.0" x2="299.0" y2="123.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="294.5" y="101.0" width="9" height="15.0" fill="#c00"/>
<line x1="314.0" y1="107.0" x2="314.0" y2="129.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="309.5" y="116.0" width="9" height="6.0" fill="#c00"/>
<line x1="329.0" y1="113.0" x2="329.0" y2="144.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="324.5" y="122.0" width="9" height="15.0" fill="#c00"/>
<line x1="344.0" y1="128.0" x2="344.0" y2="156.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="339.5" y="137.0" width="9" height="12.0" fill="#c00"/>
<line x1="359.0" y1="140.0" x2="359.0" y2="168.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="354.5" y="149.0" width="9" height="12.0" fill="#c00"/>
<line x1="374.0" y1="152.0" x2="374.0" y2="177.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="369.5" y="161.0" width="9" height="9.0" fill="#c00"/>
<line x1="389.0" y1="161.0" x2="389.0" y2="186.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="384.5" y="170.0" width="9" height="9.0" fill="#c00"/>
<line x1="404.0" y1="170.0" x2="404.0" y2="195.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="399.5" y="179.0" width="9" height="9.0" fill="#c00"/>
<line x1="419.0" y1="177.5" x2="419.0" y2="203.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="414.5" y="188.0" width="9" height="9.0" fill="#c00"/>
<line x1="434.0" y1="176.0" x2="434.0" y2="200.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="429.5" y="185.0" width="9" height="12.0" fill="#188a3e"/>
<line x1="449.0" y1="164.0" x2="449.0" y2="192.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="444.5" y="173.0" width="9" height="12.0" fill="#188a3e"/>
<line x1="464.0" y1="164.0" x2="464.0" y2="186.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="459.5" y="173.0" width="9" height="6.0" fill="#c00"/>
<line x1="479.0" y1="170.0" x2="479.0" y2="195.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="474.5" y="179.0" width="9" height="9.0" fill="#c00"/>
<line x1="494.0" y1="173.0" x2="494.0" y2="195.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="489.5" y="182.0" width="9" height="6.0" fill="#188a3e"/>
<line x1="24" y1="384.5" x2="626" y2="384.5" stroke="#888"/>
<rect x="39.5" y="350.3" width="9" height="34.2" fill="#188a3e" opacity="0.55"/>
<rect x="54.5" y="351.8" width="9" height="32.7" fill="#188a3e" opacity="0.55"/>
<rect x="69.5" y="348.7" width="9" height="35.8" fill="#c00" opacity="0.55"/>
<rect x="84.5" y="353.4" width="9" height="31.1" fill="#188a3e" opacity="0.55"/>
<rect x="99.5" y="349.5" width="9" height="35.0" fill="#188a3e" opacity="0.55"/>
<rect x="114.5" y="347.2" width="9" height="37.3" fill="#c00" opacity="0.55"/>
<rect x="129.5" y="351.1" width="9" height="33.4" fill="#188a3e" opacity="0.55"/>
<rect x="144.5" y="347.9" width="9" height="36.6" fill="#188a3e" opacity="0.55"/>
<rect x="159.5" y="345.6" width="9" height="38.9" fill="#c00" opacity="0.55"/>
<rect x="174.5" y="349.5" width="9" height="35.0" fill="#188a3e" opacity="0.55"/>
<rect x="189.5" y="344.1" width="9" height="40.4" fill="#188a3e" opacity="0.55"/>
<rect x="204.5" y="339.4" width="9" height="45.1" fill="#188a3e" opacity="0.55"/>
<rect x="219.5" y="346.4" width="9" height="38.1" fill="#c00" opacity="0.55"/>
<rect x="234.5" y="341.7" width="9" height="42.8" fill="#c00" opacity="0.55"/>
<rect x="249.5" y="314.5" width="9" height="70.0" fill="#c00" opacity="0.55"/>
<rect x="264.5" y="336.3" width="9" height="48.2" fill="#777" opacity="0.55"/>
<rect x="279.5" y="319.2" width="9" height="65.3" fill="#c00" opacity="0.55"/>
<rect x="294.5" y="340.9" width="9" height="43.6" fill="#c00" opacity="0.55"/>
<rect x="309.5" y="344.1" width="9" height="40.4" fill="#c00" opacity="0.55"/>
<rect x="324.5" y="345.6" width="9" height="38.9" fill="#c00" opacity="0.55"/>
<rect x="339.5" y="347.2" width="9" height="37.3" fill="#c00" opacity="0.55"/>
<rect x="354.5" y="348.7" width="9" height="35.8" fill="#c00" opacity="0.55"/>
<rect x="369.5" y="350.3" width="9" height="34.2" fill="#c00" opacity="0.55"/>
<rect x="384.5" y="351.8" width="9" height="32.7" fill="#c00" opacity="0.55"/>
<rect x="399.5" y="353.4" width="9" height="31.1" fill="#c00" opacity="0.55"/>
<rect x="414.5" y="349.5" width="9" height="35.0" fill="#c00" opacity="0.55"/>
<rect x="429.5" y="345.6" width="9" height="38.9" fill="#188a3e" opacity="0.55"/>
<rect x="444.5" y="348.7" width="9" height="35.8" fill="#188a3e" opacity="0.55"/>
<rect x="459.5" y="350.3" width="9" height="34.2" fill="#c00" opacity="0.55"/>
<rect x="474.5" y="351.1" width="9" height="33.4" fill="#c00" opacity="0.55"/>
<rect x="489.5" y="349.5" width="9" height="35.0" fill="#188a3e" opacity="0.55"/>
<text x="24" y="308.5" fill="#555">volum</text>
<text x="254.0" y="58.0" fill="#b06000" text-anchor="middle" style="font-weight:bold">doji 99.20 / 100.10</text>
<text x="449.0" y="148.0" fill="#c00" text-anchor="middle" style="font-weight:bold">ieșire pe trail 96.60</text>
<text x="24" y="406.5" fill="#777">bara 15: close 99.40 peste low-ul dojiului 99.20 — NU confirmă</text>
<text x="24" y="423.5" fill="#c00">bara 16: close 99.00 sub 99.20 — confirmare (intrare short)</text>
<text x="24" y="448" fill="#555">Intrare short la close sub low-ul dojiului, SL la high 4 candele, TP 1:1, apoi trail.</text>
<svg viewBox="0 0 840 571" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif">
<text x="24" y="72" fill="#333" style="font-weight:bold">Sell Doji pe short — daily (exemplu construit)</text>
<rect x="34.5" y="130.8" width="199.0" height="306.3" fill="#1a5fb4" fill-opacity="0.08" stroke="#1a5fb4" stroke-width="1"/>
<text x="34.5" y="125.8" fill="#1a5fb4" style="font-weight:bold">1. creștere de 10 candele</text>
<rect x="314.5" y="90.2" width="19.0" height="56.5" fill="#b06000" fill-opacity="0.08" stroke="#b06000" stroke-width="1"/>
<text x="314.5" y="85.2" fill="#b06000" style="font-weight:bold">2. doji</text>
<rect x="354.5" y="96.0" width="79.0" height="51.8" fill="#c00" fill-opacity="0.08" stroke="#c00" stroke-width="1"/>
<rect x="354.5" y="147.8" width="79.0" height="51.8" fill="#188a3e" fill-opacity="0.08" stroke="#188a3e" stroke-width="1"/>
<rect x="534.5" y="262.5" width="119.0" height="0.9" fill="#555" fill-opacity="0.08" stroke="#555" stroke-width="1"/>
<line x1="24" y1="96.0" x2="826" y2="96.0" stroke="#c00" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="812" y="90.0" fill="#c00" text-anchor="end">stop 100.15</text>
<line x1="24" y1="147.8" x2="826" y2="147.8" stroke="#b06000" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="812" y="141.8" fill="#b06000" text-anchor="end">intrare short 99.00</text>
<line x1="24" y1="199.5" x2="826" y2="199.5" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="812" y="193.5" fill="#188a3e" text-anchor="end">ținta 97.85</text>
<line x1="44.0" y1="404.3" x2="44.0" y2="429.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="39.5" y="417.8" width="9" height="1.6" fill="#188a3e"/>
<line x1="64.0" y1="354.8" x2="64.0" y2="429.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="59.5" y="368.3" width="9" height="49.5" fill="#188a3e"/>
<line x1="84.0" y1="354.8" x2="84.0" y2="397.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="79.5" y="368.3" width="9" height="18.0" fill="#c00"/>
<line x1="104.0" y1="314.3" x2="104.0" y2="397.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="99.5" y="327.8" width="9" height="58.5" fill="#188a3e"/>
<line x1="124.0" y1="264.8" x2="124.0" y2="339.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="119.5" y="278.3" width="9" height="49.5" fill="#188a3e"/>
<line x1="144.0" y1="264.8" x2="144.0" y2="303.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="139.5" y="278.3" width="9" height="13.5" fill="#c00"/>
<line x1="164.0" y1="224.3" x2="164.0" y2="303.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="159.5" y="237.8" width="9" height="54.0" fill="#188a3e"/>
<line x1="184.0" y1="174.8" x2="184.0" y2="249.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="179.5" y="188.3" width="9" height="49.5" fill="#188a3e"/>
<line x1="204.0" y1="174.8" x2="204.0" y2="213.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="199.5" y="188.3" width="9" height="13.5" fill="#c00"/>
<line x1="224.0" y1="138.8" x2="224.0" y2="213.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="219.5" y="152.2" width="9" height="49.5" fill="#188a3e"/>
<line x1="244.0" y1="98.3" x2="244.0" y2="163.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="239.5" y="111.8" width="9" height="40.5" fill="#188a3e"/>
<line x1="264.0" y1="80.3" x2="264.0" y2="123.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="259.5" y="93.8" width="9" height="18.0" fill="#188a3e"/>
<line x1="284.0" y1="80.3" x2="284.0" y2="118.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="279.5" y="93.8" width="9" height="13.5" fill="#c00"/>
<line x1="304.0" y1="98.2" x2="304.0" y2="129.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="299.5" y="107.2" width="9" height="11.2" fill="#c00"/>
<line x1="324.0" y1="98.2" x2="324.0" y2="138.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="319.5" y="118.5" width="9" height="2.3" fill="#c00"/>
<line x1="344.0" y1="111.8" x2="344.0" y2="136.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="339.5" y="120.8" width="9" height="9.0" fill="#c00"/>
<line x1="364.0" y1="120.7" x2="364.0" y2="154.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="359.5" y="129.8" width="9" height="18.0" fill="#c00"/>
<line x1="384.0" y1="134.3" x2="384.0" y2="181.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="379.5" y="147.8" width="9" height="22.5" fill="#c00"/>
<line x1="404.0" y1="156.8" x2="404.0" y2="190.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="399.5" y="170.3" width="9" height="9.0" fill="#c00"/>
<line x1="424.0" y1="165.8" x2="424.0" y2="213.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="419.5" y="179.3" width="9" height="22.5" fill="#c00"/>
<line x1="444.0" y1="188.3" x2="444.0" y2="231.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="439.5" y="201.8" width="9" height="18.0" fill="#c00"/>
<line x1="464.0" y1="206.3" x2="464.0" y2="249.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="459.5" y="219.8" width="9" height="18.0" fill="#c00"/>
<line x1="484.0" y1="224.3" x2="484.0" y2="262.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="479.5" y="237.8" width="9" height="13.5" fill="#c00"/>
<line x1="504.0" y1="237.8" x2="504.0" y2="276.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="499.5" y="251.3" width="9" height="13.5" fill="#c00"/>
<line x1="524.0" y1="251.3" x2="524.0" y2="289.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="519.5" y="264.8" width="9" height="13.5" fill="#c00"/>
<line x1="544.0" y1="262.5" x2="544.0" y2="300.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="539.5" y="278.3" width="9" height="13.5" fill="#c00"/>
<line x1="564.0" y1="260.3" x2="564.0" y2="296.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="559.5" y="273.8" width="9" height="18.0" fill="#188a3e"/>
<line x1="584.0" y1="242.3" x2="584.0" y2="285.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="579.5" y="255.8" width="9" height="18.0" fill="#188a3e"/>
<line x1="604.0" y1="242.3" x2="604.0" y2="276.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="599.5" y="255.8" width="9" height="9.0" fill="#c00"/>
<line x1="624.0" y1="251.3" x2="624.0" y2="289.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="619.5" y="264.8" width="9" height="13.5" fill="#c00"/>
<line x1="644.0" y1="255.8" x2="644.0" y2="289.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="639.5" y="269.3" width="9" height="9.0" fill="#188a3e"/>
<line x1="24" y1="529.0" x2="826" y2="529.0" stroke="#888"/>
<rect x="39.5" y="499.7" width="9" height="29.3" fill="#188a3e" opacity="0.55"/>
<rect x="59.5" y="501.0" width="9" height="28.0" fill="#188a3e" opacity="0.55"/>
<rect x="79.5" y="498.3" width="9" height="30.7" fill="#c00" opacity="0.55"/>
<rect x="99.5" y="502.3" width="9" height="26.7" fill="#188a3e" opacity="0.55"/>
<rect x="119.5" y="499.0" width="9" height="30.0" fill="#188a3e" opacity="0.55"/>
<rect x="139.5" y="497.0" width="9" height="32.0" fill="#c00" opacity="0.55"/>
<rect x="159.5" y="500.3" width="9" height="28.7" fill="#188a3e" opacity="0.55"/>
<rect x="179.5" y="497.7" width="9" height="31.3" fill="#188a3e" opacity="0.55"/>
<rect x="199.5" y="495.7" width="9" height="33.3" fill="#c00" opacity="0.55"/>
<rect x="219.5" y="499.0" width="9" height="30.0" fill="#188a3e" opacity="0.55"/>
<rect x="239.5" y="494.3" width="9" height="34.7" fill="#188a3e" opacity="0.55"/>
<rect x="259.5" y="490.3" width="9" height="38.7" fill="#188a3e" opacity="0.55"/>
<rect x="279.5" y="496.3" width="9" height="32.7" fill="#c00" opacity="0.55"/>
<rect x="299.5" y="492.3" width="9" height="36.7" fill="#c00" opacity="0.55"/>
<rect x="319.5" y="469.0" width="9" height="60.0" fill="#c00" opacity="0.55"/>
<rect x="339.5" y="487.7" width="9" height="41.3" fill="#c00" opacity="0.55"/>
<rect x="359.5" y="473.0" width="9" height="56.0" fill="#c00" opacity="0.55"/>
<rect x="379.5" y="491.7" width="9" height="37.3" fill="#c00" opacity="0.55"/>
<rect x="399.5" y="494.3" width="9" height="34.7" fill="#c00" opacity="0.55"/>
<rect x="419.5" y="495.7" width="9" height="33.3" fill="#c00" opacity="0.55"/>
<rect x="439.5" y="497.0" width="9" height="32.0" fill="#c00" opacity="0.55"/>
<rect x="459.5" y="498.3" width="9" height="30.7" fill="#c00" opacity="0.55"/>
<rect x="479.5" y="499.7" width="9" height="29.3" fill="#c00" opacity="0.55"/>
<rect x="499.5" y="501.0" width="9" height="28.0" fill="#c00" opacity="0.55"/>
<rect x="519.5" y="502.3" width="9" height="26.7" fill="#c00" opacity="0.55"/>
<rect x="539.5" y="499.0" width="9" height="30.0" fill="#c00" opacity="0.55"/>
<rect x="559.5" y="495.7" width="9" height="33.3" fill="#188a3e" opacity="0.55"/>
<rect x="579.5" y="498.3" width="9" height="30.7" fill="#188a3e" opacity="0.55"/>
<rect x="599.5" y="499.7" width="9" height="29.3" fill="#c00" opacity="0.55"/>
<rect x="619.5" y="500.3" width="9" height="28.7" fill="#c00" opacity="0.55"/>
<rect x="639.5" y="499.0" width="9" height="30.0" fill="#188a3e" opacity="0.55"/>
<text x="24" y="463.0" fill="#555">volum</text>
<line x1="514.0" y1="66.0" x2="411.8" y2="90.2" stroke="#c00" stroke-width="1.8"/>
<polygon points="404.0,92.0 410.9,86.3 412.7,94.1" fill="#c00"/>
<text x="514.0" y="47.0" fill="#c00" text-anchor="middle" style="font-weight:bold">STOPUL SUS, la 100.15 — 5 cenți peste maximul ultimelor 4 candele:</text>
<text x="514.0" y="61.0" fill="#c00" text-anchor="middle" style="font-weight:bold">dacă prețul urcă până aici, creșterea continuă și ideea e moartă</text>
<line x1="294.0" y1="257.0" x2="359.4" y2="165.0" stroke="#b06000" stroke-width="1.8"/>
<polygon points="364.0,158.5 362.6,167.3 356.1,162.7" fill="#b06000"/>
<text x="294.0" y="271.0" fill="#b06000" text-anchor="middle" style="font-weight:bold">AICI INTRI SHORT, la 99.00:</text>
<text x="294.0" y="285.0" fill="#b06000" text-anchor="middle" style="font-weight:bold">a doua candelă după doji e prima</text>
<text x="294.0" y="299.0" fill="#b06000" text-anchor="middle" style="font-weight:bold">care se ÎNCHIDE sub low-ul lui (99.20)</text>
<line x1="512.5" y1="167.5" x2="439.9" y2="196.5" stroke="#188a3e" stroke-width="1.8"/>
<polygon points="432.5,199.5 438.4,192.8 441.4,200.2" fill="#188a3e"/>
<text x="516.5" y="164.5" fill="#188a3e" text-anchor="start" style="font-weight:bold">ținta JOS, la 97.85: tot 1.15, exact cât ai riscat;</text>
<text x="516.5" y="178.5" fill="#188a3e" text-anchor="start" style="font-weight:bold">aici închizi prima treime</text>
<line x1="544.0" y1="315.0" x2="577.3" y2="293.4" stroke="#555" stroke-width="1.8"/>
<polygon points="584.0,289.0 579.5,296.7 575.1,290.0" fill="#555"/>
<text x="544.0" y="329.0" fill="#555" text-anchor="middle" style="font-weight:bold">trail-ul a coborât după preț (96.45);</text>
<text x="544.0" y="343.0" fill="#555" text-anchor="middle" style="font-weight:bold">prima închidere peste el: ieși cu restul, 96.60</text>
<text x="24" y="559" fill="#555">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.</text>
</svg>

Before

Width:  |  Height:  |  Size: 8.8 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -1,130 +1,146 @@
"""Buy Doji — unde pui stopul: 4 candele înapoi, sub structură (exemplu construit).
"""Buy Doji — unde pui stopul: 4 candele înapoi, sub structură.
Citește specificația `gen/strategii/buy_doji_stop.spec.txt`. Două panouri
stivuite, aceeași serie 0-14 ca buy_doji_transe (downtrend, doji 12, +1 13,
confirmare 14). Sus: numărătoarea celor 4 candele (1 = confirmarea). Jos:
același trade, stop „la ochi" 52.90 față de stopul din regulă 51.55.
Citește `gen/strategii/buy_doji_stop.spec.txt`. Barele vin din
`buy_doji_ansamblu.serie()` — e același trade ca în toate celelalte
diagrame ale capitolului (doji 50.10/49.25, intrare 50.40, stop 49.20).
Panoul de sus: cum numeri cele 4 candele, de la confirmare înapoi.
Panoul de jos: același trade, cu un stop pus „la ochi" (49.70, sub candela
de confirmare) față de stopul din regulă (49.20). Al doilea picior al
fundului coboară la 49.50: mătură stopul la ochi, nu-l atinge pe cel din
regulă. Barele de după intrare sunt CONSTRUITE.
"""
import re
import sys; sys.path.insert(0, "/workspace/atm-curs-dl")
from svg_candles import Candle, Chart, Level, Mark
import sys
from pathlib import Path
OUT = "/workspace/atm-curs-dl/gen/strategii/buy_doji_stop.svg"
sys.path.insert(0, "/workspace/atm-curs-dl")
sys.path.insert(0, str(Path(__file__).parent))
from svg_candles import Candle, Chart, Level, Zone, Arrow # noqa: E402
from buy_doji_ansamblu import serie, DOJI, CONF, DOJI_L, ENTRY, SL, TP1, R # noqa: E402
# --- seria: barele 0-14 exact ca în buy_doji_transe.spec.txt -----------------
closes = [60.40, 59.60, 59.90, 58.80, 58.10, 58.40, 57.20, 56.30, 56.60,
55.30, 54.20, 52.40]
bars, o = [], 61.00
for c in closes: # fitile implicite 0.15 peste/sub corp
bars.append((o, max(o, c) + 0.15, min(o, c) - 0.15, c))
o = c
bars += [(52.40, 53.00, 51.60, 52.30), # 12 doji
(52.30, 52.85, 52.10, 52.60), # 13 +1
(52.60, 53.85, 52.45, 53.70)] # 14 confirmare
after = [(53.70, 53.75, 52.70, 52.90), # 15 lovește stopul la ochi
(52.90, 53.05, 52.00, 52.20), # 16 al doilea picior, higher low
(52.20, 53.40, 52.10, 53.30),
(53.30, 54.30, 53.20, 54.20),
(54.20, 55.10, 54.10, 55.00),
(55.00, 56.00, 54.90, 55.95)] # 20 TP1
full = bars + after
o_, h_, l_, c_ = (list(x) for x in zip(*full))
OUT = Path(__file__).with_suffix(".svg")
S = 6 # prima bară arătată din serie
OCHI = 49.70 # stopul „la ochi", sub candela de confirmare
GREEN, RED, ORANGE, BLUE, GREY = "#188a3e", "#c00", "#b06000", "#1a5fb4", "#555"
W, VGAP = 720, 14
ENTRY, SL, OCHI, TP1, LOW4 = 53.70, 51.55, 52.90, 55.85, 51.60
base = serie()[S:CONF + 1] # până la confirmare, inclusiv
after = [Candle(*b) for b in [
(50.40, 50.50, 49.85, 49.95), # +1: corecție
(49.95, 50.05, 49.50, 49.60), # +2: al doilea picior, low 49.50 — mătură 49.70
(49.60, 50.35, 49.55, 50.25),
(50.25, 50.90, 50.15, 50.80),
(50.80, 51.35, 50.70, 51.25),
(51.25, 51.80, 51.15, 51.70), # +6: atinge ținta 51.60
]]
jos = base + after
d, cf = DOJI - S, CONF - S # indici locali: doji, confirmare
# --- assert-urile din spec ---------------------------------------------------
for i in range(1, len(full)): # 1
assert abs(o_[i] - c_[i - 1]) < 1e-9, f"open[{i}] != close[{i-1}]"
for i in range(len(full)):
assert l_[i] <= min(o_[i], c_[i]) and h_[i] >= max(o_[i], c_[i]), f"bara {i}"
assert min(l_[11:15]) == min(l_[10:15]) == LOW4 # 2
assert l_.index(LOW4) == 12, "cel mai jos low nu e dojiul"
assert round(LOW4 - 0.05, 2) == SL
assert min(l_[15:21]) == 52.00 and SL < 52.00 < OCHI # 3
assert next(i for i in range(15, 21) if l_[i] <= OCHI) == 15 # 4
assert all(l_[i] > SL for i in range(15, 21))
assert next(i for i in range(15, 21) if h_[i] >= TP1) == 20 # 5
assert 52.00 > LOW4 # 6
assert round(ENTRY - OCHI, 2) == 0.80 and c_[14] == ENTRY
assert round(ENTRY + (ENTRY - SL), 2) == TP1
# --- aserțiuni -----------------------------------------------------------------
for i, c in enumerate(jos):
assert c.l <= min(c.o, c.c) and c.h >= max(c.o, c.c), f"bara {i}: h/l nu cuprind o/c"
if i:
assert abs(c.o - jos[i - 1].c) < 1e-9, f"open[{i}] != close[{i-1}]"
# 1. cel mai jos low e al doji-ului, și cu 4 și cu 5 candele numărate
assert min(c.l for c in jos[cf - 3:cf + 1]) == min(c.l for c in jos[cf - 4:cf + 1]) == DOJI_L
assert jos[d].l == DOJI_L and round(DOJI_L - 0.05, 2) == SL
# 2. al doilea picior: mătură stopul la ochi, nu-l atinge pe cel din regulă
dip = [c.l for c in after]
assert min(dip) == 49.50 and SL < 49.50 < OCHI, dip
assert next(k for k, c in enumerate(after) if c.l <= OCHI) == 1, "stopul la ochi nu e lovit de al doilea picior"
assert all(c.l > SL for c in after), "stopul din regulă ar fi fost lovit"
# 3. al doilea picior e higher low față de low-ul doji-ului
assert min(dip) > DOJI_L
# 4. ținta e atinsă abia după corecție, la a 6-a bară de după intrare
assert next(k for k, c in enumerate(after, 1) if c.h >= TP1) == 6
# 5. stopul la ochi e mai aproape de intrare decât cel din regulă, și peste low-ul doji-ului
assert round(ENTRY - OCHI, 2) == 0.70 < R and DOJI_L < OCHI < jos[cf].l # sub candela de confirmare, peste low-ul doji-ului
assert round(ENTRY - SL, 2) == R
print(f"stop: low4 {DOJI_L:.2f} -> SL {SL:.2f}; la ochi {OCHI:.2f} lovit de low {min(dip):.2f}; "
f"țintă {TP1:.2f} la a 6-a bară")
GREY, RED, ORANGE, GREEN, BLUE = "#555", "#c00", "#b06000", "#188a3e", "#1a5fb4"
W = 640
common: dict = dict(scale=34.0, gap=18, body_w=10, left=44, width=W)
common: dict = dict(scale=36.0, gap=20, body_w=10, left=48, width=W)
def mk(n):
return [Candle(*b) for b in full[:n]]
# --- panoul de sus: numărătoarea ---------------------------------------------
top = Chart(
candles=mk(15),
levels=[Level(LOW4, "cel mai jos low: 51.60 (doji)", GREY, "2 2", "left"),
Level(SL, "SL 51.55", RED, "4 3")],
# fără Mark pe doji: la gap 18 eticheta calcă pe bara 11; îl numește
# paranteza de dedesubt și cercul de pe low
marks=[Mark(14, "confirmare 53.70", GREEN, "above")],
title="Unde pui stopul: 4 candele înapoi, sub structură — exemplu construit",
# --- panoul de sus: numărătoarea celor 4 candele --------------------------------
sus = Chart(
candles=base,
levels=[Level(SL, "stopul: 49.20", RED, "4 3", "left")],
zones=[Zone(cf - 3, cf, "numeri 4 candele, începând cu confirmarea", BLUE)],
arrows=[
Arrow(d, "cel mai jos low din cele 4: 49.25\n(e al doji-ului)",
where="below", price=DOJI_L, color=GREY, dx=250, dy=34),
Arrow(cf - 1, "stopul: 49.20, cu 5 cenți mai jos\nsub el, ideea că vânzătorii\nau obosit e moartă",
where="below", price=SL, color=RED, dx=250, dy=76),
Arrow(cf, "confirmarea: close 50.40\nde aici numeri înapoi",
where="above", color=GREEN, dx=250),
],
title="Pasul 5 — stopul: numeri 4 candele înapoi de la confirmare",
**common,
)
svg_top = top.render()
# numerele 4 3 2 1 + (5) sub bare, bandă de evidențiere, paranteză
yb = top._y(SL) + 18 # rândul cu numere, sub linia de SL
x = top._cx
extra_top = [
f'<rect x="{x(11) - 8:.1f}" y="{top._y(max(h_[11:15])) - 4:.1f}" '
f'width="{x(14) - x(11) + 16:.1f}" height="{yb + 6 - top._y(max(h_[11:15])):.1f}" '
f'fill="{BLUE}" opacity="0.08"/>',
f'<circle cx="{x(12):.1f}" cy="{top._y(LOW4):.1f}" r="4" fill="none" '
f'stroke="{RED}" stroke-width="1.5"/>',
]
for i, n in zip(range(11, 15), "4321"):
extra_top.append(f'<text x="{x(i):.1f}" y="{yb:.1f}" fill="{BLUE}" '
f'text-anchor="middle" style="font-weight:bold">{n}</text>')
extra_top.append(f'<text x="{x(10):.1f}" y="{yb:.1f}" fill="#999" '
f'text-anchor="middle">(5)</text>')
yp = yb + 8
extra_top.append(f'<polyline points="{x(11) - 5:.1f},{yp:.1f} {x(11) - 5:.1f},{yp + 5:.1f} '
f'{x(14) + 5:.1f},{yp + 5:.1f} {x(14) + 5:.1f},{yp:.1f}" '
f'fill="none" stroke="{BLUE}" stroke-width="1.2"/>')
extra_top.append(f'<text x="{x(14) + 14:.1f}" y="{yp + 9:.1f}" fill="{BLUE}">'
f'ultimele 4 candele (3 = doji, 1 = confirmarea)</text>')
extra_top.append(f'<text x="24" y="{yp + 28:.1f}" fill="#555">'
f'Cu 4 sau cu 5 candele iese la fel: în downtrend low-ul dojiului '
f'e oricum cel mai jos. SL = 51.60 − 0.05.</text>')
h_top = yp + 40
# --- panoul de jos: același trade, două stopuri -------------------------------
bot = Chart(
candles=mk(21),
levels=[Level(TP1, "TP1 55.85", GREEN, "2 2"),
Level(ENTRY, "intrare 53.70", GREY, "4 3"),
Level(OCHI, "stop la ochi 52.90 — lovit", ORANGE, "4 3"),
Level(SL, "SL din regulă 51.55 — ținut", RED, "4 3")],
marks=[Mark(16, "al doilea picior: 52.00, higher low", BLUE, "below", dy=10),
Mark(20, "TP1", GREEN, "above")],
title="Același trade: stop la ochi (0.80 sub intrare) vs stop din regulă",
caption="Barele 15-20 și stopul la ochi sunt construite, pentru contrast.",
top=h_top + 10 + 34, # panoul de jos începe sub cel de sus, fără <g transform>
# --- panoul de jos: stop la ochi vs stop din regulă -----------------------------
gata = Chart(
candles=jos,
levels=[Level(TP1, "ținta 1: 51.60", GREEN, "2 2", "left"),
Level(ENTRY, "intrarea: 50.40", GREY, "4 3", "left"),
Level(OCHI, "stop pus la ochi: 49.70", ORANGE, "4 3", "left"),
Level(SL, "stopul din regulă: 49.20", RED, "4 3", "left")],
# eticheta zonei o punem manual: Zone o ridică deasupra candelelor din
# dreptul textului, adică departe de banda pe care o marchează
zones=[Zone(cf + 1, cf + 2, "", RED, p_top=OCHI, p_bot=SL)],
arrows=[
Arrow(cf + 2, "stopul pus la ochi (49.70) e măturat\nera prea aproape de intrare",
where="below", price=OCHI, color=ORANGE, dx=230, dy=6),
Arrow(cf + 2, "al doilea picior al fundului: 49.50\nfundurile fac des asta",
where="below", price=49.50, color=BLUE, dx=230, dy=56),
Arrow(cf + 1, "stopul din regulă (49.20) ține\nal doilea picior rămâne peste el",
where="below", price=SL, color=RED, dx=230, dy=106),
Arrow(len(jos) - 1, "prețul ajunge la țintă\ndar numai cu stopul corect\nmai erai în trade",
where="above", price=TP1, color=GREEN, dx=150),
],
title="Același trade: stop „la ochi” (sub candela de confirmare) vs stopul din regulă",
caption="Barele de după intrare și stopul la ochi sunt construite, pentru contrast.",
**common,
)
svg_bot = bot.render()
extra_bot = [
f'<circle cx="{bot._cx(15):.1f}" cy="{bot._y(OCHI):.1f}" r="5" fill="none" '
f'stroke="{ORANGE}" stroke-width="2"/>',
]
# header-ul (viewBox) e al panoului de jos: el conține și offset-ul celui de sus
def panou(ch, sus_de=0.0):
ch.top += sus_de
svg = ch.render()
h = float(re.search(r'viewBox="0 0 [\d.]+ ([\d.]+)"', svg).group(1))
# render() mută `top` intern și îl restaurează; offsetul se citește din
# prima linie de Level, altfel tot ce desenăm pe urmă iese mai sus cu ~22px
off = float(re.search(r'<line x1="24" y1="([\d.]+)"', svg).group(1)) - ch._y(ch.levels[0].price)
return svg[svg.index(">") + 1:svg.rindex("</svg>")].strip(), h, off
body_sus, h_sus, off_sus = panou(sus)
# numerele 4 3 2 1 sub barele numărate, plus (5) — arată că iese la fel
yb = sus._y(SL) + off_sus + 22
nums = []
for k, n in zip(range(cf - 3, cf + 1), "4321"):
nums.append(f'<text x="{sus._cx(k):.1f}" y="{yb:.1f}" fill="{BLUE}" text-anchor="middle" '
f'style="font-weight:bold">{n}</text>')
nums.append(f'<text x="{sus._cx(cf - 4):.1f}" y="{yb:.1f}" fill="#999" text-anchor="middle">(5)</text>')
nums.append(f'<text x="24" y="{yb + 20:.1f}" fill="#555">'
f'cu 4 sau cu 5 candele iese la fel: în scădere, low-ul doji-ului e oricum cel mai jos</text>')
h_sus = max(h_sus, yb + 32)
body_jos, h_jos, off_jos = panou(gata, h_sus + VGAP)
zx = gata._cx(cf + 3) + 10
banda = (f'<text x="{zx:.1f}" y="{gata._y(OCHI) + off_jos - 6:.1f}" fill="{RED}" '
f'style="font-weight:bold">pe aici trece al doilea picior</text>')
H = h_jos + 8
svg = "\n ".join([
svg_bot.split(">", 1)[0] + ">",
svg_top.split(">", 1)[1].rsplit("</svg>", 1)[0].strip(), *extra_top,
f'<line x1="24" y1="{h_top + 2:.0f}" x2="{W - 14}" y2="{h_top + 2:.0f}" stroke="#ccc"/>',
svg_bot.split(">", 1)[1].rsplit("</svg>", 1)[0].strip(), *extra_bot,
f'<svg viewBox="0 0 {W} {H:.0f}" xmlns="http://www.w3.org/2000/svg" '
f'style="width:100%;height:auto;font:12px sans-serif">',
body_sus, *nums,
f'<line x1="24" y1="{h_sus + VGAP / 2:.0f}" x2="{W - 14}" y2="{h_sus + VGAP / 2:.0f}" stroke="#ddd"/>',
body_jos, banda,
]) + "\n</svg>"
H = float(re.search(r'viewBox="0 0 \d+ ([\d.]+)"', svg).group(1))
assert "<svg" in svg and "\n\n" not in svg, "linie goală în SVG"
with open(OUT, "w") as f:
f.write(svg)
assert "\n\n" not in svg and "<svg" in svg, "linie goală în SVG"
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})"
OUT.write_text(svg, encoding="utf-8")
print(f"scris {OUT} ({W}x{H:.0f})")

View File

@@ -1,55 +1,63 @@
SPEC DIAGRAMĂ — buy_doji_stop
=============================
tip: PRET, două panouri stivuite, aceeași serie până la bara 14
destinație: summaries/17_STRATEGII/01_buy_doji.md, Pasul 8 (stopul)
tip: PRET, două panouri stivuite
destinație: summaries/17_STRATEGII/01_buy_doji.md, pasul cu stopul
cheie markdown: <!-- DIAGRAMA: stop -->
titlu SVG: „Unde pui stopul: 4 candele înapoi, sub structură — exemplu construit"
stil: ca buy_doji_transe (aceleași bare 0-14, copiate sau importate).
titluri SVG: sus „Pasul 5 — stopul: numeri 4 candele înapoi de la confirmare";
jos „Același trade: stop «la ochi» (sub candela de confirmare) vs stopul din regulă"
serie: `buy_doji_ansamblu.serie()`, barele 6-16 (același trade ca în tot
capitolul: doji 50.10/49.25, intrare 50.40, stop 49.20).
CE TREBUIE SĂ DEMONSTREZE
-------------------------
Sus: cum numeri cele 4 candele (confirmarea și cele 3 dinainte), și de ce
în downtrend nu contează dacă numeri 4 sau 5: low-ul dojiului e oricum cel
mai jos. Jos: același trade, cu un stop pus „la ochi" (52.90, sub intrare
cu 0.80) față de stopul din regulă (51.55). Piciorul al doilea coboară la
52.00: lovește stopul la ochi, nu atinge stopul din regulă; apoi prețul
ajunge la TP1.
Sus: cum numeri cele 4 candele (confirmarea și cele 3 dinainte) și de ce în
scădere nu contează dacă numeri 4 sau 5 — low-ul doji-ului e oricum cel mai jos.
Jos: același trade, cu un stop pus „la ochi" la 49.70 (sub candela de
confirmare, care are low 49.75) față de stopul din regulă, 49.20. Al doilea
picior al fundului coboară la 49.50: mătură stopul la ochi, nu-l atinge pe cel
din regulă; apoi prețul ajunge la ținta 51.60.
SERIA
-----
Barele 0-14: identice cu buy_doji_transe (downtrend, doji 12, +1 13,
confirmare 14).
Panoul de sus: doar barele 0-14 (se oprește la intrare).
Panoul de jos: barele 0-14, apoi:
15 (53.70, 53.75, 52.70, 52.90)
16 (52.90, 53.05, 52.00, 52.20) <- al doilea picior, higher low 52.00
17 (52.20, 53.40, 52.10, 53.30)
18 (53.30, 54.30, 53.20, 54.20)
19 (54.20, 55.10, 54.10, 55.00)
20 (55.00, 56.00, 54.90, 55.95) <- TP1 55.85 atins
BARELE DE DUPĂ INTRARE (panoul de jos, CONSTRUITE)
--------------------------------------------------
+1 (50.40, 50.50, 49.85, 49.95)
+2 (49.95, 50.05, 49.50, 49.60) <- al doilea picior, low 49.50
+3 (49.60, 50.35, 49.55, 50.25)
+4 (50.25, 50.90, 50.15, 50.80)
+5 (50.80, 51.35, 50.70, 51.25)
+6 (51.25, 51.80, 51.15, 51.70) <- atinge ținta 51.60
MARKS / NIVELURI
----------------
Sus: numerotare „4 3 2 1" sub barele 11, 12, 13, 14 (1 = confirmarea);
paranteză „ultimele 4 candele"; Level 51.60 „cel mai jos low: 51.60 (doji)";
Level 51.55 roșu „SL 51.55".
Jos: Level 52.90 portocaliu „stop la ochi 52.90 — lovit"; Level 51.55 roșu
„SL din regulă 51.55 — ținut"; Level 55.85 verde punctat „TP1 55.85";
Mark(16, "al doilea picior: 52.00, higher low", below).
ADNOTĂRI
--------
Sus: zonă albastră peste cele 4 candele numărate, „numeri 4 candele, începând
cu confirmarea"; numerele 4 3 2 1 sub ele și (5) sub a cincea; Level „stopul:
49.20"; săgeți: „cel mai jos low din cele 4: 49.25 (e al doji-ului)",
„stopul: 49.20, cu 5 cenți mai jos / sub el, ideea că vânzătorii au obosit e
moartă", „confirmarea: close 50.40 / de aici numeri înapoi".
Jos: Level-uri 51.60 / 50.40 / 49.70 / 49.20; zonă roșie între 49.70 și 49.20
peste barele +1 și +2, etichetă „pe aici trece al doilea picior"; săgeți:
stopul la ochi măturat, al doilea picior 49.50 („fundurile fac des asta"),
stopul din regulă ține, și „prețul ajunge la țintă / dar numai cu stopul corect
mai erai în trade".
ASSERT-URI
----------
1. open[i] == close[i-1] pe barele 15-20; h/l cuprind o/c.
2. min(l[11:15]) == min(l[10:15]) == 51.60 (4 sau 5 candele: același rezultat).
3. min(l[15:21]) == 52.00; 52.00 < 52.90 și 52.00 > 51.55.
4. primul i>14 cu low <= 52.90 este 15; niciun low din 15-20 <= 51.55.
5. primul i>14 cu high >= 55.85 este 20.
6. 52.00 > 51.60 (al doilea picior e higher low).
1. h/l cuprind o/c; open[i] == close[i-1] pe toată seria panoului de jos.
2. min(low) pe ultimele 4 candele == pe ultimele 5 == 49.25 (low-ul doji-ului);
49.25 - 0.05 == 49.20.
3. min(low) după intrare == 49.50, cu 49.20 < 49.50 < 49.70.
4. prima bară de după intrare cu low <= 49.70 e a doua (al doilea picior);
nicio bară de după intrare nu are low <= 49.20.
5. ținta 51.60 e atinsă abia la a 6-a bară de după intrare.
6. 49.50 > 49.25 (al doilea picior e higher low).
7. 50.40 - 49.70 == 0.70 < 1.20 (stopul la ochi e mai aproape de intrare) și
49.25 < 49.70 < low-ul candelei de confirmare (49.75).
8. niciun text nu iese din pânză.
SURSA
-----
- SL = extrema ultimelor 4 candele de la confirmare: summaries/03_MODUL_2/13_strategia_3_byh.md:192-193;
în practică swing low-ul: summaries/09_QA/22_2025-08-04.md:23-29.
- Stopul sub structură, nu „undeva jos"; bottom-ul mai poate face un picior:
- SL = extrema ultimelor 4 candele de la confirmare: summaries/03_MODUL_2/
13_strategia_3_byh.md:192-193; în practică swing low-ul: summaries/09_QA/
22_2025-08-04.md:23-29.
- Stopul sub structură; bottom-ul mai poate face un picior:
summaries/08_ANALIZA_ZILNICA/01_buy_doji_si_strategia_mici.md:833-836.
- Stopul „la ochi" 52.90 și barele 15-20 sunt CONSTRUITE (contrast).
- Stopul „la ochi" 49.70 și barele de după intrare sunt CONSTRUITE (contrast).

View File

@@ -1,104 +1,112 @@
<svg viewBox="0 0 640 883" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif">
<text x="24" y="48" fill="#333" style="font-weight:bold">Unde pui stopul: 4 candele înapoi, sub structură — exemplu construit</text>
<line x1="24" y1="380.7" x2="626" y2="380.7" stroke="#555" stroke-width="1.5" stroke-dasharray="2 2"/>
<text x="30" y="374.7" fill="#555">cel mai jos low: 51.60 (doji)</text>
<line x1="24" y1="382.4" x2="626" y2="382.4" stroke="#c00" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="612" y="376.4" fill="#c00" text-anchor="end">SL 51.55</text>
<line x1="44.0" y1="56.0" x2="44.0" y2="86.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="39.0" y="61.1" width="10" height="20.4" fill="#c00"/>
<line x1="62.0" y1="76.4" x2="62.0" y2="113.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="57.0" y="81.5" width="10" height="27.2" fill="#c00"/>
<line x1="80.0" y1="93.4" x2="80.0" y2="113.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="75.0" y="98.5" width="10" height="10.2" fill="#188a3e"/>
<line x1="98.0" y1="93.4" x2="98.0" y2="141.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="93.0" y="98.5" width="10" height="37.4" fill="#c00"/>
<line x1="116.0" y1="130.8" x2="116.0" y2="164.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="111.0" y="135.9" width="10" height="23.8" fill="#c00"/>
<line x1="134.0" y1="144.4" x2="134.0" y2="164.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="129.0" y="149.5" width="10" height="10.2" fill="#188a3e"/>
<line x1="152.0" y1="144.4" x2="152.0" y2="195.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="147.0" y="149.5" width="10" height="40.8" fill="#c00"/>
<line x1="170.0" y1="185.2" x2="170.0" y2="226.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="165.0" y="190.3" width="10" height="30.6" fill="#c00"/>
<line x1="188.0" y1="205.6" x2="188.0" y2="226.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="183.0" y="210.7" width="10" height="10.2" fill="#188a3e"/>
<line x1="206.0" y1="205.6" x2="206.0" y2="260.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="201.0" y="210.7" width="10" height="44.2" fill="#c00"/>
<line x1="224.0" y1="249.8" x2="224.0" y2="297.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="219.0" y="254.9" width="10" height="37.4" fill="#c00"/>
<line x1="242.0" y1="287.2" x2="242.0" y2="358.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="237.0" y="292.3" width="10" height="61.2" fill="#c00"/>
<line x1="260.0" y1="333.1" x2="260.0" y2="380.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="255.0" y="353.5" width="10" height="3.4" fill="#c00"/>
<line x1="278.0" y1="338.2" x2="278.0" y2="363.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="273.0" y="346.7" width="10" height="10.2" fill="#188a3e"/>
<line x1="296.0" y1="304.2" x2="296.0" y2="351.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="291.0" y="309.3" width="10" height="37.4" fill="#188a3e"/>
<text x="296.0" y="294.2" fill="#188a3e" text-anchor="middle" style="font-weight:bold">confirmare 53.70</text>
<rect x="234.0" y="283.2" width="70.0" height="119.2" fill="#1a5fb4" opacity="0.08"/>
<circle cx="260.0" cy="380.7" r="4" fill="none" stroke="#c00" stroke-width="1.5"/>
<text x="242.0" y="400.4" fill="#1a5fb4" text-anchor="middle" style="font-weight:bold">4</text>
<text x="260.0" y="400.4" fill="#1a5fb4" text-anchor="middle" style="font-weight:bold">3</text>
<text x="278.0" y="400.4" fill="#1a5fb4" text-anchor="middle" style="font-weight:bold">2</text>
<text x="296.0" y="400.4" fill="#1a5fb4" text-anchor="middle" style="font-weight:bold">1</text>
<text x="224.0" y="400.4" fill="#999" text-anchor="middle">(5)</text>
<polyline points="237.0,408.4 237.0,413.4 301.0,413.4 301.0,408.4" fill="none" stroke="#1a5fb4" stroke-width="1.2"/>
<text x="310.0" y="417.4" fill="#1a5fb4">ultimele 4 candele (3 = doji, 1 = confirmarea)</text>
<text x="24" y="436.4" fill="#555">Cu 4 sau cu 5 candele iese la fel: în downtrend low-ul dojiului e oricum cel mai jos. SL = 51.60 − 0.05.</text>
<line x1="24" y1="450" x2="626" y2="450" stroke="#ccc"/>
<text x="24" y="506" fill="#333" style="font-weight:bold">Același trade: stop la ochi (0.80 sub intrare) vs stop din regulă</text>
<line x1="24" y1="694.6" x2="626" y2="694.6" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="2 2"/>
<text x="612" y="688.6" fill="#188a3e" text-anchor="end">TP1 55.85</text>
<line x1="24" y1="767.7" x2="626" y2="767.7" stroke="#555" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="612" y="761.7" fill="#555" text-anchor="end">intrare 53.70</text>
<line x1="24" y1="794.9" x2="626" y2="794.9" stroke="#b06000" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="612" y="788.9" fill="#b06000" text-anchor="end">stop la ochi 52.90 — lovit</text>
<line x1="24" y1="840.8" x2="626" y2="840.8" stroke="#c00" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="612" y="834.8" fill="#c00" text-anchor="end">SL din regulă 51.55 — ținut</text>
<line x1="44.0" y1="514.4" x2="44.0" y2="545.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="39.0" y="519.5" width="10" height="20.4" fill="#c00"/>
<line x1="62.0" y1="534.8" x2="62.0" y2="572.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="57.0" y="539.9" width="10" height="27.2" fill="#c00"/>
<line x1="80.0" y1="551.8" x2="80.0" y2="572.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="75.0" y="556.9" width="10" height="10.2" fill="#188a3e"/>
<line x1="98.0" y1="551.8" x2="98.0" y2="599.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="93.0" y="556.9" width="10" height="37.4" fill="#c00"/>
<line x1="116.0" y1="589.2" x2="116.0" y2="623.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="111.0" y="594.3" width="10" height="23.8" fill="#c00"/>
<line x1="134.0" y1="602.8" x2="134.0" y2="623.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="129.0" y="607.9" width="10" height="10.2" fill="#188a3e"/>
<line x1="152.0" y1="602.8" x2="152.0" y2="653.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="147.0" y="607.9" width="10" height="40.8" fill="#c00"/>
<line x1="170.0" y1="643.6" x2="170.0" y2="684.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="165.0" y="648.7" width="10" height="30.6" fill="#c00"/>
<line x1="188.0" y1="664.0" x2="188.0" y2="684.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="183.0" y="669.1" width="10" height="10.2" fill="#188a3e"/>
<line x1="206.0" y1="664.0" x2="206.0" y2="718.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="201.0" y="669.1" width="10" height="44.2" fill="#c00"/>
<line x1="224.0" y1="708.2" x2="224.0" y2="755.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="219.0" y="713.3" width="10" height="37.4" fill="#c00"/>
<line x1="242.0" y1="745.6" x2="242.0" y2="817.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="237.0" y="750.7" width="10" height="61.2" fill="#c00"/>
<line x1="260.0" y1="791.5" x2="260.0" y2="839.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="255.0" y="811.9" width="10" height="3.4" fill="#c00"/>
<line x1="278.0" y1="796.6" x2="278.0" y2="822.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="273.0" y="805.1" width="10" height="10.2" fill="#188a3e"/>
<line x1="296.0" y1="762.6" x2="296.0" y2="810.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="291.0" y="767.7" width="10" height="37.4" fill="#188a3e"/>
<line x1="314.0" y1="766.0" x2="314.0" y2="801.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="309.0" y="767.7" width="10" height="27.2" fill="#c00"/>
<line x1="332.0" y1="789.8" x2="332.0" y2="825.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="327.0" y="794.9" width="10" height="23.8" fill="#c00"/>
<line x1="350.0" y1="777.9" x2="350.0" y2="822.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="345.0" y="781.3" width="10" height="37.4" fill="#188a3e"/>
<line x1="368.0" y1="747.3" x2="368.0" y2="784.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="363.0" y="750.7" width="10" height="30.6" fill="#188a3e"/>
<line x1="386.0" y1="720.1" x2="386.0" y2="754.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="381.0" y="723.5" width="10" height="27.2" fill="#188a3e"/>
<line x1="404.0" y1="689.5" x2="404.0" y2="726.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="399.0" y="691.2" width="10" height="32.3" fill="#188a3e"/>
<text x="332.0" y="854.8" fill="#1a5fb4" text-anchor="middle" style="font-weight:bold">al doilea picior: 52.00, higher low</text>
<text x="404.0" y="679.5" fill="#188a3e" text-anchor="middle" style="font-weight:bold">TP1</text>
<text x="24" y="871" fill="#555">Barele 15-20 și stopul la ochi sunt construite, pentru contrast.</text>
<circle cx="314.0" cy="794.9" r="5" fill="none" stroke="#b06000" stroke-width="2"/>
<svg viewBox="0 0 720 1162" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif">
<text x="24" y="48" fill="#333" style="font-weight:bold">Pasul 5 — stopul: numeri 4 candele înapoi de la confirmare</text>
<rect x="178.0" y="289.2" width="80.0" height="88.0" fill="#1a5fb4" fill-opacity="0.08" stroke="#1a5fb4" stroke-width="1"/>
<text x="178.0" y="284.2" fill="#1a5fb4" style="font-weight:bold">numeri 4 candele, începând cu confirmarea</text>
<line x1="24" y1="371.0" x2="706" y2="371.0" stroke="#c00" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30" y="365.0" fill="#c00">stopul: 49.20</text>
<line x1="48.0" y1="56.0" x2="48.0" y2="119.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="43.0" y="65.0" width="10" height="43.2" fill="#c00"/>
<line x1="68.0" y1="99.2" x2="68.0" y2="158.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="63.0" y="108.2" width="10" height="39.6" fill="#c00"/>
<line x1="88.0" y1="124.4" x2="88.0" y2="158.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="83.0" y="133.4" width="10" height="14.4" fill="#188a3e"/>
<line x1="108.0" y1="124.4" x2="108.0" y2="183.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="103.0" y="133.4" width="10" height="39.6" fill="#c00"/>
<line x1="128.0" y1="164.0" x2="128.0" y2="227.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="123.0" y="173.0" width="10" height="43.2" fill="#c00"/>
<line x1="148.0" y1="207.2" x2="148.0" y2="270.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="143.0" y="216.2" width="10" height="43.2" fill="#c00"/>
<line x1="168.0" y1="250.4" x2="168.0" y2="317.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="163.0" y="259.4" width="10" height="46.8" fill="#c00"/>
<line x1="188.0" y1="297.2" x2="188.0" y2="365.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="183.0" y="306.2" width="10" height="48.6" fill="#c00"/>
<line x1="208.0" y1="338.6" x2="208.0" y2="369.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="203.0" y="354.8" width="10" height="1.8" fill="#c00"/>
<line x1="228.0" y1="340.4" x2="228.0" y2="362.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="223.0" y="345.8" width="10" height="10.8" fill="#188a3e"/>
<line x1="248.0" y1="322.4" x2="248.0" y2="351.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="243.0" y="327.8" width="10" height="18.0" fill="#188a3e"/>
<line x1="458.0" y1="433.2" x2="215.8" y2="375.1" stroke="#555" stroke-width="1.8"/>
<polygon points="208.0,373.2 216.7,371.2 214.8,379.0" fill="#555"/>
<text x="458.0" y="447.2" fill="#555" text-anchor="middle" style="font-weight:bold">cel mai jos low din cele 4: 49.25</text>
<text x="458.0" y="461.2" fill="#555" text-anchor="middle" style="font-weight:bold">(e al doji-ului)</text>
<line x1="478.0" y1="477.0" x2="235.4" y2="378.0" stroke="#c00" stroke-width="1.8"/>
<polygon points="228.0,375.0 236.9,374.3 233.9,381.7" fill="#c00"/>
<text x="478.0" y="491.0" fill="#c00" text-anchor="middle" style="font-weight:bold">stopul: 49.20, cu 5 cenți mai jos</text>
<text x="478.0" y="505.0" fill="#c00" text-anchor="middle" style="font-weight:bold">sub el, ideea că vânzătorii</text>
<text x="478.0" y="519.0" fill="#c00" text-anchor="middle" style="font-weight:bold">au obosit e moartă</text>
<line x1="498.0" y1="292.4" x2="256.0" y2="317.6" stroke="#188a3e" stroke-width="1.8"/>
<polygon points="248.0,318.4 255.5,313.6 256.4,321.6" fill="#188a3e"/>
<text x="498.0" y="273.4" fill="#188a3e" text-anchor="middle" style="font-weight:bold">confirmarea: close 50.40</text>
<text x="498.0" y="287.4" fill="#188a3e" text-anchor="middle" style="font-weight:bold">de aici numeri înapoi</text>
<text x="188.0" y="393.0" fill="#1a5fb4" text-anchor="middle" style="font-weight:bold">4</text>
<text x="208.0" y="393.0" fill="#1a5fb4" text-anchor="middle" style="font-weight:bold">3</text>
<text x="228.0" y="393.0" fill="#1a5fb4" text-anchor="middle" style="font-weight:bold">2</text>
<text x="248.0" y="393.0" fill="#1a5fb4" text-anchor="middle" style="font-weight:bold">1</text>
<text x="168.0" y="393.0" fill="#999" text-anchor="middle">(5)</text>
<text x="24" y="413.0" fill="#555">cu 4 sau cu 5 candele iese la fel: în scădere, low-ul doji-ului e oricum cel mai jos</text>
<line x1="24" y1="561" x2="706" y2="561" stroke="#ddd"/>
<text x="24" y="616" fill="#333" style="font-weight:bold">Același trade: stop „la ochi” (sub candela de confirmare) vs stopul din regulă</text>
<rect x="258.0" y="921.0" width="40.0" height="18.0" fill="#c00" fill-opacity="0.08" stroke="#c00" stroke-width="1"/>
<line x1="24" y1="852.6" x2="706" y2="852.6" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="2 2"/>
<text x="30" y="846.6" fill="#188a3e">ținta 1: 51.60</text>
<line x1="24" y1="895.8" x2="706" y2="895.8" stroke="#555" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30" y="889.8" fill="#555">intrarea: 50.40</text>
<line x1="24" y1="921.0" x2="706" y2="921.0" stroke="#b06000" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30" y="915.0" fill="#b06000">stop pus la ochi: 49.70</text>
<line x1="24" y1="939.0" x2="706" y2="939.0" stroke="#c00" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30" y="933.0" fill="#c00">stopul din regulă: 49.20</text>
<line x1="48.0" y1="624.0" x2="48.0" y2="687.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="43.0" y="633.0" width="10" height="43.2" fill="#c00"/>
<line x1="68.0" y1="667.2" x2="68.0" y2="726.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="63.0" y="676.2" width="10" height="39.6" fill="#c00"/>
<line x1="88.0" y1="692.4" x2="88.0" y2="726.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="83.0" y="701.4" width="10" height="14.4" fill="#188a3e"/>
<line x1="108.0" y1="692.4" x2="108.0" y2="751.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="103.0" y="701.4" width="10" height="39.6" fill="#c00"/>
<line x1="128.0" y1="732.0" x2="128.0" y2="795.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="123.0" y="741.0" width="10" height="43.2" fill="#c00"/>
<line x1="148.0" y1="775.2" x2="148.0" y2="838.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="143.0" y="784.2" width="10" height="43.2" fill="#c00"/>
<line x1="168.0" y1="818.4" x2="168.0" y2="885.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="163.0" y="827.4" width="10" height="46.8" fill="#c00"/>
<line x1="188.0" y1="865.2" x2="188.0" y2="933.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="183.0" y="874.2" width="10" height="48.6" fill="#c00"/>
<line x1="208.0" y1="906.6" x2="208.0" y2="937.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="203.0" y="922.8" width="10" height="1.8" fill="#c00"/>
<line x1="228.0" y1="908.4" x2="228.0" y2="930.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="223.0" y="913.8" width="10" height="10.8" fill="#188a3e"/>
<line x1="248.0" y1="890.4" x2="248.0" y2="919.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="243.0" y="895.8" width="10" height="18.0" fill="#188a3e"/>
<line x1="268.0" y1="892.2" x2="268.0" y2="915.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="263.0" y="895.8" width="10" height="16.2" fill="#c00"/>
<line x1="288.0" y1="908.4" x2="288.0" y2="928.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="283.0" y="912.0" width="10" height="12.6" fill="#c00"/>
<line x1="308.0" y1="897.6" x2="308.0" y2="926.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="303.0" y="901.2" width="10" height="23.4" fill="#188a3e"/>
<line x1="328.0" y1="877.8" x2="328.0" y2="904.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="323.0" y="881.4" width="10" height="19.8" fill="#188a3e"/>
<line x1="348.0" y1="861.6" x2="348.0" y2="885.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="343.0" y="865.2" width="10" height="16.2" fill="#188a3e"/>
<line x1="368.0" y1="845.4" x2="368.0" y2="868.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="363.0" y="849.0" width="10" height="16.2" fill="#188a3e"/>
<line x1="518.0" y1="957.0" x2="295.9" y2="926.1" stroke="#b06000" stroke-width="1.8"/>
<polygon points="288.0,925.0 296.5,922.1 295.4,930.1" fill="#b06000"/>
<text x="518.0" y="971.0" fill="#b06000" text-anchor="middle" style="font-weight:bold">stopul pus la ochi (49.70) e măturat</text>
<text x="518.0" y="985.0" fill="#b06000" text-anchor="middle" style="font-weight:bold">era prea aproape de intrare</text>
<line x1="518.0" y1="1014.2" x2="295.5" y2="934.9" stroke="#1a5fb4" stroke-width="1.8"/>
<polygon points="288.0,932.2 296.9,931.1 294.2,938.7" fill="#1a5fb4"/>
<text x="518.0" y="1028.2" fill="#1a5fb4" text-anchor="middle" style="font-weight:bold">al doilea picior al fundului: 49.50</text>
<text x="518.0" y="1042.2" fill="#1a5fb4" text-anchor="middle" style="font-weight:bold">fundurile fac des asta</text>
<line x1="498.0" y1="1075.0" x2="274.9" y2="947.0" stroke="#c00" stroke-width="1.8"/>
<polygon points="268.0,943.0 276.9,943.5 272.9,950.5" fill="#c00"/>
<text x="498.0" y="1089.0" fill="#c00" text-anchor="middle" style="font-weight:bold">stopul din regulă (49.20) ține</text>
<text x="498.0" y="1103.0" fill="#c00" text-anchor="middle" style="font-weight:bold">al doilea picior rămâne peste el</text>
<line x1="518.0" y1="822.6" x2="375.9" y2="847.2" stroke="#188a3e" stroke-width="1.8"/>
<polygon points="368.0,848.6 375.2,843.3 376.6,851.2" fill="#188a3e"/>
<text x="518.0" y="789.6" fill="#188a3e" text-anchor="middle" style="font-weight:bold">prețul ajunge la țintă</text>
<text x="518.0" y="803.6" fill="#188a3e" text-anchor="middle" style="font-weight:bold">dar numai cu stopul corect</text>
<text x="518.0" y="817.6" fill="#188a3e" text-anchor="middle" style="font-weight:bold">mai erai în trade</text>
<text x="24" y="1142" fill="#555">Barele de după intrare și stopul la ochi sunt construite, pentru contrast.</text>
<text x="318.0" y="915.0" fill="#c00" style="font-weight:bold">pe aici trece al doilea picior</text>
</svg>

Before

Width:  |  Height:  |  Size: 8.6 KiB

After

Width:  |  Height:  |  Size: 9.8 KiB

View File

@@ -1,132 +1,134 @@
"""Buy Doji — intrarea în trei tranșe (exemplu construit, doji 53.00 / 51.60).
"""Buy Doji — intrarea în trei tranșe, pe același trade ca restul capitolului.
Citește specificația `gen/strategii/buy_doji_transe.spec.txt`. Barele 0-14
sunt aceleași ca în buy_doji_stop.py. Nivelurile de 1/3 și 1/2 se calculează
din corpul candelei de confirmare, nu se scriu de mână.
Citește `gen/strategii/buy_doji_transe.spec.txt`. Barele vin din
`buy_doji_ansamblu.serie()`: doji 50.10/49.25, confirmare cu close 50.40,
stop 49.20. Nivelurile de 1/3 și 1/2 se calculează din corpul candelei de
confirmare (open 49.90 → close 50.40), nu se scriu de mână.
Lecția: împărțind intrarea în trei, prețul mediu scade de la 50.40 la
50.26, deci riscul pe acțiune de la 1.20 la 1.06 — dacă prețul revine.
Bara de după confirmare coboară la 50.10 și umple ambele ordine limită.
"""
import re
import sys; sys.path.insert(0, "/workspace/atm-curs-dl")
from svg_candles import Candle, Chart, Level, Mark
import sys
from pathlib import Path
OUT = "/workspace/atm-curs-dl/gen/strategii/buy_doji_transe.svg"
sys.path.insert(0, "/workspace/atm-curs-dl")
sys.path.insert(0, str(Path(__file__).parent))
from svg_candles import Chart, Level, Zone, Arrow # noqa: E402
from buy_doji_ansamblu import serie, DOJI, CONF, DOJI_L, ENTRY, SL, TP1, R # noqa: E402
# --- seria: barele 0-14 identice cu buy_doji_stop.py --------------------------
closes = [60.40, 59.60, 59.90, 58.80, 58.10, 58.40, 57.20, 56.30, 56.60,
55.30, 54.20, 52.40]
bars, o = [], 61.00
for c in closes: # fitile implicite 0.15 peste/sub corp
bars.append((o, max(o, c) + 0.15, min(o, c) - 0.15, c))
o = c
bars += [(52.40, 53.00, 51.60, 52.30), # 12 doji
(52.30, 52.85, 52.10, 52.60), # 13 +1
(52.60, 53.85, 52.45, 53.70), # 14 confirmare
(53.70, 53.80, 53.10, 53.45), # 15 umple 1/3 și 1/2
(53.45, 54.20, 53.35, 54.10),
(54.10, 54.85, 54.00, 54.70),
(54.70, 56.00, 54.60, 55.90)] # 18 TP1
o_, h_, l_, c_ = (list(x) for x in zip(*bars))
OUT = Path(__file__).with_suffix(".svg")
S = 12 # prima bară arătată (zoom pe fereastra de intrare)
GREEN, RED, ORANGE, BLUE, GREY = "#188a3e", "#c00", "#b06000", "#1a5fb4", "#555"
W, SCALE = 930, 100.0
# --- nivelurile, calculate din corpul barei 14 ---------------------------------
op, T1 = o_[14], c_[14]
corp = T1 - op
cds = serie()[S:20] # până la bara care atinge ținta
d, cf = DOJI - S, CONF - S # doji, confirmare (indici locali)
op, T1 = cds[cf].o, cds[cf].c # corpul candelei de confirmare
corp = round(T1 - op, 2)
T2, T3 = round(T1 - corp / 3, 2), round(T1 - corp / 2, 2)
MED = round((T1 + T2 + T3) / 3, 2)
SL = round(min(l_[11:15]) - 0.05, 2)
TP1 = round(T1 + (T1 - SL), 2)
RISC_MED, RISC_CLOSE = round(MED - SL, 2), round(T1 - SL, 2)
TP_MED = round(MED + RISC_MED, 2) # ținta de 1R socotită de la prețul mediu
retest = cds[cf + 1]
# --- aserțiuni ------------------------------------------------------------------
assert (op, T1) == (49.90, ENTRY) and corp == 0.50, (op, T1, corp)
assert (T2, T3) == (50.23, 50.15), (T2, T3)
assert MED == 50.26 and RISC_MED == 1.06 and RISC_CLOSE == R == 1.20
assert retest.l <= T3 < T2, "bara de după confirmare nu umple ambele ordine"
assert round(retest.l, 2) == 50.10, retest.l
assert min(c.l for c in cds[cf - 3:cf + 1]) == DOJI_L and round(DOJI_L - 0.05, 2) == SL
assert round(T1 + RISC_CLOSE, 2) == TP1
# ținta de 1R vine mai devreme dacă prețul mediu de intrare e mai bun
assert TP_MED == 51.32 == round(MED + RISC_MED, 2) and TP_MED < TP1
assert next(i for i in range(cf + 1, len(cds)) if cds[i].h >= TP1) == len(cds) - 1
# măsurat pe toată candela (nu doar pe corp) 1/2 iese tot T3; 1/3 iese 50.28
hi, lo = cds[cf].h, cds[cf].l
assert round(hi - (hi - lo) / 3, 2) == 50.28 and round((hi + lo) / 2, 2) == T3
print(f"transe: T1 {T1:.2f} T2 {T2:.2f} T3 {T3:.2f} medie {MED:.2f} "
f"risc {RISC_MED:.2f} (față de {RISC_CLOSE:.2f}) retest low {retest.l:.2f}")
def dy_sub(price, rand):
"""Săgeata pleacă din nivel și coboară sub linia stopului, pe rândul `rand`."""
return (price - SL) * SCALE + rand
# --- assert-urile din spec -----------------------------------------------------
for i in range(1, len(bars)): # 1
assert abs(o_[i] - c_[i - 1]) < 1e-9, f"open[{i}] != close[{i-1}]"
for i in range(len(bars)):
assert l_[i] <= min(o_[i], c_[i]) and h_[i] >= max(o_[i], c_[i]), f"bara {i}"
assert abs(o_[12] - c_[12]) <= 0.10 * (h_[12] - l_[12]) + 1e-9 # 2
assert c_[13] <= h_[12] < c_[14] and h_[12] == 53.00
assert min(l_[11:15]) == l_[12] == 51.60 and SL == 51.55 # 3
assert (op, T1) == (52.60, 53.70) and (T2, T3) == (53.33, 53.15) # 4
assert l_[15] <= T3 < T2 # 5
assert MED == 53.39 and round(MED - SL, 2) == 1.84 # 6
assert round(T1 - SL, 2) == 2.15
assert TP1 == 55.85 # 7
assert next(i for i in range(15, len(bars)) if h_[i] >= TP1) == 18
hi, lo = h_[14], l_[14] # 8
assert round(hi - (hi - lo) / 3, 2) == 53.38 and round((hi + lo) / 2, 2) == T3
GREY, RED, ORANGE, GREEN, BLUE = "#555", "#c00", "#b06000", "#188a3e", "#1a5fb4"
W = 780
ch = Chart(
candles=[Candle(*b) for b in bars],
levels=[Level(TP1, f"TP1 {TP1:.2f} = 1R de la close", GREEN, "2 2"),
Level(SL, f"SL {SL:.2f} (low 4 candele 51.60, minus 5 cenți)", RED, "4 3")],
marks=[Mark(14, f"confirmare {T1:.2f}", GREEN, "above", dy=-38)],
title="Intrarea în trei tranșe — daily, exemplu construit (doji 53.00 / 51.60)",
scale=58.0, gap=18, body_w=10, left=44, width=W,
candles=cds,
levels=[Level(TP1, "ținta 1: 51.60 = 1R față de close", GREEN, "2 2"),
Level(TP_MED, f"ținta 1: {TP_MED:.2f} = 1R față de prețul mediu {MED:.2f}", BLUE, "2 2"),
Level(SL, "stopul: 49.20", RED, "4 3", "left")],
zones=[Zone(cf, cf, "", GREEN, p_top=T1, p_bot=op)],
arrows=[
Arrow(cf, "1/3 la close 50.40\nca să nu ratezi trade-ul dacă pleacă fără tine",
where="right", price=T1, color=GREEN, dx=150, dy=dy_sub(T1, 40)),
Arrow(cf, "1/3 cu ordin limită la 50.23 (o treime din corp)\nmai ieftin, dacă prețul revine",
where="right", price=T2, color=ORANGE, dx=150, dy=dy_sub(T2, 74)),
Arrow(cf, "1/3 cu ordin limită la 50.15 (jumătatea corpului)\nși mai ieftin",
where="right", price=T3, color=ORANGE, dx=150, dy=dy_sub(T3, 108)),
Arrow(cf - 1, "media mai bună coboară ținta:\nieși la 51.32, nu la 51.60",
where="above", price=TP_MED, color=BLUE, dx=150),
Arrow(cf + 1, "retestul: prețul revine la 50.10\nși umple amândouă ordinele limită",
where="below", price=retest.l, color=BLUE, dx=-150, dy=20),
],
scale=SCALE, gap=30, body_w=10, left=56, width=W,
title="Intrarea în trei tranșe — același trade (doji 50.10 / 49.25)",
caption="Paranteza de pe candela de confirmare e corpul ei (49.90 → 50.40): pe el se măsoară 1/3 și 1/2. Stopul e unul singur. Exemplu construit.",
)
svg = ch.render()
y, x = ch._y, ch._cx
OFF = (float(re.search(r'<line x1="24" y1="([\d.]+)"', svg).group(1))
- ch._y(ch.levels[0].price)) # render() mută `top` și îl restaurează
# același lucru pe orizontală: render() lărgește pânza și mută `left` când un
# text de săgeată ar ieși în stânga. Offsetul se citește din prima candelă.
OFF_X = (float(re.search(r'<line x1="([\d.]+)"[^>]*stroke="#1a1a1a"', svg).group(1))
- ch._cx(0))
def Y(p):
return ch._y(p) + OFF
def x(i):
return ch._cx(i) + OFF_X
ex = []
# linia de ghidaj de la confirmare la eticheta ei (eticheta stă sus, peste bara 17)
ex.append(f'<line x1="{x(14):.1f}" y1="{y(h_[14]) - 3:.1f}" x2="{x(14):.1f}" '
f'y2="{y(h_[14]) - 44:.1f}" stroke="{GREEN}" stroke-width="1"/>')
# cele trei tranșe: linii de la bara 13 până la paranteza corpului
XB = 404 # paranteza corpului barei 14
for p, col, dash in ((T1, GREEN, ""), (T2, ORANGE, "3 3"), (T3, ORANGE, "3 3")):
d = f' stroke-dasharray="{dash}"' if dash else ""
ex.append(f'<line x1="{x(13) - 6:.1f}" y1="{y(p):.1f}" x2="{XB}" y2="{y(p):.1f}" '
f'stroke="{col}" stroke-width="1.5"{d}/>')
# paranteza: open 52.60 → close 53.70, cu diviziuni la 1/3 și 1/2
ex.append(f'<line x1="{XB}" y1="{y(T1):.1f}" x2="{XB}" y2="{y(op):.1f}" '
f'stroke="{GREY}" stroke-width="1.5"/>')
ex.append(f'<line x1="{XB - 6}" y1="{y(op):.1f}" x2="{XB}" y2="{y(op):.1f}" '
f'stroke="{GREY}" stroke-width="1.5"/>')
ex.append(f'<rect x="{XB - 3}" y="{y(MED) - 3:.1f}" width="6" height="6" fill="#888" '
f'transform="rotate(45 {XB} {y(MED):.1f})"/>')
# etichetele, răsfirate la dreapta, cu linii de ghidaj
yc, XL = y((T1 + T3) / 2), 440
labels = [(T1, f"1/3 la close {T1:.2f}", GREEN, ""),
(MED, f"medie {MED:.2f} → risc {MED - SL:.2f} pe acțiune (tot la close: {T1 - SL:.2f})", "#777", "2 2"),
(T2, f"1/3 la 1/3 din corp {T2:.2f}", ORANGE, "3 3"),
(T3, f"1/3 la 1/2 din corp {T3:.2f}", ORANGE, "3 3"),
(op, f"corp: open {op:.2f} → close {T1:.2f} = {corp:.2f}", GREY, "")]
for k, (p, txt, col, dash) in enumerate(labels):
ly = yc + (k - 1.5) * 22
d = f' stroke-dasharray="{dash}"' if dash else ""
ex.append(f'<polyline points="{XB},{y(p):.1f} {XL - 6},{ly - 4:.1f}" fill="none" '
f'stroke="{col}" stroke-width="1.2"{d}/>')
ex.append(f'<text x="{XL}" y="{ly:.1f}" fill="{col}" style="font-weight:bold">{txt}</text>')
# umpleri: T1 la close-ul barei 14, T2 și T3 pe low-ul barei 15; TP1 pe bara 18
for i, p, col in ((14, T1, GREEN), (15, T2, ORANGE), (15, T3, ORANGE), (18, TP1, GREEN)):
ex.append(f'<circle cx="{x(i):.1f}" cy="{y(p):.1f}" r="3.5" fill="#fff" '
# paranteza corpului, în stânga candelei de confirmare, cu diviziunile 1/3 și 1/2
xb = x(cf) - 17
ex.append(f'<polyline points="{xb + 5:.1f},{Y(T1):.1f} {xb:.1f},{Y(T1):.1f} {xb:.1f},{Y(op):.1f} '
f'{xb + 5:.1f},{Y(op):.1f}" fill="none" stroke="{GREY}" stroke-width="2"/>')
# fără etichetă lângă paranteză: oriunde lângă candele s-ar suprapune peste ele
# sau peste liniile săgeților. O numește legenda de sub grafic.
# nivelurile de tranșă, ca segmente scurte peste candela de confirmare
for p, col in ((T1, GREEN), (T2, ORANGE), (T3, ORANGE)):
dash = "" if p == T1 else ' stroke-dasharray="3 3"'
ex.append(f'<line x1="{xb:.1f}" y1="{Y(p):.1f}" x2="{x(cf) + 8:.1f}" y2="{Y(p):.1f}" '
f'stroke="{col}" stroke-width="1.5"{dash}/>')
# unde se umple fiecare tranșă: T1 la close, T2 și T3 pe low-ul barei următoare
for i, p, col in ((cf, T1, GREEN), (cf + 1, T2, ORANGE), (cf + 1, T3, ORANGE)):
ex.append(f'<circle cx="{x(i):.1f}" cy="{Y(p):.1f}" r="4" fill="#fff" '
f'stroke="{col}" stroke-width="2"/>')
# etichetele de sub candele, pe rânduri (Mark "below" le-ar pune pe același rând)
yb = y(SL) + 20
rows = [(15, f"low {l_[15]:.2f}: umple T2 și T3", ORANGE),
(13, f"+1: {c_[13]:.2f}, sub high", GREY),
(12, f"doji {h_[12]:.2f} / {l_[12]:.2f}", BLUE)]
for r, (i, txt, col) in enumerate(rows):
ry = yb + 16 * r
ex.append(f'<line x1="{x(i):.1f}" y1="{y(l_[i]) + 3:.1f}" x2="{x(i):.1f}" '
f'y2="{ry - 11:.1f}" stroke="{col}" stroke-width="1" stroke-dasharray="1 2"/>')
ex.append(f'<text x="{x(i) - 4:.1f}" y="{ry:.1f}" fill="{col}" '
# cele două paranteze de risc, la dreapta: tot la close vs cu tranșe
for xp, hi_p, txt, col in ((x(len(cds) - 1) + 40, T1,
f"risc {RISC_CLOSE:.2f} pe acțiune (tot la close)", RED),
(x(len(cds) - 1) + 290, MED,
f"risc {RISC_MED:.2f} pe acțiune (cu tranșe, preț mediu {MED:.2f})", BLUE)):
y1, y2 = Y(hi_p), Y(SL)
ex.append(f'<polyline points="{xp - 5:.1f},{y1:.1f} {xp:.1f},{y1:.1f} {xp:.1f},{y2:.1f} '
f'{xp - 5:.1f},{y2:.1f}" fill="none" stroke="{col}" stroke-width="1.5"/>')
ex.append(f'<text x="{xp + 6:.1f}" y="{(y1 + y2) / 2 + 4:.1f}" fill="{col}" '
f'style="font-weight:bold">{txt}</text>')
# legenda, pe două rânduri
ly = yb + 16 * len(rows) + 14
ex.append(f'<text x="24" y="{ly:.0f}" fill="#555">Măsurat pe corp (open {op:.2f} → close {T1:.2f}). '
f'Măsurat pe toată candela ({lo:.2f} → {hi:.2f}), 1/3 ar fi '
f'{hi - (hi - lo) / 3:.2f}; 1/2 iese tot {(hi + lo) / 2:.2f}.</text>')
ex.append(f'<text x="24" y="{ly + 17:.0f}" fill="#555">Stopul e unul singur, pentru toată '
f'poziția. Barele 0-11 și 15-18 sunt construite.</text>')
H = ly + 17 + 12
body = svg.rsplit("</svg>", 1)[0].rstrip()
svg = "\n ".join([body, *ex]) + "\n</svg>"
svg = re.sub(r'viewBox="0 0 (\d+) [\d.]+"', rf'viewBox="0 0 \1 {H:.0f}"', svg, count=1)
assert "<svg" in svg and "\n\n" not in svg, "linie goală în SVG"
with open(OUT, "w") as f:
f.write(svg)
print(f"scris {OUT} ({W}x{H:.0f})")
vw, vh = (float(v) for v in re.search(r'viewBox="0 0 ([\d.]+) ([\d.]+)"', svg).groups())
for tx, attrs, txt in re.findall(r'<text x="([-\d.]+)"([^>]*)>(.*?)</text>', svg):
ty = float(re.search(r'y="([-\d.]+)"', attrs).group(1))
w = len(txt) * 6.2
x0 = float(tx) - (w if 'text-anchor="end"' in attrs else w / 2 if 'middle' in attrs else 0)
assert 0 <= x0 and x0 + w <= vw and 0 <= ty <= vh, f"text în afara pânzei: {txt!r}"
assert "\n\n" not in svg, "linie goală în SVG"
OUT.write_text(svg, encoding="utf-8")
print(f"scris {OUT} ({vw:.0f}x{vh:.0f})")

View File

@@ -1,69 +1,53 @@
SPEC DIAGRAMĂ — buy_doji_transe
===============================
tip: PRET
destinație: summaries/17_STRATEGII/01_buy_doji.md, Pasul 7 (intrarea)
tip: PRET (un panou, zoom pe fereastra de intrare)
destinație: summaries/17_STRATEGII/01_buy_doji.md, nivelul 3 (tranșele)
cheie markdown: <!-- DIAGRAMA: transe -->
titlu SVG: „Intrarea în trei tranșe — daily, exemplu construit (doji 53.00 / 51.60)"
stil: candele lipite (gap 15-18, body_w 9-10), fără volum;
open = close anterior, fitile implicite 0.15 peste/sub corp la barele 0-11.
titlu SVG: „Intrarea în trei tranșe — același trade (doji 50.10 / 49.25)"
serie: `buy_doji_ansamblu.serie()`, barele 12-19.
CE TREBUIE SĂ DEMONSTREZE
-------------------------
Pe candela de confirmare: o treime din poziție la close (53.70), o treime
cu limit la 1/3 din corp (53.33), o treime cu limit la 1/2 (53.15). Bara de
după coboară până la 53.10 și le umple pe amândouă. Stopul e unul singur.
Prețul mediu 53.39 → risc 1.84 pe acțiune, față de 2.15 cu tot la close.
SERIA (19 bare, (o,h,l,c))
--------------------------
open[0] = 61.00; close-uri 0-11 (downtrend de 12 candele):
60.40, 59.60, 59.90, 58.80, 58.10, 58.40, 57.20, 56.30, 56.60, 55.30, 54.20, 52.40
12 doji (52.40, 53.00, 51.60, 52.30)
13 +1 (52.30, 52.85, 52.10, 52.60) close sub 53.00: încă nimic
14 confirmare (52.60, 53.85, 52.45, 53.70) close peste 53.00: Buy Doji
15 (53.70, 53.80, 53.10, 53.45) umple 1/3 și 1/2
16 (53.45, 54.20, 53.35, 54.10)
17 (54.10, 54.85, 54.00, 54.70)
18 (54.70, 56.00, 54.60, 55.90) atinge TP1 55.85 (a 4-a după intrare)
Pe candela de confirmare (open 49.90 → close 50.40, corp 0.50): o treime din
poziție la close 50.40, o treime cu ordin limită la 1/3 din corp (50.23), o
treime la 1/2 din corp (50.15). Bara următoare coboară la 50.10 (retest) și
umple amândouă ordinele limită. Prețul mediu iese 50.26, deci riscul pe acțiune
scade de la 1.20 (tot la close) la 1.06. Stopul rămâne unul singur, 49.20.
NIVELURI
--------
T1 53.70 verde „1/3 la close 53.70"
T2 53.33 portocaliu punctat „1/3 la 1/3 din corp 53.33"
T3 53.15 portocaliu punctat „1/3 la 1/2 din corp 53.15"
preț mediu 53.39 gri punctat „medie 53.39"
SL 51.55 roșu „SL 51.55 (low 4 candele 51.60, minus 5 cenți)"
TP1 55.85 verde punctat „TP1 55.85 = 1R de la close"
T1 50.40 (close) · T2 50.23 (o treime din corp) · T3 50.15 (jumătatea corpului)
preț mediu 50.26 · stop 49.20
ținta de 1R față de close: 51.60 (atinsă la ultima bară arătată)
ținta de 1R față de prețul mediu: 51.32 (50.26 + 1.06) — vine mai devreme,
ăsta e avantajul tranșelor; desenată ca al doilea nivel punctat
Măsurat pe toată candela (49.75 → 50.55), 1/3 ar fi 50.28, iar 1/2 iese tot 50.15.
MARKS
-----
Mark(12, "doji 53.00 / 51.60"), Mark(13, "+1: 52.60, sub high"),
Mark(14, "confirmare 53.70"), Mark(15, "low 53.10: umple T2 și T3", below)
LEGENDĂ
-------
„Măsurat pe corp (open 52.60 → close 53.70). Măsurat pe toată candela
(52.45 → 53.85), 1/3 ar fi 53.38; 1/2 iese tot 53.15."
ADNOTĂRI
--------
Zonă verde peste corpul candelei de confirmare; paranteză cu corpul
(49.90 → 50.40) în stânga ei; trei segmente scurte pentru T1/T2/T3 și cerculețe
acolo unde se umple fiecare tranșă (T1 la close, T2 și T3 pe low-ul barei
următoare); trei săgeți, câte una pe tranșă, cu motivul („ca să nu ratezi
trade-ul dacă pleacă fără tine" / „mai ieftin, dacă prețul revine" / „și mai
ieftin"); o săgeată pe retest; două paranteze de risc la dreapta: 1.20 tot la
close vs 1.06 cu tranșe.
ASSERT-URI
----------
1. open[i] == close[i-1]; h/l cuprind o/c.
2. doji: abs(o-c) <= 0.10*(h-l); close[13] <= 53.00 < close[14].
3. min(l[11:15]) == 51.60 (low-ul dojiului e cel mai jos din 4); SL == 51.55.
4. corp = 53.70 - 52.60; round(53.70 - corp/3, 2) == 53.33; round(53.70 - corp/2, 2) == 53.15.
5. low[15] <= 53.15 (ambele limit-uri umplute).
6. round((53.70+53.33+53.15)/3, 2) == 53.39; round(53.39-51.55, 2) == 1.84;
round(53.70-51.55, 2) == 2.15.
7. TP1 == 53.70 + 2.15 == 55.85; primul i>14 cu high >= 55.85 este 18.
8. round(53.85 - (53.85-52.45)/3, 2) == 53.38; (53.85+52.45)/2 == 53.15.
1. corpul candelei de confirmare: open 49.90, close 50.40, corp 0.50.
2. T2 == 50.23 și T3 == 50.15 (calculate din corp, nu scrise de mână).
3. medie == 50.26; medie - stop == 1.06; close - stop == 1.20 == 1R.
3b. ținta de la medie == 51.32 == medie + 1.06, și e sub 51.60.
4. low-ul barei următoare == 50.10 <= T3 (ambele ordine limită se umplu).
5. min(low) pe ultimele 4 candele de la confirmare == 49.25; stop 49.20.
6. close + 1.20 == 51.60, atinsă prima dată la ultima bară arătată.
7. măsurat pe toată candela: 1/3 == 50.28, 1/2 == 50.15 (tot T3).
8. niciun text nu iese din pânză.
SURSA
-----
- Doji 53.00/51.60, close 52.60 apoi 53.70, SL 51.55, TP1 55.85 atins la a 4-a:
summaries/08_ANALIZA_ZILNICA/01_buy_doji_si_strategia_mici.md:136-144 (exemplu construit
al sumarului; seria de aici îl redesenează cu aceleași niveluri).
- Tranșele 1/3 la close, 1/3 la 1/3, 1/3 la 1/2: summaries/09_QA/23_2025-07-29.md:206-213;
transcripts/09_Q_and_A/19_08092025.txt:1067-1073 (citat în A3_intrarea.md:276-279).
- Măsurat de la low sau de la open: summaries/09_QA/20_2025-08-25.md:178-180;
„Iei high-ul și low-ul și calculezi": summaries/09_QA/23_2025-07-29.md:210-211.
- Barele 0-11 și 15-18 sunt CONSTRUITE.
- Tranșele 1/3 la close, 1/3 la 1/3 din corp, 1/3 la 1/2: summaries/09_QA/
23_2025-07-29.md:206-213; transcripts/09_Q_and_A/19_08092025.txt:1067-1073.
- Măsurat de la low sau de la open: summaries/09_QA/20_2025-08-25.md:178-180.
- Barele sunt CONSTRUITE (aceeași serie ca restul capitolului).

View File

@@ -1,75 +1,58 @@
<svg viewBox="0 0 780 724" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif">
<text x="24" y="48" fill="#333" style="font-weight:bold">Intrarea în trei tranșe — daily, exemplu construit (doji 53.00 / 51.60)</text>
<line x1="24" y1="363.4" x2="766" y2="363.4" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="2 2"/>
<text x="752" y="357.4" fill="#188a3e" text-anchor="end">TP1 55.85 = 1R de la close</text>
<line x1="24" y1="612.8" x2="766" y2="612.8" stroke="#c00" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="752" y="606.8" fill="#c00" text-anchor="end">SL 51.55 (low 4 candele 51.60, minus 5 cenți)</text>
<line x1="44.0" y1="56.0" x2="44.0" y2="108.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="39.0" y="64.7" width="10" height="34.8" fill="#c00"/>
<line x1="62.0" y1="90.8" x2="62.0" y2="154.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="57.0" y="99.5" width="10" height="46.4" fill="#c00"/>
<line x1="80.0" y1="119.8" x2="80.0" y2="154.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="75.0" y="128.5" width="10" height="17.4" fill="#188a3e"/>
<line x1="98.0" y1="119.8" x2="98.0" y2="201.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="93.0" y="128.5" width="10" height="63.8" fill="#c00"/>
<line x1="116.0" y1="183.6" x2="116.0" y2="241.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="111.0" y="192.3" width="10" height="40.6" fill="#c00"/>
<line x1="134.0" y1="206.8" x2="134.0" y2="241.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="129.0" y="215.5" width="10" height="17.4" fill="#188a3e"/>
<line x1="152.0" y1="206.8" x2="152.0" y2="293.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="147.0" y="215.5" width="10" height="69.6" fill="#c00"/>
<line x1="170.0" y1="276.4" x2="170.0" y2="346.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="165.0" y="285.1" width="10" height="52.2" fill="#c00"/>
<line x1="188.0" y1="311.2" x2="188.0" y2="346.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="183.0" y="319.9" width="10" height="17.4" fill="#188a3e"/>
<line x1="206.0" y1="311.2" x2="206.0" y2="404.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="201.0" y="319.9" width="10" height="75.4" fill="#c00"/>
<line x1="224.0" y1="386.6" x2="224.0" y2="467.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="219.0" y="395.3" width="10" height="63.8" fill="#c00"/>
<line x1="242.0" y1="450.4" x2="242.0" y2="572.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="237.0" y="459.1" width="10" height="104.4" fill="#c00"/>
<line x1="260.0" y1="528.7" x2="260.0" y2="609.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="255.0" y="563.5" width="10" height="5.8" fill="#c00"/>
<line x1="278.0" y1="537.4" x2="278.0" y2="580.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="273.0" y="551.9" width="10" height="17.4" fill="#188a3e"/>
<line x1="296.0" y1="479.4" x2="296.0" y2="560.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="291.0" y="488.1" width="10" height="63.8" fill="#188a3e"/>
<line x1="314.0" y1="482.3" x2="314.0" y2="522.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="309.0" y="488.1" width="10" height="14.5" fill="#c00"/>
<line x1="332.0" y1="459.1" x2="332.0" y2="508.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="327.0" y="464.9" width="10" height="37.7" fill="#188a3e"/>
<line x1="350.0" y1="421.4" x2="350.0" y2="470.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="345.0" y="430.1" width="10" height="34.8" fill="#188a3e"/>
<line x1="368.0" y1="354.7" x2="368.0" y2="435.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="363.0" y="360.5" width="10" height="69.6" fill="#188a3e"/>
<text x="296.0" y="431.4" fill="#188a3e" text-anchor="middle" style="font-weight:bold">confirmare 53.70</text>
<line x1="296.0" y1="476.4" x2="296.0" y2="435.4" stroke="#188a3e" stroke-width="1"/>
<line x1="272.0" y1="488.1" x2="404" y2="488.1" stroke="#188a3e" stroke-width="1.5"/>
<line x1="272.0" y1="509.6" x2="404" y2="509.6" stroke="#b06000" stroke-width="1.5" stroke-dasharray="3 3"/>
<line x1="272.0" y1="520.0" x2="404" y2="520.0" stroke="#b06000" stroke-width="1.5" stroke-dasharray="3 3"/>
<line x1="404" y1="488.1" x2="404" y2="551.9" stroke="#555" stroke-width="1.5"/>
<line x1="398" y1="551.9" x2="404" y2="551.9" stroke="#555" stroke-width="1.5"/>
<rect x="401" y="503.1" width="6" height="6" fill="#888" transform="rotate(45 404 506.1)"/>
<polyline points="404,488.1 434,467.1" fill="none" stroke="#188a3e" stroke-width="1.2"/>
<text x="440" y="471.1" fill="#188a3e" style="font-weight:bold">1/3 la close 53.70</text>
<polyline points="404,506.1 434,489.1" fill="none" stroke="#777" stroke-width="1.2" stroke-dasharray="2 2"/>
<text x="440" y="493.1" fill="#777" style="font-weight:bold">medie 53.39 → risc 1.84 pe acțiune (tot la close: 2.15)</text>
<polyline points="404,509.6 434,511.1" fill="none" stroke="#b06000" stroke-width="1.2" stroke-dasharray="3 3"/>
<text x="440" y="515.1" fill="#b06000" style="font-weight:bold">1/3 la 1/3 din corp 53.33</text>
<polyline points="404,520.0 434,533.1" fill="none" stroke="#b06000" stroke-width="1.2" stroke-dasharray="3 3"/>
<text x="440" y="537.1" fill="#b06000" style="font-weight:bold">1/3 la 1/2 din corp 53.15</text>
<polyline points="404,551.9 434,555.1" fill="none" stroke="#555" stroke-width="1.2"/>
<text x="440" y="559.1" fill="#555" style="font-weight:bold">corp: open 52.60 → close 53.70 = 1.10</text>
<circle cx="296.0" cy="488.1" r="3.5" fill="#fff" stroke="#188a3e" stroke-width="2"/>
<circle cx="314.0" cy="509.6" r="3.5" fill="#fff" stroke="#b06000" stroke-width="2"/>
<circle cx="314.0" cy="520.0" r="3.5" fill="#fff" stroke="#b06000" stroke-width="2"/>
<circle cx="368.0" cy="363.4" r="3.5" fill="#fff" stroke="#188a3e" stroke-width="2"/>
<line x1="314.0" y1="525.9" x2="314.0" y2="621.8" stroke="#b06000" stroke-width="1" stroke-dasharray="1 2"/>
<text x="310.0" y="632.8" fill="#b06000" style="font-weight:bold">low 53.10: umple T2 și T3</text>
<line x1="278.0" y1="583.9" x2="278.0" y2="637.8" stroke="#555" stroke-width="1" stroke-dasharray="1 2"/>
<text x="274.0" y="648.8" fill="#555" style="font-weight:bold">+1: 52.60, sub high</text>
<line x1="260.0" y1="612.9" x2="260.0" y2="653.8" stroke="#1a5fb4" stroke-width="1" stroke-dasharray="1 2"/>
<text x="256.0" y="664.8" fill="#1a5fb4" style="font-weight:bold">doji 53.00 / 51.60</text>
<text x="24" y="695" fill="#555">Măsurat pe corp (open 52.60 → close 53.70). Măsurat pe toată candela (52.45 → 53.85), 1/3 ar fi 53.38; 1/2 iese tot 53.15.</text>
<text x="24" y="712" fill="#555">Stopul e unul singur, pentru toată poziția. Barele 0-11 și 15-18 sunt construite.</text>
<svg viewBox="0 0 982 561" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif">
<text x="24" y="48" fill="#333" style="font-weight:bold">Intrarea în trei tranșe — același trade (doji 50.10 / 49.25)</text>
<rect x="218.3" y="271.0" width="20.0" height="50.0" fill="#188a3e" fill-opacity="0.08" stroke="#188a3e" stroke-width="1"/>
<line x1="24" y1="151.0" x2="968" y2="151.0" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="2 2"/>
<text x="954" y="145.0" fill="#188a3e" text-anchor="end">ținta 1: 51.60 = 1R față de close</text>
<line x1="24" y1="179.0" x2="968" y2="179.0" stroke="#1a5fb4" stroke-width="1.5" stroke-dasharray="2 2"/>
<text x="954" y="173.0" fill="#1a5fb4" text-anchor="end">ținta 1: 51.32 = 1R față de prețul mediu 50.26</text>
<line x1="24" y1="391.0" x2="968" y2="391.0" stroke="#c00" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30" y="385.0" fill="#c00">stopul: 49.20</text>
<line x1="108.3" y1="56.0" x2="108.3" y2="241.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="103.3" y="81.0" width="10" height="130.0" fill="#c00"/>
<line x1="138.3" y1="186.0" x2="138.3" y2="376.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="133.3" y="211.0" width="10" height="135.0" fill="#c00"/>
<line x1="168.3" y1="301.0" x2="168.3" y2="386.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="163.3" y="346.0" width="10" height="5.0" fill="#c00"/>
<line x1="198.3" y1="306.0" x2="198.3" y2="366.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="193.3" y="321.0" width="10" height="30.0" fill="#188a3e"/>
<line x1="228.3" y1="256.0" x2="228.3" y2="336.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="223.3" y="271.0" width="10" height="50.0" fill="#188a3e"/>
<line x1="258.3" y1="196.0" x2="258.3" y2="301.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="253.3" y="221.0" width="10" height="50.0" fill="#188a3e"/>
<line x1="288.3" y1="166.0" x2="288.3" y2="251.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="283.3" y="191.0" width="10" height="30.0" fill="#188a3e"/>
<line x1="318.3" y1="136.0" x2="318.3" y2="221.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="313.3" y="161.0" width="10" height="30.0" fill="#188a3e"/>
<line x1="417.3" y1="431.0" x2="243.3" y2="276.3" stroke="#188a3e" stroke-width="1.8"/>
<polygon points="237.3,271.0 245.9,273.3 240.6,279.3" fill="#188a3e"/>
<text x="421.3" y="428.0" fill="#188a3e" text-anchor="start" style="font-weight:bold">1/3 la close 50.40</text>
<text x="421.3" y="442.0" fill="#188a3e" text-anchor="start" style="font-weight:bold">ca să nu ratezi trade-ul dacă pleacă fără tine</text>
<line x1="417.3" y1="465.0" x2="243.0" y2="293.6" stroke="#b06000" stroke-width="1.8"/>
<polygon points="237.3,288.0 245.8,290.8 240.2,296.5" fill="#b06000"/>
<text x="421.3" y="462.0" fill="#b06000" text-anchor="start" style="font-weight:bold">1/3 cu ordin limită la 50.23 (o treime din corp)</text>
<text x="421.3" y="476.0" fill="#b06000" text-anchor="start" style="font-weight:bold">mai ieftin, dacă prețul revine</text>
<line x1="417.3" y1="499.0" x2="242.6" y2="302.0" stroke="#b06000" stroke-width="1.8"/>
<polygon points="237.3,296.0 245.6,299.3 239.6,304.6" fill="#b06000"/>
<text x="421.3" y="496.0" fill="#b06000" text-anchor="start" style="font-weight:bold">1/3 cu ordin limită la 50.15 (jumătatea corpului)</text>
<text x="421.3" y="510.0" fill="#b06000" text-anchor="start" style="font-weight:bold">și mai ieftin</text>
<line x1="348.3" y1="128.0" x2="205.9" y2="172.6" stroke="#1a5fb4" stroke-width="1.8"/>
<polygon points="198.3,175.0 204.7,168.8 207.1,176.4" fill="#1a5fb4"/>
<text x="348.3" y="109.0" fill="#1a5fb4" text-anchor="middle" style="font-weight:bold">media mai bună coboară ținta:</text>
<text x="348.3" y="123.0" fill="#1a5fb4" text-anchor="middle" style="font-weight:bold">ieși la 51.32, nu la 51.60</text>
<line x1="108.3" y1="414.0" x2="251.8" y2="309.7" stroke="#1a5fb4" stroke-width="1.8"/>
<polygon points="258.3,305.0 254.2,312.9 249.5,306.5" fill="#1a5fb4"/>
<text x="108.3" y="428.0" fill="#1a5fb4" text-anchor="middle" style="font-weight:bold">retestul: prețul revine la 50.10</text>
<text x="108.3" y="442.0" fill="#1a5fb4" text-anchor="middle" style="font-weight:bold">și umple amândouă ordinele limită</text>
<text x="24" y="549" fill="#555">Paranteza de pe candela de confirmare e corpul ei (49.90 → 50.40): pe el se măsoară 1/3 și 1/2. Stopul e unul singur. Exemplu construit.</text>
<polyline points="216.3,271.0 211.3,271.0 211.3,321.0 216.3,321.0" fill="none" stroke="#555" stroke-width="2"/>
<line x1="211.3" y1="271.0" x2="236.3" y2="271.0" stroke="#188a3e" stroke-width="1.5"/>
<line x1="211.3" y1="288.0" x2="236.3" y2="288.0" stroke="#b06000" stroke-width="1.5" stroke-dasharray="3 3"/>
<line x1="211.3" y1="296.0" x2="236.3" y2="296.0" stroke="#b06000" stroke-width="1.5" stroke-dasharray="3 3"/>
<circle cx="228.3" cy="271.0" r="4" fill="#fff" stroke="#188a3e" stroke-width="2"/>
<circle cx="258.3" cy="288.0" r="4" fill="#fff" stroke="#b06000" stroke-width="2"/>
<circle cx="258.3" cy="296.0" r="4" fill="#fff" stroke="#b06000" stroke-width="2"/>
<polyline points="353.3,271.0 358.3,271.0 358.3,391.0 353.3,391.0" fill="none" stroke="#c00" stroke-width="1.5"/>
<text x="364.3" y="335.0" fill="#c00" style="font-weight:bold">risc 1.20 pe acțiune (tot la close)</text>
<polyline points="603.3,285.0 608.3,285.0 608.3,391.0 603.3,391.0" fill="none" stroke="#1a5fb4" stroke-width="1.5"/>
<text x="614.3" y="342.0" fill="#1a5fb4" style="font-weight:bold">risc 1.06 pe acțiune (cu tranșe, preț mediu 50.26)</text>
</svg>

Before

Width:  |  Height:  |  Size: 6.6 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

@@ -8,10 +8,10 @@ trendului sunt numerotate sub bară, ca numărătoarea să se vadă.
"""
import re
import sys; sys.path.insert(0, "/workspace/atm-curs-dl")
from svg_candles import Candle, Chart, Mark
from svg_candles import Arrow, Candle, Chart, Mark, Zone
OUT = "/workspace/atm-curs-dl/gen/strategii/buy_doji_trend.svg"
DOJI = (49.65, 50.10, 49.20, 49.60)
DOJI = (49.65, 50.10, 49.25, 49.60)
CONF = (49.60, 50.55, 49.45, 50.40)
@@ -54,12 +54,20 @@ def numbers(ch, idx, color):
for n, i in enumerate(idx, 1)]
def bracket(ch, a, b, y, text, color):
xa, xb = ch._cx(a) - 6, ch._cx(b) + 6
return [f'<polyline points="{xa:.1f},{y + 6:.1f} {xa:.1f},{y:.1f} {xb:.1f},{y:.1f} '
f'{xb:.1f},{y + 6:.1f}" fill="none" stroke="{color}" stroke-width="1.3"/>',
f'<text x="{xb + 8:.1f}" y="{y + 4:.1f}" fill="{color}" '
f'style="font-weight:bold">{text}</text>']
def render_keep_offsets(ch):
"""`Chart.render()` restaurează top/left după desen, deci `_y`/`_cx` de
după el dau coordonate deplasate față de body-ul randat (titlul și
etichetele zonelor mută graficul în jos). `_render()` lasă offset-urile
puse, exact ce ne trebuie ca extra-urile desenate de mână să pice la locul
lor. Se cheamă o singură dată per Chart."""
return ch._render()
def fits(ch, svg):
"""Chart mută graficul dacă un text ar ieși din pânză — aici mutarea ar
dezalinia cele două panouri, deci verificăm că nu s-a întâmplat."""
assert f'viewBox="0 0 {ch.width} ' in svg, \
f"Chart a lărgit pânza ({svg[:60]}): textul unei săgeți iese din {ch.width}px"
def body(svg):
@@ -68,32 +76,35 @@ def body(svg):
# --- panoul de sus: 9 candele ------------------------------------------------
top = Chart(candles=[Candle(*b) for b in L], left=44 + GAP, # dojiul pe aceeași verticală
marks=[Mark(10, "doji", ORANGE, "below", dy=8),
Mark(11, "confirmare 50.40", GREEN, "above")],
title="Trendul dinaintea dojiului: 9 candele vs. 3 candele — exemplu construit",
marks=[Mark(11, "confirmare 50.40", GREEN, "above")],
zones=[Zone(1, 9, "9 candele de scădere — ideal", GREEN)],
arrows=[Arrow(10, "doji la capătul scăderii\nvânzătorii s-au terminat",
where="below", color=ORANGE, dx=70)],
top=54, # titlul se desenează de mână: cel din Chart ar cădea peste eticheta zonei
**common)
svg_top = top.render()
y_br = top._y(max(b[1] for b in L[1:10])) - 10
ext_top = numbers(top, range(1, 10), RED) + bracket(top, 1, 9, y_br, "downtrend 9 candele", RED)
y_cap1 = top._y(DOJI[2]) + 50
svg_top = render_keep_offsets(top)
fits(top, svg_top)
ext_top = numbers(top, range(1, 10), RED) + [
'<text x="24" y="22" fill="#333" style="font-weight:bold">Trendul dinaintea dojiului: '
'9 candele vs. 3 candele — exemplu construit</text>']
y_cap1 = max(top._y(DOJI[2]) + 50, top._arrow_geom(top.arrows[0])["box"][3] + 24)
ext_top.append(f'<text x="24" y="{y_cap1:.1f}" fill="{GREEN}" style="font-weight:bold">'
f'DA — ideal (8-10 candele)</text>')
# --- panoul de jos: range + 3 candele ----------------------------------------
y_sep = y_cap1 + 16
bot = Chart(candles=[Candle(*b) for b in R], left=44,
marks=[Mark(11, "doji", ORANGE, "below", dy=8),
marks=[Mark(11, "doji", ORANGE, "below", dy=22),
Mark(12, "confirmare 50.40", GREEN, "above")],
top=int(y_sep + 62), **common) # titlul și paranteza range-ului, desenate mai jos
svg_bot = bot.render()
y_rg = bot._y(max(b[1] for b in R[0:8])) - 10
zones=[Zone(8, 10, "doar 3 candele — merge, dar mai slab", ORANGE)],
arrows=[Arrow(3, "înainte: preț pe loc,\nnu scădere — de aceea\nsemnalul e mai slab",
where="above", color=GREY)],
top=int(y_sep + 118), **common) # loc pentru titlul panoului și textul săgeții
svg_bot = render_keep_offsets(bot)
fits(bot, svg_bot)
ext_bot = (numbers(bot, range(8, 11), RED)
+ bracket(bot, 8, 10, bot._y(R[8][1]) - 10, "doar 3 candele", RED)
+ bracket(bot, 0, 7, y_rg, "", GREY)
+ [f'<text x="24" y="{y_sep + 24:.1f}" fill="#333" style="font-weight:bold">'
f'Același doji, după un range</text>',
f'<text x="{bot._cx(0) - 6:.1f}" y="{y_rg - 5:.1f}" fill="{GREY}">'
f'range: nu se numără</text>'])
f'Același doji, după un range</text>'])
y_cap2 = bot._y(DOJI[2]) + 50
ext_bot += [f'<text x="24" y="{y_cap2:.1f}" fill="{ORANGE}" style="font-weight:bold">'
f'ACCEPTAT, semnal mai slab</text>',

View File

@@ -5,11 +5,12 @@ destinație: summaries/17_STRATEGII/01_buy_doji.md, Pasul 3, după doji_form
cheie markdown: <!-- DIAGRAMA: trend -->
titlu SVG: „Trendul dinaintea dojiului: 9 candele vs. 3 candele — exemplu construit"
stil: candele lipite (gap 15-18, body_w 9-10), fără volum; open = close anterior;
adnotări „ca la proști": zone dreptunghiulare + săgeți cu text (CE + DE CE).
fitile implicite 0.15 peste/sub corp, cu excepțiile de mai jos.
CE TREBUIE SĂ DEMONSTREZE
-------------------------
Același doji (h 50.10 / l 49.20) și aceeași confirmare (close 50.40), după
Același doji (h 50.10 / l 49.25) și aceeași confirmare (close 50.40), după
două trenduri diferite. Stânga = ideal (9 candele). Dreapta = acceptat, dar
semnal mai slab (3 candele după un range) — și e cazul pe care scannerul cu
„Since Bear ≥ 8" nu-l găsește.
@@ -18,18 +19,22 @@ PANOUL STÂNGA — 12 bare
-----------------------
open[0] = 55.50; close-uri 0-9: 55.00, 54.30, 54.60, 53.60, 52.90, 53.10, 52.00,
51.20, 50.60, 49.65 (barele 1-9 = trendul de 9 candele)
10 doji (49.65, 50.10, 49.20, 49.60)
10 doji (49.65, 50.10, 49.25, 49.60)
11 confirmare (49.60, 50.55, 49.45, 50.40)
Mark(1..9 paranteză, "downtrend 9 candele"), Mark(10,"doji"), Mark(11,"confirmare 50.40").
Zone(1..9) verde, etichetă „9 candele de scădere — ideal"; numerele 1..9 sub bare;
săgeată pe doji: „doji la capătul scăderii / vânzătorii s-au terminat".
Mark(11,"confirmare 50.40").
Text sub panou: „DA — ideal (8-10 candele)".
PANOUL DREAPTA — 13 bare
------------------------
open[0] = 51.40; close-uri 0-7 (range): 51.70, 51.20, 51.60, 51.10, 51.50,
51.30, 51.70, 51.40; apoi 8: 50.90, 9: 50.30, 10: 49.65 (3 candele în jos)
11 doji (49.65, 50.10, 49.20, 49.60)
11 doji (49.65, 50.10, 49.25, 49.60)
12 confirmare (49.60, 50.55, 49.45, 50.40)
Mark(8..10 paranteză, "doar 3 candele"), Mark(12,"confirmare 50.40").
Zone(8..10) portocalie, etichetă „doar 3 candele — merge, dar mai slab"; numerele
1..3 sub bare; săgeată pe range (bara 3): „înainte: preț pe loc, / nu scădere — de
aceea / semnalul e mai slab". Mark(11,"doji"), Mark(12,"confirmare 50.40").
Text sub panou: „ACCEPTAT, semnal mai slab · scannerul cu Since Bear ≥ 8 nu-l vede".
ASSERT-URI
@@ -42,6 +47,14 @@ ASSERT-URI
close[8] > close[9] > close[10] (exact 3 candele în jos).
5. Confirmarea închide peste 50.10 pe ambele.
NOTĂ DE RANDARE
---------------
Extra-urile desenate de mână (numere, titlu) folosesc `ch._render()`, nu
`ch.render()`: al doilea restaurează top/left după desen, deci `_y`/`_cx` ar da
coordonate deplasate cu offset-ul pe care Chart îl pune pentru titlu și pentru
etichetele zonelor. Titlul panoului de sus e desenat de mână din același motiv
(titlul din Chart cade exact peste eticheta zonei).
SURSA
-----
- 8-10 candele ideal; 2-3 candele au funcționat, semnal mai slab:

View File

@@ -1,81 +1,86 @@
<svg viewBox="0 0 540 536" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif">
<text x="24" y="48" fill="#333" style="font-weight:bold">Trendul dinaintea dojiului: 9 candele vs. 3 candele — exemplu construit</text>
<line x1="62.0" y1="56.0" x2="62.0" y2="80.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="57.0" y="60.5" width="10" height="15.0" fill="#c00"/>
<line x1="80.0" y1="71.0" x2="80.0" y2="101.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="75.0" y="75.5" width="10" height="21.0" fill="#c00"/>
<line x1="98.0" y1="83.0" x2="98.0" y2="101.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="93.0" y="87.5" width="10" height="9.0" fill="#188a3e"/>
<line x1="116.0" y1="83.0" x2="116.0" y2="122.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="111.0" y="87.5" width="10" height="30.0" fill="#c00"/>
<line x1="134.0" y1="113.0" x2="134.0" y2="143.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="129.0" y="117.5" width="10" height="21.0" fill="#c00"/>
<line x1="152.0" y1="128.0" x2="152.0" y2="143.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="147.0" y="132.5" width="10" height="6.0" fill="#188a3e"/>
<line x1="170.0" y1="128.0" x2="170.0" y2="170.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="165.0" y="132.5" width="10" height="33.0" fill="#c00"/>
<line x1="188.0" y1="161.0" x2="188.0" y2="194.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="183.0" y="165.5" width="10" height="24.0" fill="#c00"/>
<line x1="206.0" y1="185.0" x2="206.0" y2="212.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="201.0" y="189.5" width="10" height="18.0" fill="#c00"/>
<line x1="224.0" y1="203.0" x2="224.0" y2="240.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="219.0" y="207.5" width="10" height="28.5" fill="#c00"/>
<line x1="242.0" y1="222.5" x2="242.0" y2="249.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="237.0" y="236.0" width="10" height="1.6" fill="#c00"/>
<line x1="260.0" y1="209.0" x2="260.0" y2="242.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="255.0" y="213.5" width="10" height="24.0" fill="#188a3e"/>
<text x="242.0" y="263.5" fill="#b06000" text-anchor="middle" style="font-weight:bold">doji</text>
<text x="260.0" y="199.0" fill="#188a3e" text-anchor="middle" style="font-weight:bold">confirmare 50.40</text>
<text x="80.0" y="115.0" fill="#c00" text-anchor="middle" style="font-weight:bold;font-size:11px">1</text>
<text x="98.0" y="115.0" fill="#c00" text-anchor="middle" style="font-weight:bold;font-size:11px">2</text>
<text x="116.0" y="136.0" fill="#c00" text-anchor="middle" style="font-weight:bold;font-size:11px">3</text>
<text x="134.0" y="157.0" fill="#c00" text-anchor="middle" style="font-weight:bold;font-size:11px">4</text>
<text x="152.0" y="157.0" fill="#c00" text-anchor="middle" style="font-weight:bold;font-size:11px">5</text>
<text x="170.0" y="184.0" fill="#c00" text-anchor="middle" style="font-weight:bold;font-size:11px">6</text>
<text x="188.0" y="208.0" fill="#c00" text-anchor="middle" style="font-weight:bold;font-size:11px">7</text>
<text x="206.0" y="226.0" fill="#c00" text-anchor="middle" style="font-weight:bold;font-size:11px">8</text>
<text x="224.0" y="254.5" fill="#c00" text-anchor="middle" style="font-weight:bold;font-size:11px">9</text>
<polyline points="74.0,67.0 74.0,61.0 230.0,61.0 230.0,67.0" fill="none" stroke="#c00" stroke-width="1.3"/>
<text x="238.0" y="65.0" fill="#c00" style="font-weight:bold">downtrend 9 candele</text>
<text x="24" y="299.5" fill="#188a3e" style="font-weight:bold">DA — ideal (8-10 candele)</text>
<line x1="24" y1="315" x2="526" y2="315" stroke="#ccc"/>
<line x1="44.0" y1="377.0" x2="44.0" y2="395.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="39.0" y="381.5" width="10" height="9.0" fill="#188a3e"/>
<line x1="62.0" y1="377.0" x2="62.0" y2="401.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="57.0" y="381.5" width="10" height="15.0" fill="#c00"/>
<line x1="80.0" y1="380.0" x2="80.0" y2="401.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="75.0" y="384.5" width="10" height="12.0" fill="#188a3e"/>
<line x1="98.0" y1="380.0" x2="98.0" y2="404.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="93.0" y="384.5" width="10" height="15.0" fill="#c00"/>
<line x1="116.0" y1="383.0" x2="116.0" y2="404.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="111.0" y="387.5" width="10" height="12.0" fill="#188a3e"/>
<line x1="134.0" y1="383.0" x2="134.0" y2="398.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="129.0" y="387.5" width="10" height="6.0" fill="#c00"/>
<line x1="152.0" y1="377.0" x2="152.0" y2="398.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="147.0" y="381.5" width="10" height="12.0" fill="#188a3e"/>
<line x1="170.0" y1="377.0" x2="170.0" y2="395.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="165.0" y="381.5" width="10" height="9.0" fill="#c00"/>
<line x1="188.0" y1="386.0" x2="188.0" y2="410.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="183.0" y="390.5" width="10" height="15.0" fill="#c00"/>
<line x1="206.0" y1="401.0" x2="206.0" y2="428.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="201.0" y="405.5" width="10" height="18.0" fill="#c00"/>
<line x1="224.0" y1="419.0" x2="224.0" y2="447.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="219.0" y="423.5" width="10" height="19.5" fill="#c00"/>
<line x1="242.0" y1="429.5" x2="242.0" y2="456.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="237.0" y="443.0" width="10" height="1.6" fill="#c00"/>
<line x1="260.0" y1="416.0" x2="260.0" y2="449.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="255.0" y="420.5" width="10" height="24.0" fill="#188a3e"/>
<text x="242.0" y="470.5" fill="#b06000" text-anchor="middle" style="font-weight:bold">doji</text>
<text x="260.0" y="406.0" fill="#188a3e" text-anchor="middle" style="font-weight:bold">confirmare 50.40</text>
<text x="188.0" y="424.0" fill="#c00" text-anchor="middle" style="font-weight:bold;font-size:11px">1</text>
<text x="206.0" y="442.0" fill="#c00" text-anchor="middle" style="font-weight:bold;font-size:11px">2</text>
<text x="224.0" y="461.5" fill="#c00" text-anchor="middle" style="font-weight:bold;font-size:11px">3</text>
<polyline points="182.0,382.0 182.0,376.0 230.0,376.0 230.0,382.0" fill="none" stroke="#c00" stroke-width="1.3"/>
<text x="238.0" y="380.0" fill="#c00" style="font-weight:bold">doar 3 candele</text>
<polyline points="38.0,373.0 38.0,367.0 176.0,367.0 176.0,373.0" fill="none" stroke="#555" stroke-width="1.3"/>
<text x="184.0" y="371.0" fill="#555" style="font-weight:bold"></text>
<text x="24" y="339.5" fill="#333" style="font-weight:bold">Același doji, după un range</text>
<text x="38.0" y="362.0" fill="#555">range: nu se numără</text>
<text x="24" y="506.5" fill="#b06000" style="font-weight:bold">ACCEPTAT, semnal mai slab</text>
<text x="24" y="523.5" fill="#555">scannerul cu Since Bear ≥ 8 nu-l vede</text>
<svg viewBox="0 0 540 622" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif">
<rect x="70.0" y="61.0" width="164.0" height="185.5" fill="#188a3e" fill-opacity="0.08" stroke="#188a3e" stroke-width="1"/>
<text x="70.0" y="56.0" fill="#188a3e" style="font-weight:bold">9 candele de scădere — ideal</text>
<line x1="62.0" y1="54.0" x2="62.0" y2="78.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="57.0" y="58.5" width="10" height="15.0" fill="#c00"/>
<line x1="80.0" y1="69.0" x2="80.0" y2="99.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="75.0" y="73.5" width="10" height="21.0" fill="#c00"/>
<line x1="98.0" y1="81.0" x2="98.0" y2="99.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="93.0" y="85.5" width="10" height="9.0" fill="#188a3e"/>
<line x1="116.0" y1="81.0" x2="116.0" y2="120.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="111.0" y="85.5" width="10" height="30.0" fill="#c00"/>
<line x1="134.0" y1="111.0" x2="134.0" y2="141.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="129.0" y="115.5" width="10" height="21.0" fill="#c00"/>
<line x1="152.0" y1="126.0" x2="152.0" y2="141.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="147.0" y="130.5" width="10" height="6.0" fill="#188a3e"/>
<line x1="170.0" y1="126.0" x2="170.0" y2="168.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="165.0" y="130.5" width="10" height="33.0" fill="#c00"/>
<line x1="188.0" y1="159.0" x2="188.0" y2="192.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="183.0" y="163.5" width="10" height="24.0" fill="#c00"/>
<line x1="206.0" y1="183.0" x2="206.0" y2="210.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="201.0" y="187.5" width="10" height="18.0" fill="#c00"/>
<line x1="224.0" y1="201.0" x2="224.0" y2="238.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="219.0" y="205.5" width="10" height="28.5" fill="#c00"/>
<line x1="242.0" y1="220.5" x2="242.0" y2="246.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="237.0" y="234.0" width="10" height="1.6" fill="#c00"/>
<line x1="260.0" y1="207.0" x2="260.0" y2="240.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="255.0" y="211.5" width="10" height="24.0" fill="#188a3e"/>
<text x="260.0" y="197.0" fill="#188a3e" text-anchor="middle" style="font-weight:bold">confirmare 50.40</text>
<line x1="312.0" y1="276.0" x2="249.5" y2="252.8" stroke="#b06000" stroke-width="1.8"/>
<polygon points="242.0,250.0 250.9,249.0 248.1,256.5" fill="#b06000"/>
<text x="312.0" y="290.0" fill="#b06000" text-anchor="middle" style="font-weight:bold">doji la capătul scăderii</text>
<text x="312.0" y="304.0" fill="#b06000" text-anchor="middle" style="font-weight:bold">vânzătorii s-au terminat</text>
<text x="80.0" y="113.0" fill="#c00" text-anchor="middle" style="font-weight:bold;font-size:11px">1</text>
<text x="98.0" y="113.0" fill="#c00" text-anchor="middle" style="font-weight:bold;font-size:11px">2</text>
<text x="116.0" y="134.0" fill="#c00" text-anchor="middle" style="font-weight:bold;font-size:11px">3</text>
<text x="134.0" y="155.0" fill="#c00" text-anchor="middle" style="font-weight:bold;font-size:11px">4</text>
<text x="152.0" y="155.0" fill="#c00" text-anchor="middle" style="font-weight:bold;font-size:11px">5</text>
<text x="170.0" y="182.0" fill="#c00" text-anchor="middle" style="font-weight:bold;font-size:11px">6</text>
<text x="188.0" y="206.0" fill="#c00" text-anchor="middle" style="font-weight:bold;font-size:11px">7</text>
<text x="206.0" y="224.0" fill="#c00" text-anchor="middle" style="font-weight:bold;font-size:11px">8</text>
<text x="224.0" y="252.5" fill="#c00" text-anchor="middle" style="font-weight:bold;font-size:11px">9</text>
<text x="24" y="22" fill="#333" style="font-weight:bold">Trendul dinaintea dojiului: 9 candele vs. 3 candele — exemplu construit</text>
<text x="24" y="331.0" fill="#188a3e" style="font-weight:bold">DA — ideal (8-10 candele)</text>
<line x1="24" y1="347" x2="526" y2="347" stroke="#ccc"/>
<rect x="178.0" y="465.0" width="56.0" height="77.5" fill="#b06000" fill-opacity="0.08" stroke="#b06000" stroke-width="1"/>
<text x="178.0" y="460.0" fill="#b06000" style="font-weight:bold">doar 3 candele — merge, dar mai slab</text>
<line x1="44.0" y1="464.0" x2="44.0" y2="482.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="39.0" y="468.5" width="10" height="9.0" fill="#188a3e"/>
<line x1="62.0" y1="464.0" x2="62.0" y2="488.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="57.0" y="468.5" width="10" height="15.0" fill="#c00"/>
<line x1="80.0" y1="467.0" x2="80.0" y2="488.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="75.0" y="471.5" width="10" height="12.0" fill="#188a3e"/>
<line x1="98.0" y1="467.0" x2="98.0" y2="491.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="93.0" y="471.5" width="10" height="15.0" fill="#c00"/>
<line x1="116.0" y1="470.0" x2="116.0" y2="491.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="111.0" y="474.5" width="10" height="12.0" fill="#188a3e"/>
<line x1="134.0" y1="470.0" x2="134.0" y2="485.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="129.0" y="474.5" width="10" height="6.0" fill="#c00"/>
<line x1="152.0" y1="464.0" x2="152.0" y2="485.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="147.0" y="468.5" width="10" height="12.0" fill="#188a3e"/>
<line x1="170.0" y1="464.0" x2="170.0" y2="482.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="165.0" y="468.5" width="10" height="9.0" fill="#c00"/>
<line x1="188.0" y1="473.0" x2="188.0" y2="497.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="183.0" y="477.5" width="10" height="15.0" fill="#c00"/>
<line x1="206.0" y1="488.0" x2="206.0" y2="515.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="201.0" y="492.5" width="10" height="18.0" fill="#c00"/>
<line x1="224.0" y1="506.0" x2="224.0" y2="534.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="219.0" y="510.5" width="10" height="19.5" fill="#c00"/>
<line x1="242.0" y1="516.5" x2="242.0" y2="542.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="237.0" y="530.0" width="10" height="1.6" fill="#c00"/>
<line x1="260.0" y1="503.0" x2="260.0" y2="536.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="255.0" y="507.5" width="10" height="24.0" fill="#188a3e"/>
<text x="242.0" y="556.0" fill="#b06000" text-anchor="middle" style="font-weight:bold">doji</text>
<text x="260.0" y="493.0" fill="#188a3e" text-anchor="middle" style="font-weight:bold">confirmare 50.40</text>
<line x1="98.0" y1="437.0" x2="98.0" y2="455.0" stroke="#555" stroke-width="1.8"/>
<polygon points="98.0,463.0 94.0,455.0 102.0,455.0" fill="#555"/>
<text x="98.0" y="404.0" fill="#555" text-anchor="middle" style="font-weight:bold">înainte: preț pe loc,</text>
<text x="98.0" y="418.0" fill="#555" text-anchor="middle" style="font-weight:bold">nu scădere — de aceea</text>
<text x="98.0" y="432.0" fill="#555" text-anchor="middle" style="font-weight:bold">semnalul e mai slab</text>
<text x="188.0" y="511.0" fill="#c00" text-anchor="middle" style="font-weight:bold;font-size:11px">1</text>
<text x="206.0" y="529.0" fill="#c00" text-anchor="middle" style="font-weight:bold;font-size:11px">2</text>
<text x="224.0" y="548.5" fill="#c00" text-anchor="middle" style="font-weight:bold;font-size:11px">3</text>
<text x="24" y="371.0" fill="#333" style="font-weight:bold">Același doji, după un range</text>
<text x="24" y="592.0" fill="#b06000" style="font-weight:bold">ACCEPTAT, semnal mai slab</text>
<text x="24" y="609.0" fill="#555">scannerul cu Since Bear ≥ 8 nu-l vede</text>
</svg>

Before

Width:  |  Height:  |  Size: 6.9 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

View File

@@ -214,6 +214,6 @@ capitolului respectiv, secțiunea 2.2 (A+ vs. mediocru), apoi A2.</p>
<li><strong>Patru sesiuni de analiză zilnică nu sunt ținute de autor</strong> (25, 26, 29 și
30 iunie 2026 — un înlocuitor). Regulile care se sprijineau doar pe zilele
alea au fost scoase din material încă de la sumarizare.</li>
</ul><nav class="pager"><a class="prev" href="00_SHORTLIST.html">← 00. Shortlist: ce merită să înveți, în ce ordine</a><a class="up" href="../index.html#17_STRATEGII">↑ index</a><a class="next" href="01_buy_doji.html">01. 1. Buy Doji / Sell Doji (Strategia 3 / BYH) →</a></nav>
</ul><nav class="pager"><a class="prev" href="00_SHORTLIST.html">← 00. Shortlist: ce merită să înveți, în ce ordine</a><a class="up" href="../index.html#17_STRATEGII">↑ index</a><a class="next" href="01_buy_doji.html">01. 1. Buy Doji / Sell Doji (Strategia 3) →</a></nav>
</body>
</html>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1432,6 +1432,6 @@ long-only. Rămâne miezul logic — doi pivoți, crossing, close peste pivotul
<li>Filtrele dinainte de strategie: <a href="04_selectia.html"><code>04_selectia.md</code></a>.</li>
<li>Risc și execuție: <a href="A1_risc.html"><code>A1_risc.md</code></a>.</li>
<li>Regula de trail și money management, integral: <a href="../03_MODUL_2/14_strategia_1_m2d.html"><code>03_MODUL_2/14_strategia_1_m2d.md</code></a>.</li>
</ul><nav class="pager"><a class="prev" href="01_buy_doji.html">← 01. 1. Buy Doji / Sell Doji (Strategia 3 / BYH)</a><a class="up" href="../index.html#17_STRATEGII">↑ index</a><a class="next" href="03_m2d.html">03. 3. M2D (Strategia 1, Mecanic 2 Time Frame-uri) →</a></nav>
</ul><nav class="pager"><a class="prev" href="01_buy_doji.html">← 01. 1. Buy Doji / Sell Doji (Strategia 3)</a><a class="up" href="../index.html#17_STRATEGII">↑ index</a><a class="next" href="03_m2d.html">03. 3. M2D (Strategia 1, Mecanic 2 Time Frame-uri) →</a></nav>
</body>
</html>

File diff suppressed because one or more lines are too long

View File

@@ -89,6 +89,37 @@ class MA:
_check_dash(self.dash, "MA")
@dataclass
class Zone:
"""Dreptunghi de evidențiere peste candelele i0..i1, desenat în spatele lor."""
i0: int # prima candelă acoperită
i1: int # ultima candelă acoperită (inclusiv)
text: str = "" # eticheta zonei, deasupra dreptunghiului
color: str = "#1a5fb4"
p_top: float | None = None # implicit: cel mai mare high din interval + 8 px
p_bot: float | None = None # implicit: cel mai mic low din interval + 8 px
def __post_init__(self) -> None:
if not 0 <= self.i0 <= self.i1:
raise ValueError(f"Zone(i0={self.i0}, i1={self.i1}): astept 0 <= i0 <= i1")
@dataclass
class Arrow:
"""Săgeată cu text spre o candelă: „aici intri / aici stopul / aici ținta"."""
i: int # candela țintită
text: str # textul săgeții; "\n" rupe rândul
price: float | None = None # implicit: high (above), low (below), close (left/right)
where: str = "above" # "above" | "below" | "left" | "right" — unde stă textul
color: str = "#1a5fb4"
dx: float = 0.0 # mută textul (și coada săgeții); vârful rămâne pe țintă
dy: float = 0.0
def __post_init__(self) -> None:
if self.where not in ("above", "below", "left", "right"):
raise ValueError(f"Arrow.where={self.where!r}, astept above/below/left/right")
@dataclass
class Chart:
candles: list[Candle]
@@ -108,6 +139,17 @@ class Chart:
vol_gap: float = 26.0 # spațiu între panoul de preț și cel de volum
vol_label: str = "volum"
title: str = "" # ex. "SPY — daily"
zones: list[Zone] = field(default_factory=list)
arrows: list[Arrow] = field(default_factory=list)
def __post_init__(self) -> None:
n = len(self.candles)
for z in self.zones:
if z.i1 >= n:
raise ValueError(f"Zone(i0={z.i0}, i1={z.i1}): graficul are doar {n} candele")
for a in self.arrows:
if not 0 <= a.i < n:
raise ValueError(f"Arrow(i={a.i}): graficul are doar {n} candele")
def _y(self, price: float) -> float:
return self.top + (self._pmax - price) * self.scale
@@ -115,10 +157,80 @@ class Chart:
def _cx(self, i: int) -> float:
return self.left + i * self.gap
def _zone_box(self, z: Zone) -> tuple[float, float, float, float]:
cds = self.candles[z.i0:z.i1 + 1]
pad = self.body_w / 2 + 5
y0 = self._y(z.p_top) if z.p_top is not None else self._y(max(c.h for c in cds)) - 8
y1 = self._y(z.p_bot) if z.p_bot is not None else self._y(min(c.l for c in cds)) + 8
return self._cx(z.i0) - pad, y0, self._cx(z.i1) + pad, y1
def _zone_label_y(self, z: Zone) -> float:
"""Baseline-ul etichetei: deasupra zonei și a candelelor din dreptul textului."""
x0, y0, _, _ = self._zone_box(z)
x1 = x0 + len(z.text) * 6.2
tops = [self._y(c.h) for j, c in enumerate(self.candles)
if x0 - self.body_w / 2 < self._cx(j) < x1 + self.body_w / 2]
return min([y0] + [t - 4 for t in tops]) - 5
def _arrow_geom(self, a: Arrow) -> dict:
"""Vârf, coadă, rânduri de text și bbox-ul textului (x0, x1, ytop, ybot)."""
LH, CW = 14, 6.2 # înălțime rând, lățime caracter bold 12px
cd, cx = self.candles[a.i], self._cx(a.i)
lines = a.text.split("\n")
tw = max(len(t) for t in lines) * CW
if a.where in ("above", "below"):
up = a.where == "above"
price = a.price if a.price is not None else (cd.h if up else cd.l)
tip = (cx, self._y(price) + (-4 if up else 4))
# textul stă peste candelele vecine din dreptul lui: urcă/coboară
# peste cea mai extremă, altfel acoperă fitilele
near = [c for j, c in enumerate(self.candles)
if abs(self._cx(j) - cx - a.dx) < tw / 2 + self.body_w] + [cd]
if up:
ty = min(tip[1] - 26, min(self._y(c.h) for c in near) - 8) + a.dy
base = [ty - 5 - LH * k for k in range(len(lines))][::-1]
else:
ty = max(tip[1] + 26, max(self._y(c.l) for c in near) + 8) + a.dy
base = [ty + 14 + LH * k for k in range(len(lines))]
tail, tx, anchor = (cx + a.dx, ty), cx + a.dx, "middle"
x0 = tx - tw / 2
else:
sgn = 1 if a.where == "right" else -1
price = a.price if a.price is not None else cd.c
tip = (cx + sgn * (self.body_w / 2 + 4), self._y(price))
tail = (tip[0] + sgn * 30 + a.dx, tip[1] + a.dy)
tx = tail[0] + sgn * 4
base = [tail[1] + 4 - LH * (len(lines) - 1) / 2 + LH * k for k in range(len(lines))]
anchor = "start" if sgn > 0 else "end"
x0 = tx if sgn > 0 else tx - tw
return dict(tip=tip, tail=tail, tx=tx, anchor=anchor, lines=lines, base=base,
box=(x0, x0 + tw, base[0] - 11, base[-1] + 3))
def render(self) -> str:
# _render mută top/left/width ca să facă loc titlului, trendului și
# săgeților; le restaurăm, altfel a doua randare a aceluiași Chart iese deplasată
saved = self.top, self.left, self.width
try:
return self._render()
finally:
self.top, self.left, self.width = saved
def _render(self) -> str:
prices = [p for c in self.candles for p in (c.o, c.h, c.l, c.c)]
prices += [lv.price for lv in self.levels]
prices += [p for z in self.zones for p in (z.p_top, z.p_bot) if p is not None]
prices += [a.price for a in self.arrows if a.price is not None]
self._pmax, pmin = max(prices), min(prices)
# textul săgeților și etichetele zonelor nu au voie să iasă din pânză:
# mută graficul în jos / la dreapta și lărgește canvasul cât e nevoie
boxes = [self._arrow_geom(a)["box"] for a in self.arrows]
boxes += [(x0, x0 + len(z.text) * 6.2, self._zone_label_y(z) - 11, y0)
for z in self.zones if z.text for x0, y0, _, _ in [self._zone_box(z)]]
if boxes:
self.top += max(0, 14 - min(b[2] for b in boxes))
shift = max(0, 6 - min(b[0] for b in boxes))
self.left += shift
self.width = max(self.width + int(shift), int(max(b[1] for b in boxes) + shift + 8))
if self.title:
self.top += 22
# segmentul de trend iese din zona candelelor: rezervă loc pentru el,
@@ -127,6 +239,10 @@ class Chart:
self.top += 56
body_bottom = self.top + (self._pmax - pmin) * self.scale
extra = 62 if self.trend == "up" else 0
low = [self._arrow_geom(a)["box"][3] for a in self.arrows]
low += [self._zone_box(z)[3] for z in self.zones]
if low:
extra = max(extra, max(low) - body_bottom + 6)
panel_bottom = body_bottom + extra
vols = [c.vol for c in self.candles if c.vol is not None]
@@ -148,6 +264,15 @@ class Chart:
out.append(f'<text x="24" y="{self.top - (56 if self.trend == "down" else 0) - 8:.0f}" '
f'fill="#333" style="font-weight:bold">{self.title}</text>')
# zonele primele, ca să stea în spatele nivelurilor și candelelor
for z in self.zones:
x0, y0, x1, y1 = self._zone_box(z)
out.append(f'<rect x="{x0:.1f}" y="{y0:.1f}" width="{x1 - x0:.1f}" height="{y1 - y0:.1f}" '
f'fill="{z.color}" fill-opacity="0.08" stroke="{z.color}" stroke-width="1"/>')
if z.text:
out.append(f'<text x="{x0:.1f}" y="{self._zone_label_y(z):.1f}" fill="{z.color}" '
f'style="font-weight:bold">{z.text}</text>')
# nivelurile: linie pe toată lățimea, eticheta deasupra liniei
for lv in self.levels:
y = self._y(lv.price)
@@ -234,6 +359,23 @@ class Chart:
out.append(f'<text x="{cx:.1f}" y="{y:.1f}" fill="{mk.color}" '
f'text-anchor="{anchor}" style="font-weight:bold">{mk.text}</text>')
# săgețile: linie de la text la țintă + vârf triunghi (nu marker, ca
# să nu depindă de suportul <defs> în randare); un <text> per rând,
# ca audit_diagrams.py să le măsoare corect
for a in self.arrows:
g = self._arrow_geom(a)
(x1, y1), (x2, y2) = g["tail"], g["tip"]
d = max(((x2 - x1) ** 2 + (y2 - y1) ** 2) ** 0.5, 1e-9)
ux, uy = (x2 - x1) / d, (y2 - y1) / d
bx, by = x2 - 8 * ux, y2 - 8 * uy
out.append(f'<line x1="{x1:.1f}" y1="{y1:.1f}" x2="{bx:.1f}" y2="{by:.1f}" '
f'stroke="{a.color}" stroke-width="1.8"/>')
out.append(f'<polygon points="{x2:.1f},{y2:.1f} {bx - 4 * uy:.1f},{by + 4 * ux:.1f} '
f'{bx + 4 * uy:.1f},{by - 4 * ux:.1f}" fill="{a.color}"/>')
for t, y in zip(g["lines"], g["base"]):
out.append(f'<text x="{g["tx"]:.1f}" y="{y:.1f}" fill="{a.color}" '
f'text-anchor="{g["anchor"]}" style="font-weight:bold">{t}</text>')
# detaliile ca bloc stânga-jos, câte o linie per candelă: centrate sub
# candelă se suprapun între ele de îndată ce textul depășește `gap`.
ny = panel_bottom + (self.label_gap if tags else 18) + 4
@@ -319,7 +461,36 @@ def selftest():
assert min(c.l for c in ser[:3]) > min(c.l for c in ser[3:5]), \
"al doilea picior ar trebui să fie mai jos"
print("selftest ok: 2R la exact 2R, serie fără goluri, volum proporțional")
# zone și săgeți: validare, text în pânză, vârful pe țintă
for bad in (lambda: Arrow(0, "x", where="up"), lambda: Zone(3, 1),
lambda: Chart(candles=ser, arrows=[Arrow(6, "x")]),
lambda: Chart(candles=ser, zones=[Zone(4, 6)])):
try:
bad()
raise AssertionError("validarea n-a prins argumente greșite")
except ValueError:
pass
ch3 = Chart(candles=ser, scale=40, gap=14, body_w=9, width=200,
zones=[Zone(1, 3, "baza")],
arrows=[Arrow(0, "intrare\npe close", where="above"),
Arrow(3, "stop", where="below"),
Arrow(5, "ținta de 2R, foarte departe", where="right")])
svg3 = ch3.render()
vw, vh = map(float, re.search(r'viewBox="0 0 ([\d.]+) ([\d.]+)"', svg3).groups())
assert vw > 200, "textul săgeții din dreapta iese din pânză"
for x, y in re.findall(r'<text x="([-\d.]+)" y="([-\d.]+)"', svg3):
assert 0 <= float(x) <= vw and 11 <= float(y) <= vh, f"text în afara pânzei la ({x}, {y})"
tip = ch3._arrow_geom(ch3.arrows[1])["tip"]
assert abs(tip[1] - (ch3._y(ser[3].l) + 4)) < 1e-6, "vârful săgeții below nu e sub low"
# a doua randare a aceluiași obiect trebuie să iasă identică
ch3.title, ch3.trend = "T", "down"
assert ch3.render() == ch3.render(), "render() modifică obiectul: a doua randare diferă"
assert (ch3.top, ch3.left, ch3.width) == (34, 64, 200), "render() a lăsat top/left/width modificate"
assert svg3.index("fill-opacity") < svg3.index("<rect", svg3.index("fill-opacity") + 1), \
"zona trebuie desenată înaintea candelelor"
assert svg3.count("<polygon") == 3 and "pe close</text>" in svg3
print("selftest ok: 2R la exact 2R, serie fără goluri, volum proporțional, zone+săgeți")
if __name__ == "__main__":