Analiza Zilnica 10: sinteza celor noua documente (3 diagrame)
Documentul cerut explicit de user ca ultim pas: nu un rezumat al celor nouă, ci cum se leaga strategiile intre ele. Grila de decizie, in 8 etape, reconstituita si marcata ca atare - singurul flux pe care il spune explicit e cel din 04.09 (fundamental -> monthly -> weekly -> daily -> MBT-10 la final). Documentul spune deschis ca ordinea din briefingul meu (trigger -> volum -> pivot) nu apare asa in surse: volumul si pivotul se verifica la trei etape diferite, nu dupa trigger. Cele trei diagrame urmăresc aceeasi poziție prin toata grila, pe doua timeframe-uri: weekly (double bottom cu piciorul 2 mai jos pe volum mai mic, buy doji peste pivot, higher low peste pivotul lunii) si daily (buy hammer pe volum 2.2x, close in MBT-10, intrare 75.60, SL 73.60, ieșire in trei pozitii: R1 3.1R, apoi stop pe break-even, R2 4.1R, trailing 3.5R), plus varianta NU care se opreste la trigger. Barele weekly sunt agregate din seria daily, deci cifrele se potrivesc pe ambele grafice - nu sunt doua desene independente. 9 contradictii intre documente, fiecare cu ambele variante si cu ce spun sursele: trei unde sursele decid, trei doar parțial, si trei marcate "nu reiese" (care tinta, gap-ul cumparat sau jumatatea lui, ce pivot pe weekly la MICI). Nu sunt netezite. Un tabel "ce confirma ce" pe patru trepte (veto / necesar / intarește / bonus), cu clasificarea marcata ca a autorului, si o lista de verificare de 17 puncte cu ce opreste setup-ul. 8 intrebari deschise, intre care PAM/PPAM, "pivot + 2", "proiectie neutra", definitia MBT-10 si pivotul pe weekly. Cele 54 de link-uri interne sunt reverificate de mine dupa ce toate cele noua documente s-au schimbat sub el: niciunul rupt, nici in folder, nici intre foldere. Pagina regenerata, 91 de pagini. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MtSTyTmt6AbCL9j5ajEDm1
This commit is contained in:
319
gen/az_sinteza.py
Normal file
319
gen/az_sinteza.py
Normal file
@@ -0,0 +1,319 @@
|
||||
"""Diagramele pentru summaries/08_ANALIZA_ZILNICA/10_sinteza.md.
|
||||
|
||||
Un singur setup construit (fără ticker), urmărit prin toată grila:
|
||||
weekly (structură, pivot, volum, buy doji W, higher low) -> daily (trigger,
|
||||
MBT-10, intrare, SL, ținte în trepte, break-even, trailing) -> varianta NU.
|
||||
|
||||
Barele weekly 24-31 sunt AGREGATE din seria daily (5 zile = 1 săptămână),
|
||||
deci cele două grafice spun aceeași poveste cu aceleași cifre. Pivoții
|
||||
monthly se calculează din lunile de 4 săptămâni ale seriei weekly.
|
||||
Rulează: .venv/bin/python gen/az_sinteza.py
|
||||
"""
|
||||
import re
|
||||
import sys
|
||||
from dataclasses import dataclass, field
|
||||
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
|
||||
|
||||
MD = Path("/workspace/atm-curs-dl/summaries/08_ANALIZA_ZILNICA/10_sinteza.md")
|
||||
GRAY, RED, GREEN, BLUE, ORANGE, PURPLE = "#777", "#c00", "#188a3e", "#1a5fb4", "#b06000", "#6a3d9a"
|
||||
STYLE = dict(gap=16, body_w=10, left=44, width=700)
|
||||
svgs = {}
|
||||
|
||||
|
||||
# ------------------------------------------------ PChart, copiat din gen/az_pivoti.py
|
||||
@dataclass
|
||||
class Seg:
|
||||
"""nivel valabil doar pe barele i0..i1 (o lună)"""
|
||||
i0: int
|
||||
i1: int
|
||||
price: float
|
||||
text: str
|
||||
color: str = ORANGE
|
||||
label_at: str = "out"
|
||||
dy: float = -5.0
|
||||
dash: str = ""
|
||||
|
||||
|
||||
def spread(items, gap=14):
|
||||
items = sorted(items, key=lambda t: t[0])
|
||||
out = []
|
||||
for it in items:
|
||||
y = it[0] if not out else max(it[0], out[-1][0] + gap)
|
||||
out.append((y,) + tuple(it[1:]))
|
||||
return out
|
||||
|
||||
|
||||
@dataclass
|
||||
class PChart(Chart):
|
||||
segs: list = field(default_factory=list)
|
||||
seps: list = field(default_factory=list)
|
||||
pad_px: float = 24.0
|
||||
lm: int = 104
|
||||
pad_bot_px: float = 0.0
|
||||
|
||||
def render(self) -> str:
|
||||
n = len(self.candles)
|
||||
self.left = self.lm if any(s.label_at == "lm" for s in self.segs) else self.left
|
||||
segs = list(self.segs) + [Seg(0, n - 1, lv.price, lv.text, lv.color, "out", dash="4 3")
|
||||
for lv in self.levels]
|
||||
saved_lv, saved_ma = list(self.levels), list(self.mas)
|
||||
longest = max([len(s.text) for s in segs if s.label_at == "out"] + [len(m.text) for m in saved_ma] + [0])
|
||||
self.width = max(self.width, int(self._cx(n - 1) + self.gap / 2 + 6 + longest * 6.2 + 8))
|
||||
top_price = max([c.h for c in self.candles] + [s.price for s in segs])
|
||||
self.levels = [Level(s.price, "", "none") for s in segs]
|
||||
self.levels.append(Level(top_price + self.pad_px / self.scale, "", "none"))
|
||||
if self.pad_bot_px:
|
||||
low_price = min([c.l for c in self.candles] + [s.price for s in segs])
|
||||
self.levels.append(Level(low_price - self.pad_bot_px / self.scale, "", "none"))
|
||||
self.mas = [MA(m.period, m.color, m.dash) for m in saved_ma]
|
||||
svg = self.render_base()
|
||||
self.levels, self.mas = saved_lv, saved_ma
|
||||
parts = svg.split("\n ")
|
||||
extra = []
|
||||
for k in self.seps:
|
||||
x = self._cx(k) - self.gap / 2
|
||||
extra.append(f'<line x1="{x:.1f}" y1="{self.top - 4:.1f}" x2="{x:.1f}" '
|
||||
f'y2="{self._body_bottom:.1f}" stroke="#bbb" stroke-dasharray="2 3"/>')
|
||||
closes = [c.c for c in self.candles]
|
||||
xr = self._cx(n - 1) + self.gap / 2 + 6
|
||||
out_lab = [(self._y(s.price) + 4, s) for s in segs if s.label_at == "out"]
|
||||
out_lab += [(self._y(sum(closes[-m.period:]) / m.period) + 4, Seg(0, 0, 0, m.text, m.color))
|
||||
for m in saved_ma if m.text]
|
||||
placed = {id(s): y for y, s in spread(out_lab)}
|
||||
placed.update({id(s): y for y, s in spread([(self._y(s.price) + 4, s) for s in segs if s.label_at == "lm"])})
|
||||
for s in segs:
|
||||
x0, x1, y = self._cx(s.i0) - self.gap / 2, self._cx(s.i1) + self.gap / 2, self._y(s.price)
|
||||
dash = f' stroke-dasharray="{s.dash}"' if s.dash else ""
|
||||
extra.append(f'<line x1="{x0:.1f}" y1="{y:.1f}" x2="{x1:.1f}" y2="{y:.1f}" '
|
||||
f'stroke="{s.color}" stroke-width="{1.5 if s.dash else 2}"{dash}/>')
|
||||
if s.label_at == "out":
|
||||
extra.append(f'<text x="{xr:.1f}" y="{placed[id(s)]:.1f}" fill="{s.color}">{s.text}</text>')
|
||||
elif s.label_at == "lm":
|
||||
extra.append(f'<text x="{x0 - 6:.1f}" y="{placed[id(s)]:.1f}" fill="{s.color}" '
|
||||
f'text-anchor="end">{s.text}</text>')
|
||||
for y, s in out_lab:
|
||||
if s.i1 == 0 and s.price == 0:
|
||||
extra.append(f'<text x="{xr:.1f}" y="{placed[id(s)]:.1f}" fill="{s.color}">{s.text}</text>')
|
||||
k = 2 if self.title else 1
|
||||
return "\n ".join(parts[:k] + extra + parts[k:])
|
||||
|
||||
def render_base(self):
|
||||
svg = Chart.render(self)
|
||||
svg = re.sub(r'\n <line [^>]*stroke="none"[^>]*/>\n <text [^>]*fill="none"[^>]*></text>', "", svg)
|
||||
prices = [p for c in self.candles for p in (c.o, c.h, c.l, c.c)] + [lv.price for lv in self.levels]
|
||||
self._body_bottom = self.top + (max(prices) - min(prices)) * self.scale
|
||||
return svg
|
||||
|
||||
|
||||
def pivots(bars):
|
||||
"""floor pivots din H/L/C ale perioadei încheiate"""
|
||||
H, L, C = max(c.h for c in bars), min(c.l for c in bars), bars[-1].c
|
||||
P = (H + L + C) / 3
|
||||
return dict(H=H, L=L, C=C, P=P, R1=2 * P - L, S1=2 * P - H, R2=P + (H - L), S2=P - (H - L))
|
||||
|
||||
|
||||
def px(ch, p0, p1):
|
||||
"""distanța în pixeli între două prețuri, după render"""
|
||||
return ch._y(p0) - ch._y(p1)
|
||||
|
||||
|
||||
def f2(x):
|
||||
return f"{x:.2f}"
|
||||
|
||||
|
||||
# ================================================================ seria WEEKLY, barele 0-23
|
||||
wk_cl = [88.4, 87.0, 85.2, 83.6, # M0 downtrend
|
||||
85.4, 86.6, 84.8, 82.6, # M1 bounce: bara 5 = vârful anterior (lower high)
|
||||
80.4, 78.2, 76.6, 74.2, # M2
|
||||
72.4, 70.2, 69.0, 70.8, # M3 bara 14 = picior 1
|
||||
72.0, 70.6, 68.8, 67.9, # M4 bara 19 = picior 2, mai jos
|
||||
68.0, 72.6, 74.4, 75.8] # M5 bara 20 doji, 21 buy doji W, raliu
|
||||
wk_w = [(0.4, 0.4)] * 6 + [(0.1, 0.4)] + [(0.4, 0.4)] * 6 + [(0.3, 0.5), (0.3, 0.7), (0.3, 0.3), (0.3, 0.3), (0.3, 0.3), (0.3, 0.4),
|
||||
(0.3, 0.5), (0.6, 0.5), (0.3, 0.3), (0.3, 0.3), (0.3, 0.3)]
|
||||
wk_v = [60, 62, 66, 64, 45, 42, 64, 68, 70, 72, 74, 78, 82, 90, 96, 60, 55, 58, 62, 54, 50, 118, 90, 80]
|
||||
weekly = from_closes(wk_cl, wicks=wk_w, vols=wk_v, start=90.0)
|
||||
|
||||
# ================================================================ seria DAILY = săptămânile 24-31
|
||||
d_cl = [76.6, 77.3, 77.0, 77.9, 78.2, # w24 raliul continuă, vârf de raliu
|
||||
77.4, 76.5, 76.9, 75.8, 75.0, # w25 pullback
|
||||
75.3, 74.4, 74.3, # w26 z12 = hammer: higher low
|
||||
74.9, # z13 buy hammer D: close peste high-ul hammer-ului
|
||||
75.6, # z14 close în MBT-10 -> intrare
|
||||
76.4, 77.3, 78.1, 79.0, 79.6, # w27
|
||||
79.1, 78.8, 79.4, 80.3, 80.9, # w28 (M7 începe la z20)
|
||||
81.6, 82.3, 81.8, 82.6, 83.2, # w29
|
||||
83.0, 83.8, 84.4, 84.1, 83.5, # w30
|
||||
82.6, 82.9, 81.9, 81.2, 81.6] # w31
|
||||
d_w = ([(0.3, 0.3)] * 5 + [(0.3, 0.3)] * 5 + [(0.3, 0.3), (0.2, 0.3), (0.1, 0.5), (0.2, 0.3), (0.3, 0.2)]
|
||||
+ [(0.3, 0.3)] * 25)
|
||||
d_v = [55, 52, 44, 50, 48,
|
||||
36, 38, 30, 40, 36,
|
||||
32, 34, 38, 92, 80,
|
||||
66, 60, 58, 62, 56,
|
||||
44, 40, 50, 58, 54,
|
||||
56, 60, 42, 55, 52,
|
||||
40, 50, 54, 46, 58,
|
||||
60, 44, 62, 58, 40]
|
||||
daily = from_closes(d_cl, wicks=d_w, vols=d_v, start=wk_cl[-1])
|
||||
assert len(daily) == 40
|
||||
|
||||
|
||||
def agg(bars):
|
||||
return Candle(bars[0].o, max(c.h for c in bars), min(c.l for c in bars), bars[-1].c,
|
||||
vol=sum(c.vol for c in bars) / 5)
|
||||
|
||||
|
||||
weekly += [agg(daily[k:k + 5]) for k in range(0, 40, 5)]
|
||||
assert len(weekly) == 32
|
||||
for a, b in zip(weekly, weekly[1:]):
|
||||
assert abs(a.c - b.o) < 1e-9, "seria weekly are gol între bare"
|
||||
|
||||
# ------------------------------------------------ pivoți monthly (luni de 4 săptămâni)
|
||||
month = lambda m: weekly[4 * m:4 * m + 4] # noqa: E731
|
||||
PV = {m: pivots(month(m - 1)) for m in range(1, 8)} # PV[m] = nivelurile lunii m
|
||||
P5, P6, P7 = PV[5]["P"], PV[6]["P"], PV[7]["P"]
|
||||
|
||||
# ------------------------------------------------ afirmațiile din text, pe weekly
|
||||
V_IDX, LEG1, LEG2, DOJI, BDW, HLW = 5, 14, 19, 20, 21, 26
|
||||
VARF = weekly[V_IDX].h
|
||||
assert VARF > weekly[4].h and VARF > weekly[6].h and VARF < weekly[0].o, "bara 5 nu e lower high"
|
||||
leg1, leg2 = weekly[LEG1].l, min(c.l for c in weekly[17:21])
|
||||
assert leg1 == min(c.l for c in weekly[12:16]) and leg2 < leg1, "piciorul 2 nu e mai jos"
|
||||
assert wk_v[LEG2] < wk_v[LEG1] and wk_v[18] < wk_v[13], "fără divergență de volum la piciorul 2"
|
||||
assert abs(weekly[DOJI].o - weekly[DOJI].c) <= 0.15, "bara 20 nu e doji"
|
||||
assert weekly[BDW].c > weekly[DOJI].h and weekly[BDW].c > P5, "buy doji W nu închide peste high doji și peste pivot"
|
||||
assert wk_v[BDW] == max(c.vol for c in weekly), "buy doji W nu are cel mai mare volum"
|
||||
assert weekly[DOJI].c < P5, "doji-ul trebuie să închidă sub pivotul lunii"
|
||||
assert P6 > P5, "luna 6 trebuie să fie în proiecție bull"
|
||||
hl = daily[12].l
|
||||
assert weekly[HLW].l == hl, "low-ul săptămânii 26 trebuie să fie higher low-ul din daily"
|
||||
assert hl > P6 and hl > leg2, "higher low-ul nu e deasupra pivotului lunii"
|
||||
top_raliu = max(c.h for c in daily[:5])
|
||||
assert top_raliu == max(c.h for c in daily[:12]), "vârful raliului trebuie să fie în w24"
|
||||
print(f"W varf {VARF:.2f} leg1 {leg1:.2f} leg2 {leg2:.2f} BDW close {weekly[BDW].c:.2f} P5 {P5:.2f} "
|
||||
f"P6 {P6:.2f} P7 {P7:.2f} HL {hl:.2f} top raliu {top_raliu:.2f}")
|
||||
|
||||
# ------------------------------------------------ execuția, pe daily
|
||||
HAM, TRG, ENT = 12, 13, 14
|
||||
ham = daily[HAM]
|
||||
assert ham.h - max(ham.o, ham.c) <= 0.15 and min(ham.o, ham.c) - ham.l >= 2 * abs(ham.o - ham.c), "z12 nu e hammer"
|
||||
assert daily[TRG].c > ham.h and daily[TRG].l > ham.l, "z13 nu confirmă swing low-ul (candela din dreapta)"
|
||||
avg20 = sum(d_v[:TRG]) / TRG
|
||||
assert d_v[TRG] >= 1.8 * avg20, "trigger-ul nu are volum țeavă"
|
||||
assert sum(d_v[5:12]) / 7 < 0.8 * sum(d_v[:5]) / 5, "pullback-ul nu are volum în scădere"
|
||||
entry = daily[ENT].c
|
||||
SL = round(hl - 0.2, 2)
|
||||
risk = entry - SL
|
||||
R1, R2 = PV[7]["R1"], PV[7]["R2"]
|
||||
assert entry < R1 < R2 < VARF, "treptele nu sunt în ordine"
|
||||
tp1_hit = next(i for i in range(20, 40) if daily[i].h >= R1)
|
||||
tp2_hit = next(i for i in range(tp1_hit, 40) if daily[i].h >= R2)
|
||||
assert all(c.l > entry for c in daily[tp1_hit:]), "după TP1, stopul pe break-even ar fi fost lovit"
|
||||
assert all(c.l > SL for c in daily[ENT + 1:]), "SL-ul ar fi fost lovit"
|
||||
# trailing stop (08 §5): low-ul ultimei candele care a închis peste high-ul precedentei; urcă doar
|
||||
trail, t_exit, trail_at_exit = None, None, None
|
||||
for i in range(ENT + 1, 40):
|
||||
if trail is not None and daily[i].c < trail:
|
||||
t_exit, trail_at_exit = i, trail
|
||||
break
|
||||
if daily[i].c > daily[i - 1].h:
|
||||
trail = max(trail or 0, daily[i].l)
|
||||
assert t_exit is not None, "trailing-ul nu iese în fereastra diagramei"
|
||||
exit3 = daily[t_exit].c
|
||||
rr = lambda p: (p - entry) / risk # noqa: E731
|
||||
print(f"D entry {entry:.2f} SL {SL:.2f} risc {risk:.2f} | R1 {R1:.2f} ({rr(R1):.2f}R) z{tp1_hit} | "
|
||||
f"R2 {R2:.2f} ({rr(R2):.2f}R) z{tp2_hit} | trailing {trail_at_exit:.2f} ieșire z{t_exit} close {exit3:.2f} ({rr(exit3):.2f}R)"
|
||||
f" | vol trigger {d_v[TRG]} = {d_v[TRG] / avg20:.1f}x | P6 {P6:.2f} P7 {P7:.2f}")
|
||||
total_R = (rr(R1) + rr(R2) + rr(exit3)) / 3
|
||||
print(f" medie pe 3 poziții: {total_R:.2f}R; vârful anterior {VARF:.2f} = {rr(VARF):.2f}R, neatins")
|
||||
assert max(c.h for c in daily) < VARF
|
||||
|
||||
# ================================================================ diagrama 1: weekly
|
||||
ch = PChart(candles=weekly,
|
||||
segs=[Seg(20, 23, P5, f"pivot M5 {f2(P5)}", ORANGE),
|
||||
Seg(24, 27, P6, f"pivot M6 {f2(P6)} (bull)", ORANGE),
|
||||
Seg(28, 31, P7, f"pivot M7 {f2(P7)}", ORANGE)],
|
||||
seps=[20, 24, 28],
|
||||
levels=[Level(VARF, f"vârf anterior {f2(VARF)}", BLUE)],
|
||||
marks=[Mark(V_IDX, "vârf anterior", BLUE, "above"),
|
||||
Mark(LEG1, "picior 1", RED, "below"),
|
||||
Mark(LEG2, "picior 2", RED, "below", dy=8),
|
||||
Mark(BDW, "④ buy doji W", GREEN, "above", dy=-56),
|
||||
Mark(HLW, "⑤ higher low", GREEN, "below", dy=4)],
|
||||
mas=[MA(20, PURPLE, text="SMA 20")],
|
||||
scale=13, vol_h=70, pad_bot_px=30, title="Exemplu construit (fără ticker) — weekly",
|
||||
caption="③ picior 2 mai jos, volum mai mic; ④ buy doji peste pivot; ⑤ HL peste pivot; ⑥-⑧ pe daily.",
|
||||
**STYLE)
|
||||
svgs["sinteza_weekly"] = ch.render()
|
||||
assert px(ch, P6, hl) > 3, "higher low-ul trebuie să se vadă deasupra pivotului"
|
||||
|
||||
# ================================================================ diagrama 2: daily, execuția
|
||||
ch = PChart(candles=daily,
|
||||
segs=[Seg(0, 19, P6, f"pivot M6 {f2(P6)}", ORANGE),
|
||||
Seg(20, 39, P7, f"pivot M7 {f2(P7)}", ORANGE),
|
||||
Seg(20, 39, R1, f"TP1 = R1 M7 {f2(R1)} ({rr(R1):.1f}R)", BLUE),
|
||||
Seg(20, 39, R2, f"TP2 = R2 M7 {f2(R2)} ({rr(R2):.1f}R)", BLUE)],
|
||||
seps=[20],
|
||||
levels=[Level(entry, f"intrare {f2(entry)}", GREEN),
|
||||
Level(SL, f"SL {f2(SL)} (sub HL)", RED)],
|
||||
marks=[Mark(4, "vârf raliu", GRAY, "above"),
|
||||
Mark(HAM, "HL", GREEN, "below", dy=14),
|
||||
Mark(TRG, "⑥ buy hammer", GREEN, "below", dy=36),
|
||||
Mark(ENT, "⑦ MBT-10", GREEN, "above", dy=-34),
|
||||
Mark(tp1_hit, "TP1, SL→BE", BLUE, "above", dy=-16),
|
||||
Mark(tp2_hit, "TP2", BLUE, "above"),
|
||||
Mark(t_exit, "trailing", PURPLE, "below", dy=4)],
|
||||
scale=26, vol_h=70, pad_bot_px=64, title="Exemplu construit (fără ticker) — daily",
|
||||
caption=f"⑥ trigger pe volum {d_v[TRG] / avg20:.1f}x; ⑦ intrare la close; ⑧ 3 poziții: R1, R2, trailing.",
|
||||
**STYLE)
|
||||
svgs["sinteza_daily"] = ch.render()
|
||||
for p in (R1, R2):
|
||||
assert abs(px(ch, entry, p) / px(ch, SL, entry) - rr(p)) < 0.01, "R desenat greșit"
|
||||
|
||||
# ================================================================ diagrama 3: aceeași zi 13, varianta NU
|
||||
n_cl = d_cl[:13] + [73.9, # z13: intraday peste high-ul hammer-ului, close înapoi sub
|
||||
72.7, # z14: close sub pivot și sub HL
|
||||
73.1, 72.2, 71.5, 71.9, 71.0, 70.6, 71.2, 70.4, 70.9, 70.2, 70.7, 71.3, 70.8, 71.6]
|
||||
n_w = d_w[:13] + [(1.1, 0.3), (0.3, 0.3)] + [(0.3, 0.3)] * 14
|
||||
n_v = d_v[:13] + [30, 58, 50, 60, 56, 44, 60, 52, 40, 54, 42, 38, 36, 46, 34, 40]
|
||||
nd = from_closes(n_cl, wicks=n_w, vols=n_v, start=wk_cl[-1])
|
||||
S1 = PV[6]["S1"]
|
||||
assert nd[13].h > ham.h and nd[13].c < ham.h, "z13 trebuie să treacă intraday peste hammer și să închidă sub"
|
||||
assert n_v[13] < 0.8 * avg20, "z13 trebuie să aibă volum mic"
|
||||
assert nd[14].c < P6 and nd[14].l < hl, "z14 nu anulează higher low-ul"
|
||||
low_after = min(c.l for c in nd[14:])
|
||||
assert abs(low_after - S1) < 0.4, "căderea trebuie să se oprească în zona S1"
|
||||
print(f"NU z13 high {nd[13].h:.2f} close {nd[13].c:.2f} vol {n_v[13]} ({n_v[13] / avg20:.1f}x); "
|
||||
f"z14 close {nd[14].c:.2f}; low ulterior {low_after:.2f}; S1 {S1:.2f}")
|
||||
ch = PChart(candles=nd,
|
||||
segs=[Seg(0, len(nd) - 1, P6, f"pivot M6 {f2(P6)}", ORANGE),
|
||||
Seg(0, len(nd) - 1, S1, f"S1 M6 {f2(S1)}", RED)],
|
||||
levels=[Level(hl, f"HL? {f2(hl)}", GRAY)],
|
||||
marks=[Mark(4, "vârf raliu", GRAY, "above"),
|
||||
Mark(13, "fără trigger", RED, "above", dy=-6),
|
||||
Mark(14, "sub pivot", RED, "below", dy=4)],
|
||||
scale=26, vol_h=70, pad_bot_px=20, title="Exemplu construit (fără ticker) — daily, varianta NU",
|
||||
caption=f"Z13 trece intraday peste hammer, închide sub, volum {n_v[13] / avg20:.1f}x: grila se oprește la ⑥.",
|
||||
**STYLE)
|
||||
svgs["sinteza_nu"] = ch.render()
|
||||
|
||||
# ------------------------------------------------ cifre exportate pentru text (verificate de ochi în .md)
|
||||
FACTS = dict(varf=VARF, leg1=leg1, leg2=leg2, bdw=weekly[BDW].c, P5=P5, P6=P6, P7=P7, hl=hl, top=top_raliu,
|
||||
entry=entry, SL=SL, risk=risk, R1=R1, R2=R2, rR1=rr(R1), rR2=rr(R2), trail=trail_at_exit,
|
||||
exit3=exit3, rexit=rr(exit3), avgR=total_R, volx=d_v[TRG] / avg20, rvarf=rr(VARF),
|
||||
ham_h=ham.h, n13h=nd[13].h, n13c=nd[13].c, n14c=nd[14].c, S1=S1, n13vx=n_v[13] / avg20,
|
||||
tp1z=tp1_hit, tp2z=tp2_hit, exz=t_exit)
|
||||
print({k: round(v, 2) for k, v in FACTS.items()})
|
||||
|
||||
# ------------------------------------------------ substituție în .md
|
||||
if MD.exists():
|
||||
md = MD.read_text(encoding="utf-8")
|
||||
for name, svg in svgs.items():
|
||||
pat = re.compile(rf"<!--SVG:{name}-->.*?<!--/SVG-->", re.S)
|
||||
assert pat.search(md), f"marcatorul {name} lipsește din .md"
|
||||
md = pat.sub(lambda _m: f"<!--SVG:{name}-->\n{svg}\n<!--/SVG-->", md)
|
||||
MD.write_text(md, encoding="utf-8")
|
||||
print("scris", MD)
|
||||
Reference in New Issue
Block a user