MODUL 5: ultimele patru suprapuneri de eticheta, si verificatorul scos in gen/eticheta_libera.py
Assert-ul care verifica daca o eticheta sta lipita de o linie a devenit modul propriu, importat din ambele generatoare de patternuri. Vede acum si <polyline> (mediile mobile - punctul lui orb) si, optional, corpurile candelelor. Avea si un bug tacut: regexul cerea culoare pe 6 cifre, deci sarea peste tot ce e desenat cu #c00, adica exact sagetile si nivelurile rosii. Are demo() cu self-check. La bull_flag eticheta SMA-20 nu e mutabila din generator - pozitia ei o calculeaza svg_candles - asa ca media e numita in caption, ca la cup with handle. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ThN7ixZrowca8aTGrK1MUJ
This commit is contained in:
@@ -15,7 +15,9 @@ import re
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, "/workspace/atm-curs-dl")
|
||||
sys.path.insert(0, "/workspace/atm-curs-dl/gen")
|
||||
from svg_candles import Chart, Level, Mark, MA, Zone, Arrow, from_closes # noqa: E402
|
||||
from eticheta_libera import eticheta_libera # noqa: E402
|
||||
|
||||
MD = ("/workspace/atm-curs-dl/summaries/06_MODUL_5/"
|
||||
"03_patternuri_complexe_partea_a_patra.md")
|
||||
@@ -58,31 +60,7 @@ def txt(i, p, s, color="#8b5cf6", anchor="middle", dx=0.0, dy=0.0, bold=True):
|
||||
return dict(i=i, p=p, s=s, color=color, anchor=anchor, dx=dx, dy=dy, bold=bold)
|
||||
|
||||
|
||||
def _desprinse(svg, name, etichete, min_px=5.0):
|
||||
"""Etichetele date nu au voie sa stea pe nicio linie (regresia 11/12)."""
|
||||
# fitilele candelelor (#1a1a1a) nu se numara: desenul le traverseaza oricum
|
||||
lines = [tuple(map(float, m.groups()[:4])) for m in re.finditer(
|
||||
r'<line x1="(-?[\d.]+)" y1="(-?[\d.]+)" x2="(-?[\d.]+)" y2="(-?[\d.]+)"'
|
||||
r'[^/]*?stroke="(#[0-9a-f]{6})"', svg) if m.group(5) != "#1a1a1a"]
|
||||
for m in re.finditer(r'<text x="(-?[\d.]+)" y="(-?[\d.]+)"([^>]*)>([^<]*)</text>', svg):
|
||||
tx, ty, attrs, s = float(m.group(1)), float(m.group(2)), m.group(3), m.group(4)
|
||||
if s not in etichete:
|
||||
continue
|
||||
w = 6.2 * len(s)
|
||||
x0 = tx if 'anchor="start"' in attrs else tx - w if 'anchor="end"' in attrs else tx - w / 2
|
||||
x1, top, bot = x0 + w, ty - 9 - min_px, ty + 3 + min_px
|
||||
for lx1, ly1, lx2, ly2 in lines:
|
||||
if max(lx1, lx2) < x0 or min(lx1, lx2) > x1:
|
||||
continue
|
||||
ys = [ly1 + (ly2 - ly1) * (max(min(x, max(lx1, lx2)), min(lx1, lx2)) - lx1)
|
||||
/ ((lx2 - lx1) or 1) for x in (x0, x1)] if lx1 != lx2 else [ly1, ly2]
|
||||
if min(ys) <= bot and max(ys) >= top:
|
||||
raise AssertionError(
|
||||
f"{name}: eticheta '{s}' sta pe linia "
|
||||
f"({lx1:.0f},{ly1:.0f})-({lx2:.0f},{ly2:.0f})")
|
||||
|
||||
|
||||
def deco(ch, name, segs=(), texts=(), distante=(), clear=()):
|
||||
def deco(ch, name, segs=(), texts=(), distante=(), clear=(), rects=False):
|
||||
"""Randează graficul, injectează liniile/textele, verifică, salvează."""
|
||||
saved = ch.top, ch.left, ch.width
|
||||
try:
|
||||
@@ -114,7 +92,7 @@ def deco(ch, name, segs=(), texts=(), distante=(), clear=()):
|
||||
assert m.group(0) in desenate, \
|
||||
f"{name}: eticheta numește {m.group(0)}, care nu e un nivel desenat"
|
||||
if clear:
|
||||
_desprinse(svg, name, set(clear))
|
||||
eticheta_libera(svg, name, set(clear), rects=rects)
|
||||
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:
|
||||
@@ -126,6 +104,9 @@ def deco(ch, name, segs=(), texts=(), distante=(), clear=()):
|
||||
|
||||
CAP = ("Exemplu construit (fără ticker), la scară: lecția nu rostește nicio "
|
||||
"cifră. Regula de măsurare e a cursului.")
|
||||
# la bull flag eticheta SMA-20 ar cadea exact pe linia TP1: o mut in caption
|
||||
CAP_SMA = ("Exemplu construit (fără ticker), la scară. Portocaliu punctat: SMA-20."
|
||||
" Regula de măsurare e a cursului.")
|
||||
|
||||
# ============================================================ 1. wedge descendent
|
||||
U0, L0 = 52.00, 48.00 # laturile la deschiderea triunghiului
|
||||
@@ -190,12 +171,12 @@ deco(Chart(
|
||||
Mark(13, "picior 1", "#c00", "below", dy=16),
|
||||
Mark(19, "picior 2 (mai jos)", "#c00", "below"),
|
||||
Mark(25, "hammer in capul triunghiului", "#b06000", "below", dy=8),
|
||||
Mark(27, "breakout cu volum", "#188a3e")],
|
||||
Mark(27, "breakout cu volum", "#188a3e", "above", dy=-24)],
|
||||
zones=[Zone(10, 26, "wedge descendent = consolidare contra-trend (17 bare)",
|
||||
"#8b5cf6")],
|
||||
arrows=[Arrow(29, "stopul sta sub low-ul candelei de breakout:\n"
|
||||
"daca pretul se intoarce in triunghi, ideea a murit",
|
||||
price=SL_D, where="below", color="#c00", dy=30, dx=44)],
|
||||
price=SL_D, where="below", color="#c00", dy=30, dx=56)],
|
||||
mas=[MA(20, "#b06000", dash="4 3", text="SMA-20")],
|
||||
scale=24, gap=16, body_w=9, left=46, width=730, top=62, vol_h=70,
|
||||
title="Wedge descendent — bull",
|
||||
@@ -206,11 +187,13 @@ deco(Chart(
|
||||
seg(13, lo_d(13), 27, lo_d(27)),
|
||||
seg(10.0, L0, 10.0, U0, "#8b5cf6", "", 2.2),
|
||||
seg(35.6, E_D, 35.6, TP_D, "#1a5fb4", "", 2.2)],
|
||||
texts=[txt(10.1, (U0 + L0) / 2, f"baza = {BAZA_D:.2f}", anchor="start", dx=4),
|
||||
texts=[txt(10.1, (U0 + L0) / 2, f"baza = {BAZA_D:.2f}", anchor="start",
|
||||
dx=4, dy=16),
|
||||
txt(35.8, (E_D + TP_D) / 2, f"aceeasi {BAZA_D:.2f}", "#1a5fb4",
|
||||
anchor="start", dx=4)],
|
||||
distante=(BAZA_D,),
|
||||
clear=("picior 1", "breakout cu volum", "hammer in capul triunghiului"))
|
||||
clear=("picior 1", "breakout cu volum", "hammer in capul triunghiului",
|
||||
f"baza = {BAZA_D:.2f}", f"aceeasi {BAZA_D:.2f}"))
|
||||
|
||||
# ================================================ 2. wedge vs flag (forma)
|
||||
cl = (ramp(29.6, 34.00, 6) # 0-5 urcare
|
||||
@@ -449,10 +432,10 @@ deco(Chart(
|
||||
Mark(20, "C = aici era by the dip", "#b06000", "below"),
|
||||
Mark(23, "breakout cu volum", "#188a3e", dy=-36)],
|
||||
zones=[Zone(11, 22, "flamura (12 bare)", "#999")],
|
||||
mas=[MA(20, "#b06000", dash="4 3", text="SMA-20")],
|
||||
mas=[MA(20, "#b06000", dash="4 3")],
|
||||
scale=13, gap=16, body_w=9, left=46, width=730, top=62, vol_h=70,
|
||||
title="Bull flag = ABCD long",
|
||||
caption=CAP),
|
||||
caption=CAP_SMA),
|
||||
"bull_flag",
|
||||
segs=[seg(11, 40.00, 24, up_f(24), "#1a5fb4"),
|
||||
seg(11, 37.00, 14, lo_f(14), "#1a5fb4", "4 3", 1.2),
|
||||
|
||||
Reference in New Issue
Block a user