17_STRATEGII/09_micis: capitol nou, strategia 7 pe actiuni individuale
Aprobat de user. E singura strategie din curs pe actiuni individuale, pe weekly/monthly, deci singura care se potriveste direct cu swing pe TradeStation cu bani proprii. Ce nu e acoperit nicaieri altundeva in document si face miezul capitolului: ladder-ul 1/3+1/3+1/3 masurat pe marubozu, stopul de 2/3 din doji pe timeframe-uri mari, trail-ul pe timeframe-ul de sub cel de decizie, si rutina scanezi-doji -> radar screen cu lista tinuta patru luni. Restul trimite la 01_buy_doji, 05_atmi si A3_intrarea in loc sa rescrie. 7 diagrame, audit curat, eticheta_libera a prins 9 suprapuneri reale in timpul lucrului. Pe etichete doar preturi rostite; nivelul de 1/2 din marubozu pe JNJ e lasat fara cifra, fiind derivat. Lectura "TP2 vine inaintea lui TP1" e marcata ca lectura in fiecare loc unde e folosita, cu varianta alternativa alaturi, nu doar intr-o nota de subsol. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ThN7ixZrowca8aTGrK1MUJ
This commit is contained in:
409
gen/strategii/micis_diagrame.py
Normal file
409
gen/strategii/micis_diagrame.py
Normal file
@@ -0,0 +1,409 @@
|
||||
"""Diagramele pentru summaries/17_STRATEGII/09_micis.md (MICI-S, strategia 7).
|
||||
|
||||
Un singur generator pentru cele șapte diagrame ale capitolului: capitolul are
|
||||
o serie construită folosită de trei desene, deci dacă fiecare diagramă ar sta
|
||||
în fișierul ei, seria s-ar dubla și s-ar desincroniza la prima retușare.
|
||||
|
||||
Regula de cifre, aceeași din `gen/strategia_7_micis.py`: pe etichete intră
|
||||
DOAR prețuri rostite în transcriere (157.47, 155.02, 86, 94, 133, 182, 28, 48,
|
||||
217.02, 214.25) sau prețuri dintr-un exemplu declarat construit în titlu.
|
||||
Valorile derivate (prețul mediu, 1R, 1/2 din marubozu) nu primesc etichetă pe
|
||||
desenele cu ticker, ci doar pe cele construite, unde captionul spune că R-urile
|
||||
sunt ale mele.
|
||||
|
||||
Scrie gen/strategii/micis_<cheie>.svg și substituie marcajele
|
||||
<!-- DIAGRAMA: cheie --> din capitol.
|
||||
|
||||
Rulează: .venv/bin/python gen/strategii/micis_diagrame.py
|
||||
"""
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
sys.path.insert(0, "/workspace/atm-curs-dl")
|
||||
sys.path.insert(0, "/workspace/atm-curs-dl/gen")
|
||||
from eticheta_libera import eticheta_libera # noqa: E402
|
||||
from svg_candles import MA, Arrow, Chart, Level, Mark, Zone, from_closes # noqa: E402
|
||||
|
||||
ROOT = Path("/workspace/atm-curs-dl")
|
||||
MD = ROOT / "summaries/17_STRATEGII/09_micis.md"
|
||||
OUT = ROOT / "gen/strategii"
|
||||
|
||||
RED, GREEN, BLUE, ORANGE, INK, GRAY = "#c00", "#188a3e", "#1a5fb4", "#b06000", "#333", "#888"
|
||||
PURPLE = "#6a3d9a"
|
||||
CONSTRUIT = "Exemplu construit (fără ticker), la scară. R-urile sunt ale mele."
|
||||
|
||||
SVG = {}
|
||||
|
||||
|
||||
# ----------------------------------------------------------------- unelte mici
|
||||
def ramp(a, b, n):
|
||||
return [round(a + (b - a) * k / n, 2) for k in range(1, n + 1)]
|
||||
|
||||
|
||||
def vols(n, base=44, span=12, **over):
|
||||
v = [float(base + ((i * 7) % span) - span // 2) for i in range(n)]
|
||||
for k, x in over.items():
|
||||
v[int(k[1:])] = float(x)
|
||||
return v
|
||||
|
||||
|
||||
def lo(cds, a, b):
|
||||
return round(min(c.l for c in cds[a:b + 1]), 2)
|
||||
|
||||
|
||||
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.
|
||||
|
||||
Cititorul numără downtrend-ul după high-uri, nu după culori, deci eticheta
|
||||
zonei se calculează de aici — altfel desenul încalcă propria regulă de
|
||||
„5-8 candele".
|
||||
"""
|
||||
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=RED):
|
||||
n = run_desc(cds, end)
|
||||
assert 5 <= n <= 8, f"downtrend-ul desenat are {n} candele, regula cere 5-8"
|
||||
return Zone(end - n + 1, end, f"downtrend {n} candele", color)
|
||||
|
||||
|
||||
def deco(ch, name, distante=(), intregi=(), libere=(), libere_nivel=(), extra=None):
|
||||
"""Randează, verifică etichetele, salvează.
|
||||
|
||||
`distante` = numere cu două zecimale permise în etichete fără să fie
|
||||
niveluri desenate. `intregi` = întregi rostiți. `libere` / `libere_nivel` =
|
||||
etichete pe care `eticheta_libera` le verifică (a doua grupă: etichete de
|
||||
nivel, lipite de linia lor prin construcție, deci doar candelele contează).
|
||||
"""
|
||||
svg = ch.render()
|
||||
if extra is not None:
|
||||
svg = svg.replace("\n</svg>", "\n " + "\n ".join(extra(ch)) + "\n</svg>")
|
||||
assert "\n\n" not in svg, f"{name}: linie goală în svg"
|
||||
assert ".md:" not in svg, f"{name}: trimitere fișier:linie în svg"
|
||||
assert len(ch.caption) <= 130, f"{name}: caption de {len(ch.caption)} caractere"
|
||||
desenate = ({f"{lv.price:.2f}" for lv in ch.levels}
|
||||
| {f"{a.price:.2f}" for a in ch.arrows if a.price is not None}
|
||||
| {f"{d:.2f}" for d in distante})
|
||||
permise_int = {str(i) for i in intregi} | {f"{lv.price:.0f}" for lv in ch.levels}
|
||||
for t in re.findall(r"<text\b[^>]*>(.*?)</text>", svg, re.S):
|
||||
plain = re.sub(r"<[^>]+>", "", t)
|
||||
for m in re.finditer(r"\d+\.\d\d", plain):
|
||||
assert m.group(0) in desenate, \
|
||||
f"{name}: eticheta numește {m.group(0)}, care nu e un nivel desenat"
|
||||
for m in re.finditer(r"(?<![\d.\-])(\d{2,3})(?![\d.])"
|
||||
r"(?!\s*(?:candele|bare|săptămâni|luni|perioade|mil))", plain):
|
||||
assert m.group(1) in permise_int, \
|
||||
f"{name}: eticheta numește întregul {m.group(1)}, nepermis"
|
||||
sus = min(ch._y(c.h) for c in ch.candles)
|
||||
jos = max(ch._y(c.l) for c in ch.candles)
|
||||
for lv in ch.levels:
|
||||
assert ch._y(lv.price) > sus - 0.06 * (jos - sus), \
|
||||
f"{name}: nivelul {lv.price} e lipit de marginea de sus"
|
||||
if libere:
|
||||
eticheta_libera(svg, name, set(libere), rects=True)
|
||||
if libere_nivel:
|
||||
eticheta_libera(svg, name, set(libere_nivel), rects=True, segmente=False)
|
||||
SVG[name] = svg
|
||||
print(f" {name}: {len(ch.candles)} bare, {len(ch.levels)} niveluri")
|
||||
|
||||
|
||||
# =========================================================== seria construită
|
||||
# Un trade construit, folosit de `ansamblu` și de `tinte`, ca să nu se schimbe
|
||||
# cifrele de la o secțiune la alta. Aceleași cifre ca în sumarizarea lecției.
|
||||
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
|
||||
+ [43.60, 44.80, 46.00, 47.90, 49.20, 50.70] # 18-23 urcarea
|
||||
+ [52.00, 51.30, 53.00, 54.50]) # 24-27 continuare
|
||||
WK = ([(0.40, 0.40)] * 14 + [(2.00, 1.90)] + [(0.00, 0.00)]
|
||||
+ [(0.30, 0.20), (0.20, 0.30)] + [(0.35, 0.35)] * 10)
|
||||
VL = vols(28, 46, 12, i11=58, i12=62, i13=66, i14=70, i15=96, i16=58, i17=52,
|
||||
i18=60, i19=66, i20=72, i21=78, i22=70, i23=80)
|
||||
CDS = from_closes(CL, wicks=WK, vols=VL, start=65.00)
|
||||
|
||||
DOJI_LO, DOJI_HI = lo(CDS, 14, 14), hi(CDS, 14, 14)
|
||||
H_DOJI = round(DOJI_HI - DOJI_LO, 2)
|
||||
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 run_desc(CDS, 13) == 7, "înaintea doji-ului trebuie 7 bare descrescătoare"
|
||||
|
||||
TRIG_HI, TRIG_LO = hi(CDS, 15, 15), lo(CDS, 15, 15)
|
||||
H_TRIG = round(TRIG_HI - TRIG_LO, 2)
|
||||
E1 = CDS[15].c # 45.00, la close
|
||||
E2 = round(TRIG_HI - H_TRIG / 3, 2) # 43.33, 1/3 din marubozu
|
||||
E3 = round(TRIG_HI - H_TRIG / 2, 2) # 42.50, 1/2 din marubozu
|
||||
SL = round(DOJI_LO + H_DOJI / 3, 2) # 39.33, 2/3 din doji
|
||||
MED = round((E1 + E2 + E3) / 3, 2) # 43.61
|
||||
R1, R2 = round(E1 - SL, 2), round(MED - SL, 2)
|
||||
TP1, TP2 = round(E1 + R1, 2), round(MED + R2, 2)
|
||||
assert SL == 39.33 and MED == 43.61 and TP1 == 50.67 and TP2 == 47.89
|
||||
assert lo(CDS, 16, 16) <= E2 and lo(CDS, 17, 17) <= E3, "ladder-ul nu se umple"
|
||||
assert lo(CDS, 16, 17) > SL, "pullback-ul atinge stopul"
|
||||
assert hi(CDS, 21, 21) >= TP2 and hi(CDS, 23, 23) >= TP1, "țintele nu sunt atinse"
|
||||
assert TP2 < TP1, "pe prețul mediu ținta de 1R vine mai jos, nu mai sus"
|
||||
# stopul de 2/3 stă la o treime deasupra low-ului, nu la jumătate
|
||||
assert abs((SL - DOJI_LO) - H_DOJI / 3) < 0.01, "stopul nu e la 2/3 din doji"
|
||||
print(f"construit: doji {DOJI_LO}-{DOJI_HI} intrări {E1}/{E2}/{E3} medie {MED}"
|
||||
f" SL {SL} TP1 {TP1} ({R1}) TP2 {TP2} ({R2})")
|
||||
|
||||
# -------------------------------------------------------------- 1. ansamblu
|
||||
deco(Chart(
|
||||
candles=CDS,
|
||||
levels=[Level(SL, f"SL {SL:.2f} = 2/3 din doji", RED, label_at="left"),
|
||||
Level(E1, f"1/3 la close {E1:.2f}", GREEN),
|
||||
Level(E2, f"limit 1/3 la {E2:.2f}", GREEN, label_at="left"),
|
||||
# la stânga ar cădea peste eticheta limitului de deasupra
|
||||
Level(E3, f"limit 1/3 la {E3:.2f}", GREEN),
|
||||
Level(MED, f"preț mediu {MED:.2f}", PURPLE, i0=17),
|
||||
Level(TP2, f"TP2 {TP2:.2f} — lectura mea", BLUE, i0=17),
|
||||
Level(TP1, f"TP1 {TP1:.2f}", BLUE)],
|
||||
marks=[Mark(14, "doji", ORANGE, "below", dy=14),
|
||||
Mark(15, "buy doji", GREEN, dy=-6),
|
||||
Mark(3, "consolidare", GRAY, "below", dy=18),
|
||||
Mark(17, "limituri umplute", GREEN, "below", dy=52)],
|
||||
zones=[zona_downtrend(CDS, 13), Zone(15, 17, "fereastra de intrare", GREEN)],
|
||||
mas=[MA(20, ORANGE, dash="4 3")],
|
||||
scale=18.0, gap=17, body_w=9, left=52, width=700, top=76, vol_h=70,
|
||||
vol_label="volum", title="MICI-S, tot trade-ul — weekly (exemplu construit)",
|
||||
caption=CONSTRUIT), "ansamblu", distante=(R1, R2, H_DOJI),
|
||||
libere=("doji", "buy doji", "limituri umplute"),
|
||||
libere_nivel=(f"TP1 {TP1:.2f}", f"SL {SL:.2f} = 2/3 din doji"))
|
||||
|
||||
# ------------------------------------------- 2. ladder-ul măsurat pe marubozu
|
||||
J_CL = ([166.00, 164.50, 165.50, 163.00, 161.00, 162.00, 159.50, 157.00,
|
||||
155.00, 153.00, 151.50, 150.00] # 0-11 downtrend
|
||||
+ [150.12] # 12 doji
|
||||
+ [157.47] # 13 marubozu, close = high
|
||||
+ [155.60, 154.00] # 14-15 pullback
|
||||
+ [155.50, 157.00, 158.60, 160.50, 162.00, 161.00, 163.50, 165.00,
|
||||
166.50, 168.00])
|
||||
J_WK = ([(0.60, 0.60)] * 12 + [(2.40, 2.60)] + [(0.00, 0.00)]
|
||||
+ [(0.70, 0.70), (0.40, 0.40)] + [(0.60, 0.60)] * 10)
|
||||
J_VL = vols(26, 44, 12, i12=58, i13=92, i14=54, i15=50, i16=58, i17=64, i18=70)
|
||||
JC = from_closes(J_CL, wicks=J_WK, vols=J_VL, start=167.00)
|
||||
J_E1 = JC[13].c
|
||||
J_HI, J_LO = hi(JC, 13, 13), lo(JC, 13, 13)
|
||||
J_E2 = round(J_HI - (J_HI - J_LO) / 3, 2)
|
||||
J_E3 = round(J_HI - (J_HI - J_LO) / 2, 2)
|
||||
assert J_E1 == 157.47 and J_HI == 157.47, "close-ul rostit e 157.47, pe high"
|
||||
assert J_E2 == 155.02, f"1/3 din marubozu trebuie să cadă pe 155.02, nu {J_E2}"
|
||||
assert J_E3 < J_E2, "1/2 din marubozu e sub 1/3 din marubozu"
|
||||
assert JC[13].c > hi(JC, 12, 12), "trigger-ul nu închide peste high-ul doji-ului"
|
||||
assert lo(JC, 14, 14) <= J_E2 and lo(JC, 15, 15) <= J_E3, "ladder-ul nu se umple"
|
||||
assert run_desc(JC, 11) >= 5, "downtrend-ul din stânga doji-ului e prea scurt"
|
||||
deco(Chart(
|
||||
candles=JC,
|
||||
levels=[Level(J_E1, f"1/3 la close {J_E1:.2f}", GREEN),
|
||||
Level(J_E2, f"limit 1/3 la {J_E2:.2f} = 1/3 din marubozu", GREEN, i0=13),
|
||||
Level(J_E3, "limit 1/3 la 1/2 din marubozu", PURPLE, label_at="left")],
|
||||
marks=[Mark(12, "doji", ORANGE, "below", dy=14),
|
||||
Mark(13, "marubozu de trigger", GREEN, dy=-26),
|
||||
Mark(15, "pullback-ul umple ambele limituri", GREEN, "below", dy=38)],
|
||||
scale=10.0, gap=17, body_w=9, left=58, width=700, vol_h=70,
|
||||
vol_label="volum", title="Ladder-ul, măsurat pe marubozu — JNJ weekly",
|
||||
caption="Ale lui: close-ul 157.47 și limit-ul de 155.02. Nivelul de 1/2 și "
|
||||
"barele din jur sunt ale mele."),
|
||||
"ladder", distante=(J_E3,),
|
||||
libere=("doji", "marubozu de trigger", "pullback-ul umple ambele limituri"))
|
||||
|
||||
# ------------------------------------------------------- 3. stopul (NVDA)
|
||||
N_CL = ([20.00, 23.50, 27.00, 25.00, 31.00, 38.00, 45.00, 42.00, 50.00, 55.00,
|
||||
62.00, 75.00, 90.00, 108.00, 125.00, 138.00] # 0-15 uptrend lung
|
||||
+ [150.00, 138.00, 126.00, 115.00, 101.00] # 16-20 downtrend, 5 bare
|
||||
+ [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 + [(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)
|
||||
N_LO, N_HI = lo(NC, 21, 21), hi(NC, 21, 21)
|
||||
assert (N_LO, round(N_HI - N_LO, 2)) == (86.00, 28.00), (N_LO, N_HI)
|
||||
assert abs(NC[21].c - NC[21].o) <= 0.10 * 28.00, "candela 21 nu e doji"
|
||||
assert NC[22].c == 133.00 and NC[22].c > N_HI, "trigger-ul închide la 133, peste doji"
|
||||
assert hi(NC, 27, 27) >= 182.00, "seria trebuie să ajungă la 182"
|
||||
# cifrele pe care le afirmă textul capitolului, verificate pe desen
|
||||
assert abs((133.00 - 86.00) / 133.00 * 100 - 35.3) < 0.1, "distanța 133→86 nu e 35,3%"
|
||||
assert abs((133.00 - 94.00) / 133.00 * 100 - 29.3) < 0.1, "distanța 133→94 nu e 29,3%"
|
||||
SL_STRICT = round(86.00 + 28.00 / 3, 2)
|
||||
assert SL_STRICT == 95.33, SL_STRICT
|
||||
print(f" NVDA: 2/3 din doji = {SL_STRICT} strict, el citește 94 „din ochi”")
|
||||
deco(Chart(
|
||||
candles=NC,
|
||||
levels=[Level(86.00, "sub low-ul doji-ului: 86", RED, label_at="left"),
|
||||
Level(94.00, "SL 2/3 din doji: 94", RED, label_at="left"),
|
||||
Level(133.00, "1/3 la close: 133", GREEN),
|
||||
Level(182.00, "ținta rostită: 182", BLUE)],
|
||||
marks=[Mark(21, "doji monthly, înălțime 28", ORANGE, "below", dy=34),
|
||||
Mark(22, "marubozu de trigger", GREEN, dy=-118)],
|
||||
zones=[zona_downtrend(NC, 20)],
|
||||
mas=[MA(20, ORANGE, 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="Stopul, cele două variante — NVDA monthly",
|
||||
caption="Ale lui: 86, 94 (citit din ochi), 133, 182 și înălțimea de 28; "
|
||||
"barele din jur sunt ale mele."),
|
||||
"stop", intregi=(86, 94, 133, 182, 28),
|
||||
libere=("doji monthly, înălțime 28", "marubozu de trigger"))
|
||||
|
||||
# ---------------------------------------------- 4. cele două ținte (zoom)
|
||||
cl4, wk4, vl4 = CL[9:], WK[9:], VL[9:]
|
||||
cds4 = from_closes(cl4, wicks=wk4, vols=vl4, start=CL[8])
|
||||
assert lo(cds4, 5, 5) == DOJI_LO and cds4[6].c == E1, "zoom-ul mută seria"
|
||||
deco(Chart(
|
||||
candles=cds4,
|
||||
levels=[Level(SL, f"SL {SL:.2f}", RED, label_at="left"),
|
||||
Level(MED, f"preț mediu {MED:.2f}", PURPLE),
|
||||
Level(E1, f"1/3 la {E1:.2f}", GREEN),
|
||||
Level(TP2, f"TP2 {TP2:.2f}", BLUE),
|
||||
Level(TP1, f"TP1 {TP1:.2f}", BLUE)],
|
||||
arrows=[Arrow(10, f"TP2 = 1R pe prețul mediu ({R2:.2f}) — lectura mea",
|
||||
price=TP2, where="left", color=BLUE, dx=-6, dy=-16),
|
||||
Arrow(12, f"TP1 = 1R pe prima tranșă ({R1:.2f})", price=TP1,
|
||||
where="above", color=BLUE, dy=-10)],
|
||||
mas=[MA(20, ORANGE, dash="4 3", text="SMA-20")],
|
||||
scale=13.0, gap=28, body_w=14, left=60, width=700, top=56,
|
||||
title="Cele două ținte — weekly (exemplu construit)",
|
||||
caption="Lectura mea: mediind în jos, TP2 vine înaintea lui TP1. "
|
||||
"Fraza-sursă e neinteligibilă exact aici."),
|
||||
# etichetele de săgeată sunt legate de desen prin coada lor, deci se
|
||||
# verifică doar etichetele de nivel
|
||||
"tinte", distante=(R1, R2),
|
||||
libere_nivel=(f"TP1 {TP1:.2f}", f"TP2 {TP2:.2f}", f"SL {SL:.2f}"))
|
||||
|
||||
# ------------------------------- 5. trail-ul, pe timeframe-ul de sub decizie
|
||||
cl5 = (ramp(44.00, 50.00, 5) + [49.20, 48.60, 49.40] # 0-7 trail 1
|
||||
+ ramp(49.40, 56.00, 5) + [55.00, 54.20, 55.40] # 8-15 trail 2
|
||||
+ ramp(55.40, 62.00, 5) + [61.00, 60.20, 61.40] # 16-23 trail 3
|
||||
+ ramp(61.40, 67.00, 4) + [66.20, 65.60]) # 24-29 trail 4
|
||||
cds5 = from_closes(cl5, wicks=[(0.40, 0.40)] * 30, vols=vols(30, 50, 12), start=43.00)
|
||||
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)
|
||||
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}"
|
||||
# trail-ul pe TF-ul deciziei: un singur swing low în toată fereastra, mai jos
|
||||
# decât toate cele patru mutări de pe TF-ul mic
|
||||
TF_MARE = lo(cds5, 0, 3)
|
||||
assert TF_MARE < t1 < t2 < t3 < t4, "trail-ul de pe TF-ul mare nu e cel mai de jos"
|
||||
assert all(c.l >= TF_MARE - 1e-9 for c in cds5), "trail-ul de pe TF-ul mare e lovit"
|
||||
|
||||
|
||||
def trail_tf_mare(ch):
|
||||
"""Linia groasă din caption: stopul dacă trail-ul ar sta pe TF-ul deciziei."""
|
||||
y = ch._y(TF_MARE)
|
||||
return [f'<line x1="24" y1="{y:.1f}" x2="{ch.width - 14}" y2="{y:.1f}" '
|
||||
f'stroke="{PURPLE}" stroke-width="3"/>',
|
||||
f'<text x="{ch.width - 28}" y="{y + 16:.1f}" fill="{PURPLE}" '
|
||||
f'text-anchor="end">trail pe TF-ul deciziei: {TF_MARE:.2f}, '
|
||||
f'o singură mutare</text>']
|
||||
deco(Chart(
|
||||
candles=cds5,
|
||||
levels=[Level(t1, f"trail 1: {t1:.2f}", RED, i0=SW[0]),
|
||||
Level(t2, f"trail 2: {t2:.2f}", RED, i0=SW[1]),
|
||||
Level(t3, f"trail 3: {t3:.2f}", RED, i0=SW[2]),
|
||||
Level(t4, f"trail 4: {t4:.2f}", RED, i0=SW[3])],
|
||||
marks=[Mark(6, "swing low 1", RED, "below", dy=14),
|
||||
Mark(14, "swing low 2", RED, "below", dy=14),
|
||||
Mark(22, "swing low 3", RED, "below", dy=14),
|
||||
Mark(29, "swing low 4", RED, "below", dy=34)],
|
||||
scale=7.0, gap=17, body_w=9, left=52, width=700, top=64, vol_h=70,
|
||||
vol_label="volum",
|
||||
title="Trail pe swing low, pe timeframe-ul de sub decizie (exemplu construit)",
|
||||
caption="Patru mutări pe TF-ul mic; pe TF-ul deciziei, o singură dată "
|
||||
"(linia groasă)."),
|
||||
"trail", distante=(TF_MARE,), extra=trail_tf_mare,
|
||||
libere=("swing low 1", "swing low 4"))
|
||||
|
||||
# ------------------------------------- 6. când nu merge (Tesla, 217.02/214.25)
|
||||
T_CL = ([320.00, 312.00, 304.00, 298.00]
|
||||
+ [290.00, 282.00, 272.00, 262.00, 252.00, 244.00, 236.00, 230.00]
|
||||
+ [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])
|
||||
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)] * 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 round(217.02 - 214.25, 2) == 2.77, "distanța dintre minime nu e 2.77"
|
||||
assert len(TC) == 24 and len(TC[17:24]) == 7, "urcarea rostită e de 7 săptămâni"
|
||||
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(217.02, "low-ul hammer-ului: 217.02", ORANGE, label_at="left"),
|
||||
Level(214.25, "minimul de după: 214.25", RED, label_dy=18)],
|
||||
marks=[Mark(12, "primul semnal", ORANGE, dy=-72),
|
||||
Mark(17, "al doilea semnal: acesta merge", GREEN, dy=-34),
|
||||
Mark(23, "7 săptămâni de urcare", GREEN, dy=-10)],
|
||||
arrows=[Arrow(15, "stopul pus sub 217.02\na fost luat aici", price=214.25,
|
||||
where="below", color=RED, dy=4)],
|
||||
mas=[MA(20, ORANGE, 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",
|
||||
caption="Ale lui: 217.02, 214.25 și cele 7 săptămâni de după al doilea "
|
||||
"semnal; restul barelor e al meu."),
|
||||
"nu_merge", libere=("primul semnal", "7 săptămâni de urcare"))
|
||||
|
||||
# ------------------------------------------------- 7. rutina de scanare
|
||||
SVG["rutina"] = """<svg viewBox="0 0 700 330" xmlns="http://www.w3.org/2000/svg" style="width:100%;max-width:700px;height:auto;font:12px sans-serif">
|
||||
<text x="20" y="22" fill="#333" style="font-weight:bold">Rutina: scanezi doji-uri, aștepți buy doji-ul în radar screen</text>
|
||||
<rect x="20" y="44" width="200" height="56" fill="#eef4ff" stroke="#1a5fb4"/>
|
||||
<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, ținută patru luni</text>
|
||||
<text x="262" y="86" fill="#333">într-un excel, NYSE + Nasdaq</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>
|
||||
<text x="492" y="86" fill="#333">lista stă acolo și clipocește</text>
|
||||
<line x1="222" y1="72" x2="246" y2="72" stroke="#1a5fb4" stroke-width="1.6"/>
|
||||
<line x1="452" y1="72" x2="476" y2="72" stroke="#1a5fb4" stroke-width="1.6"/>
|
||||
<line x1="580" y1="102" x2="580" y2="128" stroke="#1a5fb4" stroke-width="1.6"/>
|
||||
<rect x="480" y="130" width="200" height="56" fill="#e9f7ee" stroke="#188a3e"/>
|
||||
<text x="492" y="152" fill="#188a3e" style="font-weight:bold">4. Clipocește = buy doji</text>
|
||||
<text x="492" y="172" fill="#333">îl vezi înainte de close</text>
|
||||
<text x="20" y="128" fill="#555">Scanner-ul vede doar candela închisă: un buy doji weekly l-ai</text>
|
||||
<text x="20" y="148" fill="#555">afla vineri după 23:00, iar unul monthly în ultima noapte a lunii.</text>
|
||||
<text x="20" y="168" fill="#555">Radar screen-ul citește candela în formare, deci îl prinzi cu ore</text>
|
||||
<text x="20" y="188" fill="#555">sau zile înainte să se închidă săptămâna ori luna.</text>
|
||||
<text x="20" y="224" fill="#333" style="font-weight:bold">Când te uiți</text>
|
||||
<text x="20" y="244" fill="#555">Weekly: vineri, cu una-două ore înainte de închidere, sau chiar de joi.</text>
|
||||
<text x="20" y="264" fill="#555">Monthly: cu două-trei zile înainte de finalul lunii.</text>
|
||||
<text x="20" y="292" fill="#333" style="font-weight:bold">De ce patru luni</text>
|
||||
<text x="20" y="312" fill="#555">Breakout-ul peste doji poate veni și în a patra perioadă, deci lista nu se golește mai repede.</text>
|
||||
</svg>"""
|
||||
|
||||
# ---------------------------------------------------------------- scriere
|
||||
for name, svg in SVG.items():
|
||||
(OUT / f"micis_{name}.svg").write_text(svg, encoding="utf-8")
|
||||
print(f"{len(SVG)} svg-uri scrise în {OUT}")
|
||||
|
||||
if MD.exists():
|
||||
md = MD.read_text(encoding="utf-8")
|
||||
lipsa = [n for n in SVG if f"<!-- DIAGRAMA: {n} -->" not in md]
|
||||
assert not lipsa, f"marcaje lipsă în capitol: {lipsa}"
|
||||
for name, svg in SVG.items():
|
||||
md = re.sub(rf"<!-- DIAGRAMA: {name} -->(\n[\s\S]*?\n<!-- /DIAGRAMA: {name} -->)?",
|
||||
lambda _m: (f"<!-- DIAGRAMA: {name} -->\n{svg.strip()}\n"
|
||||
f"<!-- /DIAGRAMA: {name} -->"), md, count=1)
|
||||
MD.write_text(md, encoding="utf-8")
|
||||
print(f"{len(SVG)} diagrame substituite în {MD.name}")
|
||||
else:
|
||||
print(f"{MD.name} nu există încă — doar svg-urile sunt scrise")
|
||||
Reference in New Issue
Block a user