Mostra de format ceruta de user pe 19.09.2026 — de aprobat inainte sa aplicam formatul la celelalte 8 capitole. Specificatia e in STYLE.md, sectiunea FORMAT TUTORIAL. Structura: pasii 1-9 in ordinea in care faci lucrurile la ecran, fiecare terminat cu "Treci mai departe doar daca...". Cele trei perechi de TF (weekly-daily, monthly-weekly, daily-60min) una langa alta in pasul 2; perechea monthly-weekly e acoperita doar partial de material si scrie asta. Nivelurile 0/1/2 desfiintate ca structura. Niciun tabel de 2 coloane. Sursele mutate la final. 14 diagrame, de la 5: cele 5 vechi raman neatinse, 9 noi. Un agent per diagrama, fiecare cu audit + PNG privit. Toate 9 ies curate. 10 reguli din material care lipseau din versiunea veche, fiecare cu citat si fisier:linie — printre ele stopul se numara pe TF-ul deciziei (20_2025-08-25:9-15) si nu muti ordinul dupa pret (03_locul_crimei:296-311). Contradictie noua, a 7-a: pe weekly regula de pivoti spune Quarterly, dar MICI citeste pivotul monthly. Completarile proprii stau in blocuri "Completare proprie:", conform deciziei userului de azi. Cunoscut, nereparat: audit_diagrams da 9 fals-pozitive pe buy_doji_aplus si buy_doji_fereastra, care folosesc <g transform> (auditul nu-l intelege). A zecea, in buy_doji_sell (titlu peste eticheta "doji 99.20 / 100.10"), e reala si preexistenta. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ThN7ixZrowca8aTGrK1MUJ
133 lines
6.7 KiB
Python
133 lines
6.7 KiB
Python
"""Buy Doji — intrarea în trei tranșe (exemplu construit, doji 53.00 / 51.60).
|
|
|
|
Citește specificația `gen/strategii/buy_doji_transe.spec.txt`. Barele 0-14
|
|
sunt aceleași ca în buy_doji_stop.py. Nivelurile de 1/3 și 1/2 se calculează
|
|
din corpul candelei de confirmare, nu se scriu de mână.
|
|
"""
|
|
import re
|
|
import sys; sys.path.insert(0, "/workspace/atm-curs-dl")
|
|
from svg_candles import Candle, Chart, Level, Mark
|
|
|
|
OUT = "/workspace/atm-curs-dl/gen/strategii/buy_doji_transe.svg"
|
|
|
|
# --- seria: barele 0-14 identice cu buy_doji_stop.py --------------------------
|
|
closes = [60.40, 59.60, 59.90, 58.80, 58.10, 58.40, 57.20, 56.30, 56.60,
|
|
55.30, 54.20, 52.40]
|
|
bars, o = [], 61.00
|
|
for c in closes: # fitile implicite 0.15 peste/sub corp
|
|
bars.append((o, max(o, c) + 0.15, min(o, c) - 0.15, c))
|
|
o = c
|
|
bars += [(52.40, 53.00, 51.60, 52.30), # 12 doji
|
|
(52.30, 52.85, 52.10, 52.60), # 13 +1
|
|
(52.60, 53.85, 52.45, 53.70), # 14 confirmare
|
|
(53.70, 53.80, 53.10, 53.45), # 15 umple 1/3 și 1/2
|
|
(53.45, 54.20, 53.35, 54.10),
|
|
(54.10, 54.85, 54.00, 54.70),
|
|
(54.70, 56.00, 54.60, 55.90)] # 18 TP1
|
|
o_, h_, l_, c_ = (list(x) for x in zip(*bars))
|
|
|
|
# --- nivelurile, calculate din corpul barei 14 ---------------------------------
|
|
op, T1 = o_[14], c_[14]
|
|
corp = T1 - op
|
|
T2, T3 = round(T1 - corp / 3, 2), round(T1 - corp / 2, 2)
|
|
MED = round((T1 + T2 + T3) / 3, 2)
|
|
SL = round(min(l_[11:15]) - 0.05, 2)
|
|
TP1 = round(T1 + (T1 - SL), 2)
|
|
|
|
# --- assert-urile din spec -----------------------------------------------------
|
|
for i in range(1, len(bars)): # 1
|
|
assert abs(o_[i] - c_[i - 1]) < 1e-9, f"open[{i}] != close[{i-1}]"
|
|
for i in range(len(bars)):
|
|
assert l_[i] <= min(o_[i], c_[i]) and h_[i] >= max(o_[i], c_[i]), f"bara {i}"
|
|
assert abs(o_[12] - c_[12]) <= 0.10 * (h_[12] - l_[12]) + 1e-9 # 2
|
|
assert c_[13] <= h_[12] < c_[14] and h_[12] == 53.00
|
|
assert min(l_[11:15]) == l_[12] == 51.60 and SL == 51.55 # 3
|
|
assert (op, T1) == (52.60, 53.70) and (T2, T3) == (53.33, 53.15) # 4
|
|
assert l_[15] <= T3 < T2 # 5
|
|
assert MED == 53.39 and round(MED - SL, 2) == 1.84 # 6
|
|
assert round(T1 - SL, 2) == 2.15
|
|
assert TP1 == 55.85 # 7
|
|
assert next(i for i in range(15, len(bars)) if h_[i] >= TP1) == 18
|
|
hi, lo = h_[14], l_[14] # 8
|
|
assert round(hi - (hi - lo) / 3, 2) == 53.38 and round((hi + lo) / 2, 2) == T3
|
|
|
|
GREY, RED, ORANGE, GREEN, BLUE = "#555", "#c00", "#b06000", "#188a3e", "#1a5fb4"
|
|
W = 780
|
|
ch = Chart(
|
|
candles=[Candle(*b) for b in bars],
|
|
levels=[Level(TP1, f"TP1 {TP1:.2f} = 1R de la close", GREEN, "2 2"),
|
|
Level(SL, f"SL {SL:.2f} (low 4 candele 51.60, minus 5 cenți)", RED, "4 3")],
|
|
marks=[Mark(14, f"confirmare {T1:.2f}", GREEN, "above", dy=-38)],
|
|
title="Intrarea în trei tranșe — daily, exemplu construit (doji 53.00 / 51.60)",
|
|
scale=58.0, gap=18, body_w=10, left=44, width=W,
|
|
)
|
|
svg = ch.render()
|
|
y, x = ch._y, ch._cx
|
|
ex = []
|
|
|
|
# linia de ghidaj de la confirmare la eticheta ei (eticheta stă sus, peste bara 17)
|
|
ex.append(f'<line x1="{x(14):.1f}" y1="{y(h_[14]) - 3:.1f}" x2="{x(14):.1f}" '
|
|
f'y2="{y(h_[14]) - 44:.1f}" stroke="{GREEN}" stroke-width="1"/>')
|
|
|
|
# cele trei tranșe: linii de la bara 13 până la paranteza corpului
|
|
XB = 404 # paranteza corpului barei 14
|
|
for p, col, dash in ((T1, GREEN, ""), (T2, ORANGE, "3 3"), (T3, ORANGE, "3 3")):
|
|
d = f' stroke-dasharray="{dash}"' if dash else ""
|
|
ex.append(f'<line x1="{x(13) - 6:.1f}" y1="{y(p):.1f}" x2="{XB}" y2="{y(p):.1f}" '
|
|
f'stroke="{col}" stroke-width="1.5"{d}/>')
|
|
# paranteza: open 52.60 → close 53.70, cu diviziuni la 1/3 și 1/2
|
|
ex.append(f'<line x1="{XB}" y1="{y(T1):.1f}" x2="{XB}" y2="{y(op):.1f}" '
|
|
f'stroke="{GREY}" stroke-width="1.5"/>')
|
|
ex.append(f'<line x1="{XB - 6}" y1="{y(op):.1f}" x2="{XB}" y2="{y(op):.1f}" '
|
|
f'stroke="{GREY}" stroke-width="1.5"/>')
|
|
ex.append(f'<rect x="{XB - 3}" y="{y(MED) - 3:.1f}" width="6" height="6" fill="#888" '
|
|
f'transform="rotate(45 {XB} {y(MED):.1f})"/>')
|
|
|
|
# etichetele, răsfirate la dreapta, cu linii de ghidaj
|
|
yc, XL = y((T1 + T3) / 2), 440
|
|
labels = [(T1, f"1/3 la close {T1:.2f}", GREEN, ""),
|
|
(MED, f"medie {MED:.2f} → risc {MED - SL:.2f} pe acțiune (tot la close: {T1 - SL:.2f})", "#777", "2 2"),
|
|
(T2, f"1/3 la 1/3 din corp {T2:.2f}", ORANGE, "3 3"),
|
|
(T3, f"1/3 la 1/2 din corp {T3:.2f}", ORANGE, "3 3"),
|
|
(op, f"corp: open {op:.2f} → close {T1:.2f} = {corp:.2f}", GREY, "")]
|
|
for k, (p, txt, col, dash) in enumerate(labels):
|
|
ly = yc + (k - 1.5) * 22
|
|
d = f' stroke-dasharray="{dash}"' if dash else ""
|
|
ex.append(f'<polyline points="{XB},{y(p):.1f} {XL - 6},{ly - 4:.1f}" fill="none" '
|
|
f'stroke="{col}" stroke-width="1.2"{d}/>')
|
|
ex.append(f'<text x="{XL}" y="{ly:.1f}" fill="{col}" style="font-weight:bold">{txt}</text>')
|
|
|
|
# umpleri: T1 la close-ul barei 14, T2 și T3 pe low-ul barei 15; TP1 pe bara 18
|
|
for i, p, col in ((14, T1, GREEN), (15, T2, ORANGE), (15, T3, ORANGE), (18, TP1, GREEN)):
|
|
ex.append(f'<circle cx="{x(i):.1f}" cy="{y(p):.1f}" r="3.5" fill="#fff" '
|
|
f'stroke="{col}" stroke-width="2"/>')
|
|
|
|
# etichetele de sub candele, pe rânduri (Mark "below" le-ar pune pe același rând)
|
|
yb = y(SL) + 20
|
|
rows = [(15, f"low {l_[15]:.2f}: umple T2 și T3", ORANGE),
|
|
(13, f"+1: {c_[13]:.2f}, sub high", GREY),
|
|
(12, f"doji {h_[12]:.2f} / {l_[12]:.2f}", BLUE)]
|
|
for r, (i, txt, col) in enumerate(rows):
|
|
ry = yb + 16 * r
|
|
ex.append(f'<line x1="{x(i):.1f}" y1="{y(l_[i]) + 3:.1f}" x2="{x(i):.1f}" '
|
|
f'y2="{ry - 11:.1f}" stroke="{col}" stroke-width="1" stroke-dasharray="1 2"/>')
|
|
ex.append(f'<text x="{x(i) - 4:.1f}" y="{ry:.1f}" fill="{col}" '
|
|
f'style="font-weight:bold">{txt}</text>')
|
|
|
|
# legenda, pe două rânduri
|
|
ly = yb + 16 * len(rows) + 14
|
|
ex.append(f'<text x="24" y="{ly:.0f}" fill="#555">Măsurat pe corp (open {op:.2f} → close {T1:.2f}). '
|
|
f'Măsurat pe toată candela ({lo:.2f} → {hi:.2f}), 1/3 ar fi '
|
|
f'{hi - (hi - lo) / 3:.2f}; 1/2 iese tot {(hi + lo) / 2:.2f}.</text>')
|
|
ex.append(f'<text x="24" y="{ly + 17:.0f}" fill="#555">Stopul e unul singur, pentru toată '
|
|
f'poziția. Barele 0-11 și 15-18 sunt construite.</text>')
|
|
H = ly + 17 + 12
|
|
|
|
body = svg.rsplit("</svg>", 1)[0].rstrip()
|
|
svg = "\n ".join([body, *ex]) + "\n</svg>"
|
|
svg = re.sub(r'viewBox="0 0 (\d+) [\d.]+"', rf'viewBox="0 0 \1 {H:.0f}"', svg, count=1)
|
|
assert "<svg" in svg and "\n\n" not in svg, "linie goală în SVG"
|
|
with open(OUT, "w") as f:
|
|
f.write(svg)
|
|
print(f"scris {OUT} ({W}x{H:.0f})")
|