MODUL 5: 24 de reparatii pe cele doua strategii, dupa verificare

Opt erau blocante, adica un cititor ar fi executat gresit pe cont:

- 56% era legat de o intrare la 133 care da de fapt 35,3%; cifra se propaga in
  dimensionarea pozitiei. Acum spune ca 56% e rostit separat si ca raportul nu
  se verifica.
- "2/3 taie jumatate din risc" era fals (29,3% vs 35,3%).
- definitia lui buy doji se contrazicea cu regula de 4 luni din acelasi
  document.
- diagrama de trail arata stopul deasupra pretului: liniile traversau tot
  graficul, deci in stanga stateau peste candele. Acum fiecare porneste din
  swing low-ul care o declanseaza, cu cele patru swing low-uri marcate.
- linia gatului era data ca "media celor doua varfuri", ceea ce nu reproduce
  63.00 pe propriul desen; e din interiorul gatului.
- singura regula mecanica de "nu intra" nu era desenata cu mecanismul ei:
  panoul de volum avea bare egale de la o baza, in loc de histograma cu semn.
- "SL minim 54.17" se citea invers decat intelege textul: e pretul cel mai
  sus permis, nu stopul cel mai stramt.
- lectura "TP2 vine inaintea lui TP1" era prezentata ca geometrie in doua
  diagrame, desi fraza-sursa e neinteligibila si sursa sprijina la fel de bine
  varianta in care se recalculeaza si TP si SL. Acum e marcata ca lectura
  chiar acolo unde e folosita, cu varianta alternativa alaturi.

svg_candles are trei adaugiri optionale (Level.i0, Level.label_dy,
Chart.vol_zero) cerute de reparatiile de mai sus; selftest-ul trece si
diagramele existente nu se schimba daca nu sunt regenerate.

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-10-02 02:35:51 +00:00
parent 0dd358802d
commit c198cd0a7b
7 changed files with 1184 additions and 945 deletions

View File

