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:
@@ -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>",
|
||||
|
||||
Reference in New Issue
Block a user