@@ -49,6 +49,28 @@ def hi(cds, a, b):
return round(max(c.h for c in cds[a:b + 1]), 2)
def run_desc(cds, end):
"""Câte bare consecutive, terminând cu `end`, au high-uri descrescătoare.
Regula strategiei e „5-8 candele"; cititorul numără pe desen după
high-uri (`04_6_...txt:142`), deci eticheta zonei se calculează de aici,
nu se scrie de mână. Altfel desenul ajunge să încalce propria regulă.
"""
k = 1
while end - k >= 0 and cds[end - k].h > cds[end - k + 1].h:
k += 1
return k
def zona_downtrend(cds, end, color="#c00"):
"""Zone(…) peste run-ul descrescător care se termină la bara `end`."""
n = run_desc(cds, end)
assert 5 <= n <= 8, \
f"downtrend-ul desenat are {n} candele cu high-uri descrescătoare, " \
f"iar strategia cere 5-8"
return Zone(end - n + 1, end, f"downtrend {n} candele", color)
def deco(ch, name, distante=(), intregi=()):
"""Randează graficul, verifică etichetele, salvează.
@@ -90,8 +112,8 @@ CONSTRUIT = "Exemplu construit (fără ticker), la scară. R-urile sunt ale mele
# =========================================================== seria construită
# Un singur trade construit, folosit de trei diagrame (harta, pasul 1, țintele),
# ca să nu se schimbe cifrele de la o secțiune la alta.
CL = ([64.00, 63.00, 62.00, 61.00, 58.50, 56.00, 54.00] # 0-6 context
+ [52.00, 50.00, 48.00, 45.50, 43.00, 41.50, 39.90] # 7-13 downtrend, 7 bare
CL = ([64.00, 65.80, 64.30, 65.90, 64.20, 62.80, 64.00] # 0-6 consolidare
+ [60.50, 57.00, 53.50, 50.00, 46.50, 43.00, 39.90] # 7-13 downtrend, 7 bare
+ [40.00] # 14 doji
+ [45.00] # 15 marubozu de trigger
+ [43.20, 42.60] # 16-17 pullback-ul
@@ -112,6 +134,8 @@ assert (DOJI_LO, DOJI_HI, H_DOJI) == (38.00, 42.00, 4.00), (DOJI_LO, DOJI_HI)
assert abs(CDS[14].c - CDS[14].o) <= 0.10 * H_DOJI, "candela 14 nu e doji"
assert CDS[15].c > DOJI_HI, "trigger-ul nu închide peste high-ul doji-ului"
assert lo(CDS, 7, 13) < lo(CDS, 0, 6), "downtrend-ul numărat nu coboară"
assert run_desc(CDS, 13) == 7, \
f"înaintea doji-ului trebuie 7 bare cu high descrescător, sunt {run_desc(CDS, 13)}"
TRIG_HI, TRIG_LO = hi(CDS, 15, 15), lo(CDS, 15, 15)
H_TRIG = round(TRIG_HI - TRIG_LO, 2) # 5.00
@@ -138,17 +162,20 @@ deco(Chart(
Level(E1, f"intrare 1/3 la close {E1:.2f}", "#188a3e"),
Level(E2, f"limit 1/3 la {E2:.2f}", "#188a3e", label_at="left"),
Level(E3, f"limit 1/3 la {E3:.2f}", "#188a3e", label_at="left"),
Level(MED, f"preț mediu {MED:.2f}", "#6a3d9a"),
Level(TP2, f"TP2 {TP2:.2f}", "#1a5fb4"),
# prețul mediu există abia după ce s-a umplut a treia tranșă:
# linia pornește de acolo, deci nu mai taie eticheta limitului
Level(MED, f"preț mediu {MED:.2f}", "#6a3d9a", i0=17),
Level(TP2, f"TP2 {TP2:.2f} — lectura mea", "#1a5fb4", i0=17),
Level(TP1, f"TP1 {TP1:.2f}", "#1a5fb4")],
marks=[Mark(14, "doji", "#b06000", "below", dy=14),
Mark(15, "buy doji", "#188a3e", dy=-6),
Mark(17, "se umplu limiturile", "#188a3e", "below", dy=44),
Mark(5, "consolidare", "#888", "below"),
Mark(17, "se umplu limiturile", "#188a3e", "below", dy=0),
Mark(23, "ieși, nu aștepți", "#1a5fb4", dy=-8)],
zones=[Zone(7, 13, "downtrend 7 candele", "#c00"),
zones=[zona_downtrend(CDS, 13),
Zone(15, 17, "fereastra de intrare", "#188a3e")],
mas=[MA(20, "#b06000", dash="4 3", text="SMA-20")],
scale=18.0, gap=17, body_w=9, left=52, width=700, vol_h=70,
mas=[MA(20, "#b06000", dash="4 3")],
scale=18.0, gap=17, body_w=9, left=52, width=700, top=76, vol_h=70,
vol_label="volum", title="MICIS, tot trade-ul — weekly (exemplu construit)",
caption=CONSTRUIT), "harta", distante=(R1, R2, H_DOJI))
@@ -167,7 +194,7 @@ deco(Chart(
levels=[Level(PIV, f"pivot quarterly {PIV:.2f}", "#b06000", label_at="left"),
Level(DOJI_LO, f"low-ul doji-ului {DOJI_LO:.2f}", "#6a3d9a")],
marks=[Mark(25, "doji", "#b06000", dy=-18)],
zones=[Zone(18, 24, "downtrend 7 candele", "#c00")],
zones=[zona_downtrend(cds2, 24)],
mas=[MA(20, "#b06000", dash="4 3", text="SMA-20")],
scale=8.0, gap=17, body_w=9, left=52, width=700, vol_h=70,
vol_label="volum", title="Pasul 1, DA — doji weekly pe pivotul quarterly",
@@ -179,18 +206,26 @@ cl3 = (ramp(41.00, 47.00, 6) + [46.50, 47.50] + ramp(47.50, 53.00, 6)
+ [52.40, 53.20] + ramp(53.20, 59.00, 6) + [58.60, 59.40, 58.80]
+ [59.00] + [58.40, 57.00, 55.00])
wk3 = [(0.35, 0.35)] * 25 + [(1.60, 1.50)] + [(0.40, 0.40)] * 3
vl3 = vols(29, 48, 12, i22=38, i23=34, i24=30, i25=26, i26=34, i27=44, i28=52)
# volumul trebuie să scadă pe TOT uptrend-ul, nu doar pe ultimele bare:
# eticheta „volum în scădere" se citește peste zona verde, nu peste 4 bare
vl3 = ([50.0, 52.0, 48.0, 54.0, 50.0, 52.0]
+ [62.0, 60.0, 58.0, 56.0, 54.0, 52.0, 50.0, 48.0, 46.0, 44.0,
42.0, 40.0, 38.0, 36.0, 33.0, 30.0, 28.0, 26.0, 25.0, 24.0]
+ [40.0, 56.0, 68.0])
cds3 = from_closes(cl3, wicks=wk3, vols=vl3, start=40.00)
assert abs(cds3[25].c - cds3[25].o) <= 0.10 * (cds3[25].h - cds3[25].l), \
"candela 25 nu e doji"
assert cds3[25].c > cds3[0].c and hi(cds3, 25, 25) == hi(cds3, 0, 28), \
"doji-ul trebuie să cadă în vârful unui uptrend"
assert vl3[25] == min(vl3), "volumul trebuie să fie cel mai mic la doji"
assert all(vl3[i] > vl3[i + 1] for i in range(6, 25)), \
"barele de volum trebuie să scadă pe toată zona de uptrend, cât ține eticheta"
assert vl3[26] < vl3[27] < vl3[28], "volumul trebuie să revină pe corecție"
deco(Chart(
candles=cds3,
marks=[Mark(25, "doji aici: după uptrend", "#c00", dy=-10),
Mark(22, "volum în scădere", "#c00", "below", dy=24),
Mark(28, "urmează corecția", "#c00", "below", dy=14),
Mark(16, "volum în scădere pe tot uptrend-ul", "#c00", "below", dy=24),
Mark(28, "urmează corecția, cu volum", "#c00", "below", dy=14),
Mark(12, "uptrend", "#188a3e", "below", dy=38)],
zones=[Zone(6, 24, "", "#188a3e")],
mas=[MA(20, "#b06000", dash="4 3", text="SMA-20")],
@@ -222,9 +257,12 @@ assert lo(JC, 14, 14) <= J_E2 and lo(JC, 15, 15) <= J_E3, "ladder-ul nu se umple
deco(Chart(
candles=JC,
levels=[Level(J_E1, f"intrare 1/3 la close {J_E1:.2f}", "#188a3e"),
# limiturile există abia după close-ul candelei de trigger, deci
# liniile pornesc de la ea: altfel taie eticheta de dedesubt
Level(J_E2, f"limit 1/3 la {J_E2:.2f} = 1/3 din marubozu", "#188a3e",
label_at="left"),
Level(J_E3, "limit 1/3 la 1/2 din marubozu", "#6a3d9a")],
i0=13),
Level(J_E3, "limit 1/3 la 1/2 din marubozu", "#6a3d9a",
label_at="left")],
marks=[Mark(12, "doji", "#b06000", "below", dy=14),
Mark(13, "marubozu de trigger", "#188a3e", dy=-26),
Mark(15, "pullback-ul umple ambele limituri", "#188a3e", "below", dy=38)],
@@ -254,7 +292,9 @@ assert lo(AC, 16, 26) > A_E2, "ladder-ul NU trebuie să se umple pe acest desen"
deco(Chart(
candles=AC,
levels=[Level(A_E1, f"intrare 1/3 la close {A_E1:.2f}", "#188a3e"),
Level(A_E2, f"limit 1/3 la {A_E2:.2f} — niciodată atins", "#c00",
# înălțimea candelei nu e rostită pe AMD, deci nivelul de 1/3 nu
# primește cifră — aceeași regulă ca pe JNJ
Level(A_E2, "limit 1/3 — niciodată atins", "#c00",
label_at="left"),
Level(180.00, "unde a ajuns: 180", "#1a5fb4")],
marks=[Mark(14, "doji", "#b06000", "below", dy=14),
@@ -273,7 +313,11 @@ N_CL = ([20.00, 23.50, 27.00, 25.00, 31.00, 38.00, 45.00, 42.00, 50.00, 55.00,
+ [100.50] # 21 doji
+ [133.00] # 22 marubozu de trigger
+ [141.00, 152.00, 164.00, 175.00, 182.00]) # 23-27 spre 182
N_WK = ([(1.50, 1.50)] * 16 + [(3.00, 3.00)] * 5 + [(13.00, 14.50)]
# bara 16 e vârful: fitil de respingere deasupra, ca high-ul ei să fie
# cel mai sus din downtrend și numărătoarea după high-uri să dea 5, cât
# spune eticheta
N_WK = ([(1.50, 1.50)] * 16 + [(5.00, 3.00)] + [(3.00, 3.00)] * 4
+ [(13.00, 14.50)]
+ [(0.50, 1.50)] + [(2.00, 2.00)] * 5)
N_VL = vols(28, 46, 12, i19=66, i20=78, i21=84, i22=104, i23=86, i24=80)
NC = from_closes(N_CL, wicks=N_WK, vols=N_VL, start=19.00)
@@ -294,7 +338,7 @@ deco(Chart(
Level(182.00, "ținta rostită: 182", "#1a5fb4")],
marks=[Mark(21, "doji monthly, înălțime 28", "#b06000", "below", dy=16),
Mark(22, "marubozu de trigger", "#188a3e", dy=-70)],
zones=[Zone(16, 20, "downtrend 5 candele", "#c00")],
zones=[zona_downtrend(NC, 20)],
mas=[MA(20, "#b06000", dash="4 3", text="SMA-20")],
scale=2.4, gap=19, body_w=10, left=58, width=700, top=60, vol_h=70,
vol_label="volum", title="Pasul 3, stopul — NVDA monthly",
@@ -312,18 +356,18 @@ deco(Chart(
candles=cds4,
levels=[Level(SL, f"SL {SL:.2f}", "#c00", label_at="left"),
Level(MED, f"preț mediu {MED:.2f}", "#6a3d9a"),
Level(E1, f"intrare 1 la {E1:.2f}", "#188a3e"),
Level(E1, f"intrare 1/3 la {E1:.2f}", "#188a3e"),
Level(TP2, f"TP2 {TP2:.2f}", "#1a5fb4"),
Level(TP1, f"TP1 {TP1:.2f}", "#1a5fb4")],
arrows=[Arrow(10, f"TP2 = 1R pe medie ({R2:.2f})", price=TP2, where="left",
color="#1a5fb4", dx=-6),
color="#1a5fb4", dx=-6, dy=-16),
Arrow(12, f"TP1 = 1R pe prima tranșă ({R1:.2f})", price=TP1,
where="above", color="#1a5fb4", dy=-10)],
mas=[MA(20, "#b06000", dash="4 3", text="SMA-20")],
scale=13.0, gap=28, body_w=14, left=60, width=700, top=56,
title="Pasul 4, cele două ținte — weekly (exemplu construit)",
caption="Mediind în jos, 1R se scurtează: TP2 vine înaintea lui TP1. "
"R-urile sunt ale mele."),
caption="Lectura mea: mediind în jos, TP2 vine înaintea lui TP1. "
"Fraza-sursă e neinteligibilă aici."),
"pasul4_tinte", distante=(R1, R2))
# --------------------------------------------------- 8. pasul 5 — trail-ul
@@ -334,23 +378,37 @@ cl5 = (ramp(44.00, 50.00, 5) + [49.20, 48.60, 49.40] # 0-7 trail 1
wk5 = [(0.40, 0.40)] * 30
vl5 = vols(30, 50, 12)
cds5 = from_closes(cl5, wicks=wk5, vols=vl5, start=43.00)
# fiecare trail e declanșat de un swing low anume; linia lui pornește de la
# bara aceea, nu din marginea desenului
SW = [6, 14, 22, 29]
t1, t2, t3, t4 = (lo(cds5, 5, 7), lo(cds5, 13, 15), lo(cds5, 21, 23),
lo(cds5, 28, 29))
assert t1 < t2 < t3 < t4, (t1, t2, t3, t4)
# regresia de prins: o linie de trail nu are voie să treacă pe deasupra
# prețului la dreapta ei — altfel desenul arată o poziție deja stopată
for _i0, _t in zip(SW, (t1, t2, t3, t4)):
assert all(c.l >= _t - 1e-9 for c in cds5[_i0:]), \
f"trail-ul {_t} de la bara {_i0} trece peste low-ul unei bare de după"
assert lo(cds5, max(0, _i0 - 1), min(_i0 + 1, len(cds5) - 1)) == _t, \
f"trail-ul {_t} nu e ancorat de swing low-ul de la bara {_i0}"
deco(Chart(
candles=cds5,
levels=[Level(t1, f"trail 1: {t1:.2f}", "#c00", label_at="left"),
Level(t2, f"trail 2: {t2:.2f}", "#c00", label_at="left"),
Level(t3, f"trail 3: {t3:.2f}", "#c00"),
Level(t4, f"trail 4: {t4:.2f}", "#c00")],
marks=[Mark(6, "swing low", "#c00", "below", dy=14),
Mark(14, "swing low mai sus → muți stopul", "#c00", dy=-10)],
mas=[MA(20, "#b06000", dash="4 3", text="SMA-20")],
# etichetele la dreapta: la stânga ar cădea peste candele, pentru că
# fiecare linie începe acum în mijlocul desenului
levels=[Level(t1, f"trail 1: {t1:.2f}", "#c00", i0=SW[0]),
Level(t2, f"trail 2: {t2:.2f}", "#c00", i0=SW[1]),
Level(t3, f"trail 3: {t3:.2f}", "#c00", i0=SW[2]),
Level(t4, f"trail 4: {t4:.2f}", "#c00", i0=SW[3])],
marks=[Mark(6, "swing low 1", "#c00", "below", dy=14),
Mark(14, "swing low 2", "#c00", "below", dy=14),
Mark(22, "swing low 3", "#c00", "below", dy=14),
Mark(29, "swing low 4", "#c00", "below", dy=14)],
mas=[MA(20, "#b06000", dash="4 3")],
scale=7.0, gap=17, body_w=9, left=52, width=700, top=64, vol_h=70,
vol_label="volum",
title="Pasul 5, trail pe swing low — weekly (decizia a fost pe monthly)",
caption="Exemplu construit (fără ticker). Stopul urcă doar la un swing low "
"mai sus; nu coboară niciodată."), "pasul5_trail")
caption="Fiecare linie de trail pornește de la swing low-ul care o "
"declanșează; stopul nu coboară niciodată."), "pasul5_trail")
# ------------------------------------- 9. când nu merge (Tesla, 217.02/214.25)
T_CL = ([320.00, 312.00, 304.00, 298.00] # 0-3
@@ -358,25 +416,31 @@ T_CL = ([320.00, 312.00, 304.00, 298.00] # 0-3
+ [232.00] # 12 buy hammer
+ [228.00, 222.00, 216.00] # 13-15 scoate stopul
+ [225.00] # 16 al doilea semnal
+ [240.00, 252.00, 262.00, 272.00, 282.00, 290.00, 298.00] # 17-23
+ [295.00, 302.00]) # 24-25
+ [240.00, 252.00, 262.00, 272.00, 282.00, 290.00, 298.00]) # 17-23
T_WK = ([(3.00, 3.00)] * 12 + [(2.00, 12.98)]
+ [(2.00, 2.00), (2.00, 2.00), (1.00, 1.75)]
+ [(2.00, 2.00)] * 10)
T_VL = vols(26, 46, 12, i12=72, i15=78, i16=84, i17=88, i18=80)
+ [(2.00, 2.00)] * 8)
T_VL = vols(24, 46, 12, i12=72, i15=78, i16=84, i17=88, i18=80)
TC = from_closes(T_CL, wicks=T_WK, vols=T_VL, start=326.00)
assert lo(TC, 12, 12) == 217.02, f"low-ul hammer-ului trebuie 217.02, e {lo(TC, 12, 12)}"
assert lo(TC, 13, 15) == 214.25, f"minimul următor trebuie 214.25, e {lo(TC, 13, 15)}"
assert 214.25 < 217.02, "al doilea minim e sub low-ul hammer-ului"
assert len(TC[17:24]) == 7, "urcarea rostită e de 7 săptămâni"
assert len(TC) == 24, "după al doilea semnal se desenează exact cele 7 bare rostite"
assert all(TC[i].c < TC[i + 1].c for i in range(17, 23)), \
"cele 7 bare etichetate ca urcare trebuie să urce toate"
deco(Chart(
candles=TC,
levels=[Level(214.25, "minimul de după: 214.25", "#c00")],
levels=[Level(217.02, "low-ul hammer-ului: 217.02", "#b06000",
label_at="left"),
# cele două minime sunt la 2.77 dolari: eticheta celui de jos
# trece sub propria linie, altfel o taie linia de deasupra
Level(214.25, "minimul de după: 214.25", "#c00", label_dy=18)],
marks=[Mark(12, "buy hammer — primul semnal", "#b06000", dy=-10),
Mark(17, "al doilea semnal, acesta merge", "#188a3e", dy=-10),
Mark(23, "7 săptămâni de urcare", "#188a3e", dy=-10)],
arrows=[Arrow(12, "low-ul hammer-ului: 217.02;\nstopul pus sub el a fost luat",
price=217.02, where="left", color="#b06000", dx=-10, dy=-26)],
arrows=[Arrow(15, "stopul pus sub 217.02\na fost luat aici",
price=214.25, where="below", color="#c00", dy=4)],
mas=[MA(20, "#b06000", dash="4 3", text="SMA-20")],
scale=2.6, gap=19, body_w=10, left=58, width=700, vol_h=70,
vol_label="volum", title="Când nu merge — Tesla weekly",
@@ -419,7 +483,7 @@ SVG["flux"] = """<svg viewBox="0 0 700 300" xmlns="http://www.w3.org/2000/svg" s
<text x="32" y="66" fill="#1a5fb4" style="font-weight:bold">1. Scanner, pe candelă închisă</text>
<text x="32" y="86" fill="#333">doar DOJI, nu buy doji</text>
<rect x="250" y="44" width="200" height="56" fill="#eef4ff" stroke="#1a5fb4"/>
<text x="262" y="66" fill="#1a5fb4" style="font-weight:bold">2. Lista, 3-400 de simboluri</text>
<text x="262" y="66" fill="#1a5fb4" style="font-weight:bold">2. Lista, 200-300 de simboluri</text>
<text x="262" y="86" fill="#333">ținută 4 luni, într-un excel</text>
<rect x="480" y="44" width="200" height="56" fill="#eef4ff" stroke="#1a5fb4"/>
<text x="492" y="66" fill="#1a5fb4" style="font-weight:bold">3. Radar screen</text>

View File

@@ -134,7 +134,11 @@ SL = round(CAP + H / 3, 2) # 1/3 de la cap: marginea de sus a t
E = CDS[32].c # intrarea, la close-ul candelei de breakout
R = round(E - SL, 2)
TP1 = round(E + R, 2)
GAT = round((hi(CDS, 12, 12) + hi(CDS, 24, 24)) / 2, 2) # media celor două vârfuri
# „măsoară din interiorul gâtului pe aici, iau un average" (`05_7_...txt:1304`):
# nivelul se ia din interiorul gâtului, NU de la cele mai de sus vârfuri. Pe
# desen vârfurile sunt mai sus (barele 13 și 25 ating 63.30), de aceea eticheta
# nu are voie să spună „media celor două vârfuri".
GAT = round((hi(CDS, 12, 12) + hi(CDS, 24, 24)) / 2, 2)
H_HS = round(GAT - CAP, 2)
TP2 = round(GAT + H_HS, 2)
@@ -151,6 +155,10 @@ assert hi(CDS, 38, 42) >= TP1 > TP2, \
assert lo(CDS, 13, 18) < lo(CDS, 6, 9) and lo(CDS, 13, 18) < lo(CDS, 25, 31), \
"capul trebuie să fie mai jos decât ambii umeri"
assert VL[32] > max(VL[25:32]), "candela de breakout nu are volumul cel mai mare"
# regresia de prins: eticheta gâtului spune „din interiorul gâtului, nu de la
# vârfuri", deci nivelul trebuie să stea strict sub cel mai de sus vârf al zonei
assert GAT < max(hi(CDS, 10, 13), hi(CDS, 24, 25)), \
f"gâtul {GAT} nu e sub vârfurile zonei: eticheta ar minți"
print(f"construit: cap {CAP} umeri {UMS}/{UMD} H {H} SL {SL} intrare {E}"
f" R {R} TP1 {TP1} gât {GAT} (h {H_HS}) TP2 {TP2}")
@@ -167,7 +175,7 @@ deco(Chart(
Mark(17, "capul", "#6a3d9a", "below", dy=16),
Mark(31, "doji", "#b06000", "below", dy=8),
Mark(32, "buy doji = trigger", "#188a3e", dy=-40),
Mark(34, "retest", "#b06000", "below", dy=22),
Mark(34, "pullback la nivelul de breakout", "#b06000", "below", dy=22),
Mark(41, "apoi trail", "#1a5fb4", dy=-8)],
zones=[Zone(25, 31, "umărul drept", "#188a3e")],
mas=[MA(20, "#b06000", dash="4 3")],
@@ -301,28 +309,52 @@ X_CL = ([55.00, 56.50, 58.00, 59.50, 61.00, 62.20, 63.00]
+ [64.40] # 18 breakout, dar fără volum
+ [62.00, 60.00, 57.50, 55.00]) # 19-22 breakdown
X_WK = T_WK
X_VL = vols(23, 44, 10, i4=78, i8=52, i9=48, i10=40, i11=38, i12=34, i13=32,
i14=30, i15=28, i16=26, i17=24, i18=36, i19=54, i20=66, i21=74)
# Regula de „nu intra" din sursă e despre o histogramă CU SEMN care cade sub
# swing low-ul ei („histograma asta cade sub swing low-ul de aici […] iar prețul
# încă nu e acolo"), nu despre bare brute pornite de la o bază: pe bare
# nesemnate „minime tot mai joase" nu înseamnă nimic vizual. De aceea panoul de
# jos al acestei diagrame e desenat în jurul unui zero (`vol_zero`), cu trei
# minime tot mai joase, iar bara candelei de breakout fals e mică și sub zero.
ZERO = 50.0
X_VL = [60.0, 64.0, 68.0, 74.0, 80.0, 72.0, 66.0, # 0-6 urcarea
56.0, 50.0, 42.0, # 7-9 minimul 1
48.0, 46.0, 38.0, # 10-12 minimul 2
44.0, 42.0, 34.0, 40.0, # 13-16 minimul 3
36.0, # 17 doji
44.0, # 18 breakout fals
30.0, 24.0, 20.0, 16.0] # 19-22 breakdown
XC = from_closes(X_CL, wicks=X_WK, vols=X_VL, start=54.00)
assert abs(XC[17].c - XC[17].o) <= 0.15 * (XC[17].h - XC[17].l), "bara 17 nu e doji"
assert XC[18].c > hi(XC, 7, 17), "breakout-ul de preț există și aici"
assert X_VL[18] < X_VL[4], "volumul de breakout NU trebuie să treacă swing high-ul"
assert X_VL[17] == min(X_VL), "volumul minim trebuie să cadă pe doji"
assert X_VL[18] < ZERO, \
"pe candela de breakout histograma trebuie să fie deja sub zero"
_SW = (9, 12, 15)
for _i in _SW:
assert X_VL[_i - 1] > X_VL[_i] < X_VL[_i + 1], \
f"bara {_i} nu e un minim local al histogramei"
assert X_VL[_i] < ZERO, f"minimul de la bara {_i} trebuie să fie sub zero"
assert X_VL[_SW[0]] > X_VL[_SW[1]] > X_VL[_SW[2]], \
f"minimele histogramei nu coboară: {[X_VL[i] for i in _SW]}"
assert XC[22].c < lo(XC, 7, 17), "după breakout-ul fals prețul rupe consolidarea"
deco(Chart(
candles=XC,
levels=[Level(lo(XC, 7, 17), f"baza {lo(XC, 7, 17):.2f}", "#c00",
label_at="left")],
marks=[Mark(17, "doji", "#b06000", "below", dy=26),
Mark(18, "închide peste consolidare, dar volumul e praf", "#c00", dy=-10),
Mark(12, "volumul face minime tot mai joase", "#c00", "below", dy=26),
Mark(18, "închide peste consolidare, dar volumul e deja sub zero",
"#c00", dy=-10),
Mark(11, "histograma rupe sub propriul swing low, de trei ori",
"#c00", "below", dy=46),
Mark(22, "breakdown", "#c00", "below", dy=14)],
zones=[Zone(7, 17, "aceeași consolidare de 11 bare", "#c00")],
mas=[MA(20, "#b06000", dash="4 3", text="SMA-20")],
scale=14.0, gap=26, body_w=11, left=58, width=700, top=46, vol_h=80,
vol_label="volum", title="Pasul 2, NU — breakout de preț fără breakout de volum",
caption="Exemplu construit (fără ticker). Prețul arată identic cu diagrama "
"de deasupra; diferă panoul de volum. False breakout."), "pas2_nu")
vol_zero=ZERO,
vol_label="histogramă de volum, cu semn (stil on balance volume)",
title="Pasul 2, NU — breakout de preț fără breakout de volum",
caption="Exemplu construit. Prețul e identic cu al diagramei de deasupra; "
"panoul de jos e histograma cu semn, nu volumul brut."), "pas2_nu")
# ================================================== 6. pasul 3 — stopul, treimea de jos
deco(Chart(
@@ -330,7 +362,7 @@ deco(Chart(
levels=[Level(UMD, f"umăr drept {UMD:.2f}", "#6a3d9a"),
Level(CAP, f"cap {CAP:.2f} — baza lui H", "#6a3d9a",
label_at="left"),
Level(SL, f"SL minim {SL:.2f} = cap + H/3", "#c00"),
Level(SL, f"SL cel mai sus permis: {SL:.2f} = cap + H/3", "#c00"),
Level(E, f"intrare {E:.2f}; distanța până la SL e R", "#188a3e",
label_at="left")],
marks=[Mark(12, "capul", "#6a3d9a", "below", dy=16),
@@ -344,11 +376,13 @@ deco(Chart(
# ========================================================= 7. pasul 4 — cele două ținte
deco(Chart(
candles=CDS[18:],
levels=[Level(SL, f"SL {SL:.2f}", "#c00", label_at="left"),
levels=[Level(CAP, f"capul {CAP:.2f} = baza înălțimii HS", "#6a3d9a"),
Level(SL, f"SL {SL:.2f}", "#c00", label_at="left"),
Level(E, f"intrare {E:.2f}", "#188a3e", label_at="left"),
Level(GAT, f"linia gâtului {GAT:.2f}, media celor două vârfuri",
"#6a3d9a", label_at="left"),
Level(TP2, f"TP2 {TP2:.2f} = gât + înălțimea HS", "#1a5fb4",
Level(GAT, f"linia gâtului {GAT:.2f}, din interiorul gâtului "
f"(nu de la vârfuri)", "#6a3d9a", label_at="left"),
Level(TP2, f"TP2 {TP2:.2f} = gât + înălțimea HS "
f"({GAT:.2f} − {CAP:.2f} = {H_HS:.2f})", "#1a5fb4",
label_at="left"),
Level(TP1, f"TP1 {TP1:.2f} = intrare + R", "#1a5fb4",
label_at="left")],
@@ -369,7 +403,9 @@ Y_CL = ([50.00, 51.20, 52.40, 53.00, 52.20, 53.40, 52.60, 53.20,
Y_WK = ([(0.30, 0.30)] * 10 + [(0.20, 0.20)]
+ [(0.30, 0.30), (0.30, 0.30), (0.30, 0.30)]
+ [(0.60, 0.50)] + [(0.30, 0.30)] * 4)
Y_VL = vols(19, 44, 10, i10=96, i11=52, i12=48, i13=46, i14=56, i15=88, i16=82)
# barele de retest trebuie să fie mai mici decât ale consolidării: legenda
# spune „volum mic pe retest, mare pe repornire"
Y_VL = vols(19, 44, 10, i10=96, i11=30, i12=26, i13=24, i14=28, i15=88, i16=82)
YC = from_closes(Y_CL, wicks=Y_WK, vols=Y_VL, start=49.00)
C_HI, C_LO = hi(YC, 0, 9), lo(YC, 0, 9)
JUM = round((C_HI + C_LO) / 2, 2)
@@ -377,14 +413,22 @@ assert YC[10].c > C_HI, "bara 10 trebuie să facă breakout peste consolidare"
assert JUM < lo(YC, 11, 14) < C_HI, \
"retestul trebuie să intre în consolidare, dar să se oprească peste jumătate"
assert YC[18].c > YC[10].c, "după retest prețul trebuie să plece mai sus"
assert max(Y_VL[11:15]) < min(Y_VL[0:10]), \
"barele de retest trebuie să fie sub toate barele consolidării"
assert Y_VL[15] > max(Y_VL[0:15]) * 0.9, "repornirea trebuie să vină cu volum"
# dreptunghiul consolidării e ancorat exact de cele două cifre din etichete,
# fără cei 8 px de padding impliciți: altfel capacul nu cade pe 53.70
assert JUM == round((C_HI + C_LO) / 2, 2), "jumătatea nu e a intervalului declarat"
deco(Chart(
candles=YC,
levels=[Level(C_HI, f"vârful consolidării {C_HI:.2f} = locul crimei", "#6a3d9a"),
Level(JUM, f"jumătatea consolidării {JUM:.2f}", "#b06000")],
Level(JUM, f"jumătatea consolidării {JUM:.2f} "
f"= ({C_HI:.2f} + {C_LO:.2f}) / 2", "#b06000"),
Level(C_LO, f"baza consolidării {C_LO:.2f}", "#6a3d9a")],
marks=[Mark(10, "breakout", "#188a3e", dy=-10),
Mark(13, "retest, se oprește peste jumătate", "#188a3e", "below", dy=20),
Mark(14, "doji aici: a doua intrare", "#188a3e", "below", dy=38)],
zones=[Zone(0, 9, "consolidarea", "#6a3d9a")],
zones=[Zone(0, 9, "consolidarea", "#6a3d9a", p_top=C_HI, p_bot=C_LO)],
scale=22.0, gap=30, body_w=12, left=58, width=700, top=46, vol_h=70,
vol_label="volum", title="Retestul, DA — se oprește în jumătatea de sus",
caption="Exemplu construit (fără ticker). Volum mic pe retest, mare pe "
@@ -412,7 +456,7 @@ deco(Chart(
marks=[Mark(10, "același breakout", "#188a3e", dy=-10),
Mark(13, "retestul trece sub jumătate", "#c00", "below", dy=52),
Mark(17, "volum în creștere pe coborâre", "#c00", "below", dy=16)],
zones=[Zone(0, 9, "aceeași consolidare", "#6a3d9a")],
zones=[Zone(0, 9, "aceeași consolidare", "#6a3d9a", p_top=C_HI, p_bot=C_LO)],
scale=15.0, gap=30, body_w=12, left=58, width=700, top=46, vol_h=70,
vol_label="volum", title="Retestul, NU — trece sub jumătate și rupe baza",
caption="Exemplu construit (fără ticker). Același breakout; diferă cât de "