atmi: diagramele refacute, cinci noi, si fisa de surse

Noi: pivoti (PPQ/SQ calculati din trimestrul precedent, cu formula pe
desen), perechi_tf (weekly -> daily ca descompunere reala, cu caseta,
ghidaje si PPQ pe ambele panouri), trigger (BIM apoi verde, fata de
verde inainte de BIM — cutitul in cadere), risc (ce inseamna "fara
stop": 24 de bare sub apa, -20 % pe pozitie), reinvestire (ciclul
banilor pe trei cicluri).

aplus devine corectie: diagrama arata un prag de corectie, nu un setup
A+, si numele vechi trimitea la altceva.

Trei bug-uri reale: exemplul era etichetat weekly cu 20 de bare, dar
textul spunea "un an mai tarziu" — trecut pe monthly cu assert pe numarul
de luni; ansamblul avea o trimitere fisier:linie desenata in SVG; si
benzile PPQ/SQ erau inversate ca sens, cu SQ fix pe intrare.

PPQ 95.80 si SQ 90.80 sunt completare proprie — cursul spune explicit ca
nu da valorile; derivate cu formula standard, cu assert.

Textul capitolului e neatins — agentul a atins pragul de context.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ThN7ixZrowca8aTGrK1MUJ
This commit is contained in:
Claude Agent
2026-09-20 12:46:38 +00:00
parent 0ed607134d
commit c08c857274
25 changed files with 2133 additions and 623 deletions

View File

@@ -1,6 +1,6 @@
"""Diagrama de ansamblu ATMI (strategii/05_atmi.md, marcajul `ansamblu`).
„SPY — daily: corecție ≥4 % → SQ/PPQ → BIM + verde → intrare → TP +10 %".
„SPY — daily: corecție ≥4 % → zona PPQ → BIM + verde → intrare → TP +10 %".
Structura seriei și nivelurile vin din spec-ul
`gen/strategii/atmi_ansamblu.spec.txt`. Toate cifrele desenate (100.00 swing
@@ -27,29 +27,32 @@ PURPLE = "#7b2fbf" # folosit în materialul de curs pentru PPQ
# ---------------------------------------------------------------- seria (33 bare)
# 15 bare de urcare ~88 -> 100, 8 de corecție 100 -> 96 (ultima = intrarea),
# 10 de urcare 96 -> 105.60. open-ul fiecărei bare = close-ul precedentei.
UP_A = [88.2, 88.8, 89.5, 90.1, 90.8, 91.6, 92.5, 93.3, 94.2, 95.1,
96.0, 96.9, 97.8, 98.9, 100.00] # 0-14
CORR = [99.3, 98.5, 97.8, 97.2, 96.7, 96.3, 96.00, 96.00] # 15-22
UP_B = [96.6, 97.2, 97.9, 98.6, 99.4, 100.3, 101.4, 102.6, 104.0, 105.60] # 23-32
UP_A = [96.60, 97.10, 97.60, 98.00, 98.50, 98.20, 98.70, 99.20,
99.60, 99.30, 99.70, 100.00] # 0-11
CORR = [99.30, 98.50, 97.80, 97.20, 96.70, 96.30, 95.90, 96.00] # 12-19 (18 = BIM)
UP_B = [96.60, 97.20, 97.90, 98.60, 99.40, 100.30, 101.40, 102.60,
103.40, 104.20, 104.90, 105.60] # 20-31
CLOSES = UP_A + CORR + UP_B
assert len(CLOSES) == 33, len(CLOSES)
PEAK, BIM, ENTRY, LAST = 14, 21, 22, 32
assert len(CLOSES) == 32, len(CLOSES)
PEAK, BIM, ENTRY, LAST = 11, 18, 19, 31
# fitile (sus, jos) per bară; jos pe corecție ținut ≥ 0 ca minimul să fie fix 96.00
WICKS = ([(0.30, 0.30)] * 14
+ [(0.00, 0.30)] # 14: vârful atinge exact 100.00
+ [(0.00, 0.00), (0.05, 0.10), (0.05, 0.10), (0.05, 0.15),
(0.05, 0.15), (0.05, 0.20), (0.05, 0.00), (0.12, 0.00)] # 15-22
+ [(0.25, 0.25)] * 9
+ [(0.00, 0.20)]) # 32: închide/atinge exact 105.60
assert len(WICKS) == len(CLOSES)
WICKS = ([(0.25, 0.25)] * 11
+ [(0.00, 0.25)] # 11: vârful atinge exact 100.00
+ [(0.00, 0.20), (0.05, 0.20), (0.05, 0.20), (0.05, 0.20),
(0.05, 0.20), (0.05, 0.20),
(0.05, 0.35), # 18: bara de BIM, fundul la 95.55
(0.15, 0.05)] # 19: candela verde de intrare
+ [(0.25, 0.00)] + [(0.25, 0.25)] * 10
+ [(0.00, 0.20)]) # 31: închide/atinge exact 105.60
assert len(WICKS) == len(CLOSES), (len(WICKS), len(CLOSES))
VOLS = ([44, 47, 42, 50, 45, 41, 48, 43, 46, 51, 44, 49, 46, 52, 58] # 0-14 urcare
+ [64, 70, 66, 61, 58, 74, 96, 88] # 15-22 corecție + BIM/intrare
+ [55, 58, 52, 60, 57, 63, 59, 66, 72, 84]) # 23-32 urcare spre TP
assert len(VOLS) == len(CLOSES)
VOLS = ([44, 47, 42, 50, 45, 41, 48, 43, 46, 51, 44, 58] # 0-11 urcare
+ [64, 70, 66, 61, 58, 74, 96, 88] # 12-19 corecție + BIM/intrare
+ [55, 58, 52, 60, 57, 63, 59, 66, 70, 74, 78, 84]) # 20-31 urcare spre TP
assert len(VOLS) == len(CLOSES), (len(VOLS), len(CLOSES))
cds = from_closes(CLOSES, wicks=WICKS, vols=VOLS, start=88.0)
cds = from_closes(CLOSES, wicks=WICKS, vols=VOLS, start=96.20)
# ---------------------------------------------------------------- assert-urile din spec
high = 100.00
@@ -58,9 +61,9 @@ tp = cds[LAST].h
assert abs((high - 96.00) / high * 100 - 4.0) < 0.05 # corecția e 4.0 %
assert abs(entry - 96.00) < 0.05 # intrarea = close-ul candelei verzi
assert abs(tp / entry - 1.10) < 0.005 # TP = +10 %
assert abs(tp - max(c.h for c in cds[-10:])) < 1e-9 # TP atins la final, e maximul barelor
assert abs(tp - max(c.h for c in cds[-12:])) < 1e-9 # TP atins la final, e maximul barelor
assert BIM < ENTRY # BIM înainte de candela verde
assert abs(min(c.l for c in cds[15:23]) - 96.00) < 1e-9 # minimul corecției = 96.00
assert abs(min(c.l for c in cds[12:20]) - 95.55) < 1e-9 # fundul corecției = 95.55
assert cds[ENTRY].c >= cds[ENTRY].o # candela de intrare e verde
assert abs(cds[PEAK].h - high) < 1e-9 # swing high = 100.00
assert abs(cds[LAST].c - tp) < 1e-9 # ultima bară închide pe TP
@@ -75,16 +78,17 @@ assert all("stop" not in lv.text.lower() for lv in levels)
assert all(lv.price >= entry - 1e-9 for lv in levels)
marks = [
Mark(15, "corecție 4.0 %", ORANGE, "above"),
Mark(BIM, "BIM", ORANGE, "above"),
Mark(ENTRY, "BIM + candelă verde → intrare", GREEN, "below", dy=20),
Mark(13, "corecție 4,0 %", ORANGE, "below", dy=26),
Mark(BIM, "BIM", "#0a7f9e", "above"),
Mark(ENTRY, "prima candelă verde → intrare", GREEN, "below", dy=30),
Mark(LAST, "ieși cu tot", BLUE, "below", dy=22),
]
ch = Chart(candles=cds, levels=levels, marks=marks,
mas=[MA(20, ORANGE, dash="4 3", text="SMA-20 (ilustrativ)")],
scale=18.0, gap=16, body_w=9, left=44, width=720, vol_h=70, top=70,
scale=22.0, gap=17, body_w=9, left=44, width=720, vol_h=70, vol_gap=72, top=88,
vol_label="volum",
caption="Niveluri (100.00 / 96.00 / 105.60) din curs; PPQ/SQ schematice, fără cifre în material.")
caption="100.00 / 96.00 / 105.60 sunt cifrele exemplului din curs; PPQ 95.80 e calculat "
"în diagrama pasului 1 (cursul nu dă valorile pivoților).")
svg = ch.render()
@@ -98,26 +102,30 @@ def band(price: float, half: float, color: str, label: str) -> str:
y_top, y_bot = ch._y(price + half), ch._y(price - half)
return (f'<rect x="24" y="{y_top:.1f}" width="{ch.width - 38}" '
f'height="{y_bot - y_top:.1f}" fill="{color}" opacity="0.10"/>'
f'<text x="28" y="{y_top - 4:.1f}" fill="{color}">{label}</text>')
f'<text x="28" y="{y_bot + 14:.1f}" fill="{color}">{label}</text>')
# SQ e zona joasă (intrarea exact pe ea), PPQ zona mai sus, retragere mai mică
assert (entry + 1.60 - 0.35) > (entry + 0.35), "benzile SQ și PPQ nu se suprapun"
sq = band(entry, 0.35, GREEN, "SQ — zonă quarterly")
ppq = band(entry + 1.60, 0.35, PURPLE, "PPQ — zonă quarterly")
# PPQ 95.80 e pivotul trimestrial calculat în diagrama pasului 1; banda e
# zona de cumpărare din jurul lui. SQ 90.80 e sub scara acestui desen, deci
# nu se desenează aici — apare pe diagrama pasului 1.
PPQ = 95.80
assert abs(min(c.l for c in cds) - 95.55) < 1e-9
assert PPQ - 0.30 <= min(c.l for c in cds) <= PPQ + 0.30, "fundul nu cade în banda PPQ"
assert entry > PPQ, "candela verde trebuie să închidă peste pivot"
ppq = band(PPQ, 0.30, PURPLE, f"zona PPQ {PPQ:.2f} — aici cumperi")
sq = ""
# „fără stop-loss standard" stă sub zona de intrare, unde nu are candele
no_sl = (f'<text x="{ch._cx(ENTRY):.0f}" y="{ch._y(entry) + 63:.1f}" fill="{RED}" '
f'text-anchor="middle">fără stop-loss standard</text>'
f'<text x="{ch._cx(ENTRY):.0f}" y="{ch._y(entry) + 76:.1f}" fill="{GRAY}" '
f'text-anchor="middle">(03_strategia_2_atmi.md:164-169)</text>')
no_sl = (f'<text x="{ch._cx(ENTRY):.0f}" y="{ch._y(entry) + 46:.1f}" fill="{RED}" '
f'text-anchor="middle">fără stop-loss standard — nicio linie sub intrare</text>')
# titlul e injectat deasupra, ca rând separat de eticheta TP (care stă chiar
# sub marginea de sus a panoului); altfel cele două texte se calcă la dreapta
titlu = ('<text x="24" y="26" fill="#333" style="font-weight:bold">'
'SPY — daily: corecție ≥4 % → SQ/PPQ → BIM + verde → intrare → TP +10 %</text>')
'SPY — daily: corecție ≥4 % → zona PPQ → BIM + verde → intrare → TP +10 %</text>')
i = svg.index(">") + 1
svg = svg[:i] + "\n " + "\n ".join([sq, ppq, no_sl, titlu]) + svg[i:]
svg = svg[:i] + "\n " + "\n ".join([ppq, no_sl, titlu]) + svg[i:]
assert svg.count("\n\n") == 0, "linie goală în SVG rupe blocul din markdown"
assert ".md:" not in svg, "trimitere fișier:linie în SVG"
OUT.write_text(svg)
print(f"scris {OUT.name}: {len(cds)} candele, intrare {entry:.2f}, TP {tp:.2f}")

View File

@@ -1,119 +1,114 @@
<svg viewBox="0 0 720 530" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif">
<rect x="24" y="236.5" width="682" height="12.6" fill="#188a3e" opacity="0.10"/><text x="28" y="232.5" fill="#188a3e">SQ — zonă quarterly</text>
<rect x="24" y="207.7" width="682" height="12.6" fill="#7b2fbf" opacity="0.10"/><text x="28" y="203.7" fill="#7b2fbf">PPQ — zonă quarterly</text>
<text x="396" y="305.8" fill="#c00" text-anchor="middle">fără stop-loss standard</text><text x="396" y="318.8" fill="#777" text-anchor="middle">(03_strategia_2_atmi.md:164-169)</text>
<text x="24" y="26" fill="#333" style="font-weight:bold">SPY — daily: corecție ≥4 % → SQ/PPQ → BIM + verde → intrare → TP +10 %</text>
<line x1="24" y1="170.8" x2="706" y2="170.8" stroke="#333" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30" y="164.8" fill="#333">100.00 — swing high recent</text>
<line x1="24" y1="242.8" x2="706" y2="242.8" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="692" y="236.8" fill="#188a3e" text-anchor="end">intrare 96.00</text>
<line x1="24" y1="70.0" x2="706" y2="70.0" stroke="#1a5fb4" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="692" y="64.0" fill="#1a5fb4" text-anchor="end">TP +10 % = 105.60</text>
<polyline points="348.0,266.9 364.0,259.6 380.0,253.1 396.0,247.3 412.0,241.4 428.0,235.7 444.0,230.0 460.0,224.5 476.0,219.0 492.0,213.5 508.0,207.9 524.0,201.9 540.0,195.5 556.0,188.5" fill="none" stroke="#b06000" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="562" y="182" fill="#b06000">SMA-20 (ilustrativ)</text>
<line x1="44.0" y1="377.8" x2="44.0" y2="392.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="39.5" y="383.2" width="9" height="3.6" fill="#188a3e"/>
<line x1="60.0" y1="367.0" x2="60.0" y2="388.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="55.5" y="372.4" width="9" height="10.8" fill="#188a3e"/>
<line x1="76.0" y1="354.4" x2="76.0" y2="377.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="71.5" y="359.8" width="9" height="12.6" fill="#188a3e"/>
<line x1="92.0" y1="343.6" x2="92.0" y2="365.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="87.5" y="349.0" width="9" height="10.8" fill="#188a3e"/>
<line x1="108.0" y1="331.0" x2="108.0" y2="354.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="103.5" y="336.4" width="9" height="12.6" fill="#188a3e"/>
<line x1="124.0" y1="316.6" x2="124.0" y2="341.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="119.5" y="322.0" width="9" height="14.4" fill="#188a3e"/>
<line x1="140.0" y1="300.4" x2="140.0" y2="327.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="135.5" y="305.8" width="9" height="16.2" fill="#188a3e"/>
<line x1="156.0" y1="286.0" x2="156.0" y2="311.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="151.5" y="291.4" width="9" height="14.4" fill="#188a3e"/>
<line x1="172.0" y1="269.8" x2="172.0" y2="296.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="167.5" y="275.2" width="9" height="16.2" fill="#188a3e"/>
<line x1="188.0" y1="253.6" x2="188.0" y2="280.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="183.5" y="259.0" width="9" height="16.2" fill="#188a3e"/>
<line x1="204.0" y1="237.4" x2="204.0" y2="264.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="199.5" y="242.8" width="9" height="16.2" fill="#188a3e"/>
<line x1="220.0" y1="221.2" x2="220.0" y2="248.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="215.5" y="226.6" width="9" height="16.2" fill="#188a3e"/>
<line x1="236.0" y1="205.0" x2="236.0" y2="232.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="231.5" y="210.4" width="9" height="16.2" fill="#188a3e"/>
<line x1="252.0" y1="185.2" x2="252.0" y2="215.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="247.5" y="190.6" width="9" height="19.8" fill="#188a3e"/>
<line x1="268.0" y1="170.8" x2="268.0" y2="196.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="263.5" y="170.8" width="9" height="19.8" fill="#188a3e"/>
<line x1="284.0" y1="170.8" x2="284.0" y2="183.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="279.5" y="170.8" width="9" height="12.6" fill="#c00"/>
<line x1="300.0" y1="182.5" x2="300.0" y2="199.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="295.5" y="183.4" width="9" height="14.4" fill="#c00"/>
<line x1="316.0" y1="196.9" x2="316.0" y2="212.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="311.5" y="197.8" width="9" height="12.6" fill="#c00"/>
<line x1="332.0" y1="209.5" x2="332.0" y2="223.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="327.5" y="210.4" width="9" height="10.8" fill="#c00"/>
<line x1="348.0" y1="220.3" x2="348.0" y2="232.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="343.5" y="221.2" width="9" height="9.0" fill="#c00"/>
<line x1="364.0" y1="229.3" x2="364.0" y2="241.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="359.5" y="230.2" width="9" height="7.2" fill="#c00"/>
<line x1="380.0" y1="236.5" x2="380.0" y2="242.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="375.5" y="237.4" width="9" height="5.4" fill="#c00"/>
<line x1="396.0" y1="240.6" x2="396.0" y2="242.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="391.5" y="242.8" width="9" height="1.6" fill="#188a3e"/>
<line x1="412.0" y1="227.5" x2="412.0" y2="247.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="407.5" y="232.0" width="9" height="10.8" fill="#188a3e"/>
<line x1="428.0" y1="216.7" x2="428.0" y2="236.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="423.5" y="221.2" width="9" height="10.8" fill="#188a3e"/>
<line x1="444.0" y1="204.1" x2="444.0" y2="225.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="439.5" y="208.6" width="9" height="12.6" fill="#188a3e"/>
<line x1="460.0" y1="191.5" x2="460.0" y2="213.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="455.5" y="196.0" width="9" height="12.6" fill="#188a3e"/>
<line x1="476.0" y1="177.1" x2="476.0" y2="200.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="471.5" y="181.6" width="9" height="14.4" fill="#188a3e"/>
<line x1="492.0" y1="160.9" x2="492.0" y2="186.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="487.5" y="165.4" width="9" height="16.2" fill="#188a3e"/>
<line x1="508.0" y1="141.1" x2="508.0" y2="169.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="503.5" y="145.6" width="9" height="19.8" fill="#188a3e"/>
<line x1="524.0" y1="119.5" x2="524.0" y2="150.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="519.5" y="124.0" width="9" height="21.6" fill="#188a3e"/>
<line x1="540.0" y1="94.3" x2="540.0" y2="128.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="535.5" y="98.8" width="9" height="25.2" fill="#188a3e"/>
<line x1="556.0" y1="70.0" x2="556.0" y2="102.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="551.5" y="70.0" width="9" height="28.8" fill="#188a3e"/>
<line x1="24" y1="488.2" x2="706" y2="488.2" stroke="#888"/>
<rect x="39.5" y="456.1" width="9" height="32.1" fill="#188a3e" opacity="0.55"/>
<rect x="55.5" y="453.9" width="9" height="34.3" fill="#188a3e" opacity="0.55"/>
<rect x="71.5" y="457.6" width="9" height="30.6" fill="#188a3e" opacity="0.55"/>
<rect x="87.5" y="451.7" width="9" height="36.5" fill="#188a3e" opacity="0.55"/>
<rect x="103.5" y="455.4" width="9" height="32.8" fill="#188a3e" opacity="0.55"/>
<rect x="119.5" y="458.3" width="9" height="29.9" fill="#188a3e" opacity="0.55"/>
<rect x="135.5" y="453.2" width="9" height="35.0" fill="#188a3e" opacity="0.55"/>
<rect x="151.5" y="456.8" width="9" height="31.4" fill="#188a3e" opacity="0.55"/>
<rect x="167.5" y="454.7" width="9" height="33.5" fill="#188a3e" opacity="0.55"/>
<rect x="183.5" y="451.0" width="9" height="37.2" fill="#188a3e" opacity="0.55"/>
<rect x="199.5" y="456.1" width="9" height="32.1" fill="#188a3e" opacity="0.55"/>
<rect x="215.5" y="452.5" width="9" height="35.7" fill="#188a3e" opacity="0.55"/>
<rect x="231.5" y="454.7" width="9" height="33.5" fill="#188a3e" opacity="0.55"/>
<rect x="247.5" y="450.3" width="9" height="37.9" fill="#188a3e" opacity="0.55"/>
<rect x="263.5" y="445.9" width="9" height="42.3" fill="#188a3e" opacity="0.55"/>
<rect x="279.5" y="441.5" width="9" height="46.7" fill="#c00" opacity="0.55"/>
<rect x="295.5" y="437.2" width="9" height="51.0" fill="#c00" opacity="0.55"/>
<rect x="311.5" y="440.1" width="9" height="48.1" fill="#c00" opacity="0.55"/>
<rect x="327.5" y="443.7" width="9" height="44.5" fill="#c00" opacity="0.55"/>
<rect x="343.5" y="445.9" width="9" height="42.3" fill="#c00" opacity="0.55"/>
<rect x="359.5" y="434.2" width="9" height="54.0" fill="#c00" opacity="0.55"/>
<rect x="375.5" y="418.2" width="9" height="70.0" fill="#c00" opacity="0.55"/>
<rect x="391.5" y="424.0" width="9" height="64.2" fill="#188a3e" opacity="0.55"/>
<rect x="407.5" y="448.1" width="9" height="40.1" fill="#188a3e" opacity="0.55"/>
<rect x="423.5" y="445.9" width="9" height="42.3" fill="#188a3e" opacity="0.55"/>
<rect x="439.5" y="450.3" width="9" height="37.9" fill="#188a3e" opacity="0.55"/>
<rect x="455.5" y="444.4" width="9" height="43.8" fill="#188a3e" opacity="0.55"/>
<rect x="471.5" y="446.6" width="9" height="41.6" fill="#188a3e" opacity="0.55"/>
<rect x="487.5" y="442.3" width="9" height="45.9" fill="#188a3e" opacity="0.55"/>
<rect x="503.5" y="445.2" width="9" height="43.0" fill="#188a3e" opacity="0.55"/>
<rect x="519.5" y="440.1" width="9" height="48.1" fill="#188a3e" opacity="0.55"/>
<rect x="535.5" y="435.7" width="9" height="52.5" fill="#188a3e" opacity="0.55"/>
<rect x="551.5" y="426.9" width="9" height="61.2" fill="#188a3e" opacity="0.55"/>
<text x="24" y="412.2" fill="#555">volum</text>
<text x="284.0" y="160.8" fill="#b06000" text-anchor="middle" style="font-weight:bold">corecție 4.0 %</text>
<text x="380.0" y="226.5" fill="#b06000" text-anchor="middle" style="font-weight:bold">BIM</text>
<text x="396.0" y="282.8" fill="#188a3e" text-anchor="middle" style="font-weight:bold">BIM + candelă verde → intrare</text>
<text x="24" y="518" fill="#555">Niveluri (100.00 / 96.00 / 105.60) din curs; PPQ/SQ schematice, fără cifre în material.</text>
<svg viewBox="0 0 720 493" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif">
<rect x="24" y="297.0" width="682" height="13.2" fill="#7b2fbf" opacity="0.10"/><text x="28" y="324.2" fill="#7b2fbf">zona PPQ 95.80 — aici cumperi</text>
<text x="367" y="345.2" fill="#c00" text-anchor="middle">fără stop-loss standard — nicio linie sub intrare</text>
<text x="24" y="26" fill="#333" style="font-weight:bold">SPY — daily: corecție ≥4 % → zona PPQ → BIM + verde → intrare → TP +10 %</text>
<line x1="24" y1="211.2" x2="706" y2="211.2" stroke="#333" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30" y="205.2" fill="#333">100.00 — swing high recent</text>
<line x1="24" y1="299.2" x2="706" y2="299.2" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="692" y="293.2" fill="#188a3e" text-anchor="end">intrare 96.00</text>
<line x1="24" y1="88.0" x2="706" y2="88.0" stroke="#1a5fb4" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="692" y="82.0" fill="#1a5fb4" text-anchor="end">TP +10 % = 105.60</text>
<line x1="44.0" y1="280.5" x2="44.0" y2="300.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="39.5" y="286.0" width="9" height="8.8" fill="#188a3e"/>
<line x1="61.0" y1="269.5" x2="61.0" y2="291.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="56.5" y="275.0" width="9" height="11.0" fill="#188a3e"/>
<line x1="78.0" y1="258.5" x2="78.0" y2="280.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="73.5" y="264.0" width="9" height="11.0" fill="#188a3e"/>
<line x1="95.0" y1="249.7" x2="95.0" y2="269.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="90.5" y="255.2" width="9" height="8.8" fill="#188a3e"/>
<line x1="112.0" y1="238.7" x2="112.0" y2="260.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="107.5" y="244.2" width="9" height="11.0" fill="#188a3e"/>
<line x1="129.0" y1="238.7" x2="129.0" y2="256.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="124.5" y="244.2" width="9" height="6.6" fill="#c00"/>
<line x1="146.0" y1="234.3" x2="146.0" y2="256.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="141.5" y="239.8" width="9" height="11.0" fill="#188a3e"/>
<line x1="163.0" y1="223.3" x2="163.0" y2="245.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="158.5" y="228.8" width="9" height="11.0" fill="#188a3e"/>
<line x1="180.0" y1="214.5" x2="180.0" y2="234.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="175.5" y="220.0" width="9" height="8.8" fill="#188a3e"/>
<line x1="197.0" y1="214.5" x2="197.0" y2="232.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="192.5" y="220.0" width="9" height="6.6" fill="#c00"/>
<line x1="214.0" y1="212.3" x2="214.0" y2="232.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="209.5" y="217.8" width="9" height="8.8" fill="#188a3e"/>
<line x1="231.0" y1="211.2" x2="231.0" y2="223.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="226.5" y="211.2" width="9" height="6.6" fill="#188a3e"/>
<line x1="248.0" y1="211.2" x2="248.0" y2="231.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="243.5" y="211.2" width="9" height="15.4" fill="#c00"/>
<line x1="265.0" y1="225.5" x2="265.0" y2="248.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="260.5" y="226.6" width="9" height="17.6" fill="#c00"/>
<line x1="282.0" y1="243.1" x2="282.0" y2="264.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="277.5" y="244.2" width="9" height="15.4" fill="#c00"/>
<line x1="299.0" y1="258.5" x2="299.0" y2="277.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="294.5" y="259.6" width="9" height="13.2" fill="#c00"/>
<line x1="316.0" y1="271.7" x2="316.0" y2="288.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="311.5" y="272.8" width="9" height="11.0" fill="#c00"/>
<line x1="333.0" y1="282.7" x2="333.0" y2="297.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="328.5" y="283.8" width="9" height="8.8" fill="#c00"/>
<line x1="350.0" y1="291.5" x2="350.0" y2="309.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="345.5" y="292.6" width="9" height="8.8" fill="#c00"/>
<line x1="367.0" y1="295.9" x2="367.0" y2="302.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="362.5" y="299.2" width="9" height="2.2" fill="#188a3e"/>
<line x1="384.0" y1="280.5" x2="384.0" y2="299.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="379.5" y="286.0" width="9" height="13.2" fill="#188a3e"/>
<line x1="401.0" y1="267.3" x2="401.0" y2="291.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="396.5" y="272.8" width="9" height="13.2" fill="#188a3e"/>
<line x1="418.0" y1="251.9" x2="418.0" y2="278.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="413.5" y="257.4" width="9" height="15.4" fill="#188a3e"/>
<line x1="435.0" y1="236.5" x2="435.0" y2="262.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="430.5" y="242.0" width="9" height="15.4" fill="#188a3e"/>
<line x1="452.0" y1="218.9" x2="452.0" y2="247.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="447.5" y="224.4" width="9" height="17.6" fill="#188a3e"/>
<line x1="469.0" y1="199.1" x2="469.0" y2="229.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="464.5" y="204.6" width="9" height="19.8" fill="#188a3e"/>
<line x1="486.0" y1="174.9" x2="486.0" y2="210.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="481.5" y="180.4" width="9" height="24.2" fill="#188a3e"/>
<line x1="503.0" y1="148.5" x2="503.0" y2="185.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="498.5" y="154.0" width="9" height="26.4" fill="#188a3e"/>
<line x1="520.0" y1="130.9" x2="520.0" y2="159.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="515.5" y="136.4" width="9" height="17.6" fill="#188a3e"/>
<line x1="537.0" y1="113.3" x2="537.0" y2="141.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="532.5" y="118.8" width="9" height="17.6" fill="#188a3e"/>
<line x1="554.0" y1="97.9" x2="554.0" y2="124.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="549.5" y="103.4" width="9" height="15.4" fill="#188a3e"/>
<line x1="571.0" y1="88.0" x2="571.0" y2="107.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="566.5" y="88.0" width="9" height="15.4" fill="#188a3e"/>
<line x1="24" y1="451.1" x2="706" y2="451.1" stroke="#888"/>
<rect x="39.5" y="419.0" width="9" height="32.1" fill="#188a3e" opacity="0.55"/>
<rect x="56.5" y="416.8" width="9" height="34.3" fill="#188a3e" opacity="0.55"/>
<rect x="73.5" y="420.5" width="9" height="30.6" fill="#188a3e" opacity="0.55"/>
<rect x="90.5" y="414.6" width="9" height="36.5" fill="#188a3e" opacity="0.55"/>
<rect x="107.5" y="418.3" width="9" height="32.8" fill="#188a3e" opacity="0.55"/>
<rect x="124.5" y="421.2" width="9" height="29.9" fill="#c00" opacity="0.55"/>
<rect x="141.5" y="416.1" width="9" height="35.0" fill="#188a3e" opacity="0.55"/>
<rect x="158.5" y="419.7" width="9" height="31.4" fill="#188a3e" opacity="0.55"/>
<rect x="175.5" y="417.6" width="9" height="33.5" fill="#188a3e" opacity="0.55"/>
<rect x="192.5" y="413.9" width="9" height="37.2" fill="#c00" opacity="0.55"/>
<rect x="209.5" y="419.0" width="9" height="32.1" fill="#188a3e" opacity="0.55"/>
<rect x="226.5" y="408.8" width="9" height="42.3" fill="#188a3e" opacity="0.55"/>
<rect x="243.5" y="404.4" width="9" height="46.7" fill="#c00" opacity="0.55"/>
<rect x="260.5" y="400.1" width="9" height="51.0" fill="#c00" opacity="0.55"/>
<rect x="277.5" y="403.0" width="9" height="48.1" fill="#c00" opacity="0.55"/>
<rect x="294.5" y="406.6" width="9" height="44.5" fill="#c00" opacity="0.55"/>
<rect x="311.5" y="408.8" width="9" height="42.3" fill="#c00" opacity="0.55"/>
<rect x="328.5" y="397.1" width="9" height="54.0" fill="#c00" opacity="0.55"/>
<rect x="345.5" y="381.1" width="9" height="70.0" fill="#c00" opacity="0.55"/>
<rect x="362.5" y="386.9" width="9" height="64.2" fill="#188a3e" opacity="0.55"/>
<rect x="379.5" y="411.0" width="9" height="40.1" fill="#188a3e" opacity="0.55"/>
<rect x="396.5" y="408.8" width="9" height="42.3" fill="#188a3e" opacity="0.55"/>
<rect x="413.5" y="413.2" width="9" height="37.9" fill="#188a3e" opacity="0.55"/>
<rect x="430.5" y="407.3" width="9" height="43.8" fill="#188a3e" opacity="0.55"/>
<rect x="447.5" y="409.5" width="9" height="41.6" fill="#188a3e" opacity="0.55"/>
<rect x="464.5" y="405.2" width="9" height="45.9" fill="#188a3e" opacity="0.55"/>
<rect x="481.5" y="408.1" width="9" height="43.0" fill="#188a3e" opacity="0.55"/>
<rect x="498.5" y="403.0" width="9" height="48.1" fill="#188a3e" opacity="0.55"/>
<rect x="515.5" y="400.1" width="9" height="51.0" fill="#188a3e" opacity="0.55"/>
<rect x="532.5" y="397.1" width="9" height="54.0" fill="#188a3e" opacity="0.55"/>
<rect x="549.5" y="394.2" width="9" height="56.9" fill="#188a3e" opacity="0.55"/>
<rect x="566.5" y="389.8" width="9" height="61.2" fill="#188a3e" opacity="0.55"/>
<text x="24" y="375.1" fill="#555">volum</text>
<text x="265.0" y="294.6" fill="#b06000" text-anchor="middle" style="font-weight:bold">corecție 4,0 %</text>
<text x="350.0" y="281.5" fill="#0a7f9e" text-anchor="middle" style="font-weight:bold">BIM</text>
<text x="367.0" y="323.1" fill="#188a3e" text-anchor="middle" style="font-weight:bold">prima candelă verde → intrare</text>
<text x="571.0" y="149.8" fill="#1a5fb4" text-anchor="middle" style="font-weight:bold">ieși cu tot</text>
<text x="24" y="481" fill="#555">100.00 / 96.00 / 105.60 sunt cifrele exemplului din curs; PPQ 95.80 e calculat în diagrama pasului 1 (cursul nu dă valorile pivoților).</text>
</svg>

Before

Width:  |  Height:  |  Size: 9.9 KiB

After

Width:  |  Height:  |  Size: 9.3 KiB

View File

@@ -1,6 +1,6 @@
"""ATMI — aceeași corecție: 4.0 % (DA) vs. 3.9 % (NU; cursul zice „3.93 %").
Citește specificația `gen/strategii/atmi_aplus.spec.txt`.
Citește specificația `gen/strategii/atmi_corectie.spec.txt`.
O singură serie de 32 de candele daily (open-ul fiecărei bare = close-ul
precedentei, deci seria e continuă), care urmează calea DA: urcare la swing
@@ -19,6 +19,7 @@ sys.path.insert(0, "/workspace/atm-curs-dl")
from svg_candles import Chart, Level, Mark, from_closes # noqa: E402
GRAY, RED, GREEN, BLUE, ORANGE, INK = "#777", "#c00", "#188a3e", "#1a5fb4", "#b06000", "#333"
PURPLE = "#7b2fbf"
# --- seria: 32 de close-uri, structura din specificație ----------------------
# 0-11 urcare 90.00 -> 100.00 (swing high la bara 11)
@@ -38,7 +39,7 @@ assert len(closes) == 32
# wick-uri (sus, jos): implicite (0.25, 0.30), cu excepțiile care fixează nivelurile
wicks = [(0.25, 0.30)] * 32
wicks[11] = (0.00, 0.30) # swing high: high = close = 100.00
wicks[18] = (0.20, 0.45) # BIM: codiță lungă în jos (hammer)
wicks[18] = (0.20, 0.43) # BIM: codiță lungă în jos, fundul la 95.55
wicks[19] = (0.20, 0.15) # candela de intrare
wicks[31] = (0.00, 0.30) # TP: high = close = 105.60
@@ -115,7 +116,7 @@ ch = Chart(
Mark(BIM_I, "BIM", GREEN, "above", dy=-2),
Mark(ENTRY_I, "candelă verde → trigger", GREEN, "below", dy=20),
],
scale=18.0, gap=16, body_w=9, left=44, width=680, vol_h=70,
scale=21.0, gap=16, body_w=9, left=44, width=680, vol_h=70,
vol_label="volum", title="SPY — daily: aceeași corecție, 4.0 % (DA) vs. 3.9 % (NU)",
caption="Calea DA (candele): 4.0 % la 96.00. Calea NU (punctat): 3.9 % („3.93 %” în curs) — fără intrare.",
)
@@ -123,9 +124,14 @@ svg = ch.render()
# --- elemente suplimentare, pe coordonatele graficului -----------------------
x0, x1 = 24, ch.width - 14
band_top, band_bot = ch._y(96.40), ch._y(95.40)
PPQ = 95.80 # pivotul trimestrial, calculat în atmi_pivoti.py
FUND = round(min(c.l for c in cds[12:20]), 2)
assert FUND == 95.55, FUND
assert PPQ - 0.30 <= FUND <= PPQ + 0.30, "fundul căii DA nu cade în banda PPQ"
assert NU_STOP >= PPQ + 0.30, "calea NU ar coborî în zona de cumpărare"
band_top, band_bot = ch._y(PPQ + 0.30), ch._y(PPQ - 0.30)
band = (f'<rect x="{x0}" y="{band_top:.1f}" width="{x1 - x0}" height="{band_bot - band_top:.1f}" '
f'fill="{GRAY}" opacity="0.10"/>')
f'fill="{PURPLE}" opacity="0.12"/>')
nu_line = ('<polyline points="' + " ".join(f"{ch._cx(i):.1f},{ch._y(p):.1f}" for i, p in nu_pts) + '" '
f'fill="none" stroke="{RED}" stroke-width="1.8" stroke-dasharray="5 4"/>')
@@ -135,15 +141,15 @@ nu_hline = (f'<line x1="24" y1="{ch._y(NU_STOP):.1f}" x2="{ch.width - 14}" y2="{
# punctul de oprire al traseului NU (96.10, strict deasupra pragului de 4 %)
stop_dot = (f'<circle cx="{ch._cx(17):.1f}" cy="{ch._y(NU_STOP):.1f}" r="3.5" fill="{RED}"/>')
# eticheta traseului NU, sub linia 96.10 (nu se suprapune cu eticheta verde de 96.00)
nu_lab = (f'<text x="{ch.width - 28}" y="{ch._y(NU_STOP) + 12:.1f}" fill="{RED}" text-anchor="end">'
f'96.10 = 3.9 % — NU, sub prag</text>')
nu_lab = (f'<text x="30" y="{ch._y(NU_STOP) - 8:.1f}" fill="{RED}">'
f'{NU_STOP:.2f} = 3.9 % — NU, sub prag</text>')
# eticheta zonei quarterly, sub banda (fără cifre: cursul nu le dă)
zone_lab = (f'<text x="{ch.width - 28}" y="{ch._y(95.40) + 13:.1f}" fill="{GRAY}" text-anchor="end">'
f'zonă quarterly</text>')
zone_lab = (f'<text x="30" y="{ch._y(PPQ - 0.30) + 34:.1f}" fill="{PURPLE}">'
f'zona PPQ {PPQ:.2f} — aici cumperi</text>')
# legende scurte ale celor două trasee
da_lab = (f'<text x="24" y="{ch._y(98.50):.1f}" fill="{GREEN}" '
da_lab = (f'<text x="24" y="{ch._y(97.60):.1f}" fill="{GREEN}" '
f'style="font-weight:bold">calea DA (candelele)</text>')
nu_leg = (f'<text x="{ch._cx(25):.1f}" y="{ch._y(94.45) + 16:.1f}" fill="{RED}" '
nu_leg = (f'<text x="{ch._cx(25):.1f}" y="{ch._y(94.45) + 30:.1f}" fill="{RED}" '
f'style="font-weight:bold">calea NU (continuă în jos)</text>')
overlay = [nu_line, nu_hline, stop_dot, nu_lab, zone_lab, da_lab, nu_leg]
@@ -151,8 +157,9 @@ svg = svg.replace(">", ">\n " + band, 1) # ban
svg = svg.replace("\n</svg>", "\n " + "\n ".join(overlay) + "\n</svg>") # traseele, peste
assert "\n\n" not in svg, "linie goală în SVG"
assert ".md:" not in svg, "trimitere fișier:linie în SVG"
assert "</svg>" in svg and "stroke-dasharray=\"5 4\"" in svg, "traseul NU nu a fost inserat"
with open("/workspace/atm-curs-dl/gen/strategii/atmi_aplus.svg", "w") as f:
with open("/workspace/atm-curs-dl/gen/strategii/atmi_corectie.svg", "w") as f:
f.write(svg)
print("scris gen/strategii/atmi_aplus.svg")
print("scris gen/strategii/atmi_corectie.svg")

View File

@@ -0,0 +1,119 @@
<svg viewBox="0 0 680 557" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif">
<rect x="24" y="233.5" width="642" height="12.6" fill="#7b2fbf" opacity="0.12"/>
<text x="24" y="48" fill="#333" style="font-weight:bold">SPY — daily: aceeași corecție, 4.0 % (DA) vs. 3.9 % (NU)</text>
<line x1="24" y1="173.6" x2="666" y2="173.6" stroke="#333" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="652" y="167.6" fill="#333" text-anchor="end">100.00 — swing high</text>
<line x1="24" y1="257.6" x2="666" y2="257.6" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="652" y="251.6" fill="#188a3e" text-anchor="end">96.00 = 4.0 % — DA, intri</text>
<line x1="24" y1="56.0" x2="666" y2="56.0" stroke="#1a5fb4" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="652" y="50.0" fill="#1a5fb4" text-anchor="end">TP +10 % = 105.60</text>
<line x1="44.0" y1="378.3" x2="44.0" y2="402.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="39.5" y="383.6" width="9" height="12.6" fill="#188a3e"/>
<line x1="60.0" y1="359.4" x2="60.0" y2="389.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="55.5" y="364.7" width="9" height="18.9" fill="#188a3e"/>
<line x1="76.0" y1="342.6" x2="76.0" y2="371.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="71.5" y="347.9" width="9" height="16.8" fill="#188a3e"/>
<line x1="92.0" y1="327.9" x2="92.0" y2="354.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="87.5" y="333.2" width="9" height="14.7" fill="#188a3e"/>
<line x1="108.0" y1="311.1" x2="108.0" y2="339.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="103.5" y="316.4" width="9" height="16.8" fill="#188a3e"/>
<line x1="124.0" y1="294.3" x2="124.0" y2="322.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="119.5" y="299.6" width="9" height="16.8" fill="#188a3e"/>
<line x1="140.0" y1="279.6" x2="140.0" y2="305.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="135.5" y="284.9" width="9" height="14.7" fill="#188a3e"/>
<line x1="156.0" y1="264.9" x2="156.0" y2="291.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="151.5" y="270.2" width="9" height="14.7" fill="#188a3e"/>
<line x1="172.0" y1="250.2" x2="172.0" y2="276.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="167.5" y="255.5" width="9" height="14.7" fill="#188a3e"/>
<line x1="188.0" y1="231.3" x2="188.0" y2="261.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="183.5" y="236.6" width="9" height="18.9" fill="#188a3e"/>
<line x1="204.0" y1="204.0" x2="204.0" y2="242.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="199.5" y="209.3" width="9" height="27.3" fill="#188a3e"/>
<line x1="220.0" y1="173.6" x2="220.0" y2="215.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="215.5" y="173.6" width="9" height="35.7" fill="#188a3e"/>
<line x1="236.0" y1="168.3" x2="236.0" y2="194.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="231.5" y="173.6" width="9" height="14.7" fill="#c00"/>
<line x1="252.0" y1="183.0" x2="252.0" y2="211.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="247.5" y="188.3" width="9" height="16.8" fill="#c00"/>
<line x1="268.0" y1="199.8" x2="268.0" y2="228.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="263.5" y="205.1" width="9" height="16.8" fill="#c00"/>
<line x1="284.0" y1="216.6" x2="284.0" y2="240.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="279.5" y="221.9" width="9" height="12.6" fill="#c00"/>
<line x1="300.0" y1="229.2" x2="300.0" y2="251.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="295.5" y="234.5" width="9" height="10.5" fill="#c00"/>
<line x1="316.0" y1="239.8" x2="316.0" y2="259.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="311.5" y="245.0" width="9" height="8.4" fill="#c00"/>
<line x1="332.0" y1="249.2" x2="332.0" y2="267.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="327.5" y="253.4" width="9" height="4.6" fill="#c00"/>
<line x1="348.0" y1="253.4" x2="348.0" y2="261.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="343.5" y="257.6" width="9" height="1.6" fill="#188a3e"/>
<line x1="364.0" y1="231.3" x2="364.0" y2="263.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="359.5" y="236.6" width="9" height="21.0" fill="#188a3e"/>
<line x1="380.0" y1="212.4" x2="380.0" y2="242.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="375.5" y="217.7" width="9" height="18.9" fill="#188a3e"/>
<line x1="396.0" y1="193.5" x2="396.0" y2="224.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="391.5" y="198.8" width="9" height="18.9" fill="#188a3e"/>
<line x1="412.0" y1="174.6" x2="412.0" y2="205.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="407.5" y="179.9" width="9" height="18.9" fill="#188a3e"/>
<line x1="428.0" y1="157.8" x2="428.0" y2="186.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="423.5" y="163.1" width="9" height="16.8" fill="#188a3e"/>
<line x1="444.0" y1="141.0" x2="444.0" y2="169.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="439.5" y="146.3" width="9" height="16.8" fill="#188a3e"/>
<line x1="460.0" y1="124.2" x2="460.0" y2="152.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="455.5" y="129.5" width="9" height="16.8" fill="#188a3e"/>
<line x1="476.0" y1="107.4" x2="476.0" y2="135.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="471.5" y="112.7" width="9" height="16.8" fill="#188a3e"/>
<line x1="492.0" y1="90.6" x2="492.0" y2="119.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="487.5" y="95.9" width="9" height="16.8" fill="#188a3e"/>
<line x1="508.0" y1="73.8" x2="508.0" y2="102.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="503.5" y="79.1" width="9" height="16.8" fill="#188a3e"/>
<line x1="524.0" y1="61.2" x2="524.0" y2="85.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="519.5" y="66.5" width="9" height="12.6" fill="#188a3e"/>
<line x1="540.0" y1="56.0" x2="540.0" y2="72.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="535.5" y="56.0" width="9" height="10.5" fill="#188a3e"/>
<line x1="24" y1="498.5" x2="666" y2="498.5" stroke="#888"/>
<rect x="39.5" y="460.3" width="9" height="38.2" fill="#188a3e" opacity="0.55"/>
<rect x="55.5" y="458.7" width="9" height="39.8" fill="#188a3e" opacity="0.55"/>
<rect x="71.5" y="461.9" width="9" height="36.6" fill="#188a3e" opacity="0.55"/>
<rect x="87.5" y="457.1" width="9" height="41.4" fill="#188a3e" opacity="0.55"/>
<rect x="103.5" y="455.5" width="9" height="43.0" fill="#188a3e" opacity="0.55"/>
<rect x="119.5" y="458.7" width="9" height="39.8" fill="#188a3e" opacity="0.55"/>
<rect x="135.5" y="454.0" width="9" height="44.5" fill="#188a3e" opacity="0.55"/>
<rect x="151.5" y="457.1" width="9" height="41.4" fill="#188a3e" opacity="0.55"/>
<rect x="167.5" y="452.4" width="9" height="46.1" fill="#188a3e" opacity="0.55"/>
<rect x="183.5" y="450.8" width="9" height="47.7" fill="#188a3e" opacity="0.55"/>
<rect x="199.5" y="447.6" width="9" height="50.9" fill="#188a3e" opacity="0.55"/>
<rect x="215.5" y="441.2" width="9" height="57.3" fill="#188a3e" opacity="0.55"/>
<rect x="231.5" y="442.8" width="9" height="55.7" fill="#c00" opacity="0.55"/>
<rect x="247.5" y="439.6" width="9" height="58.9" fill="#c00" opacity="0.55"/>
<rect x="263.5" y="436.5" width="9" height="62.0" fill="#c00" opacity="0.55"/>
<rect x="279.5" y="433.3" width="9" height="65.2" fill="#c00" opacity="0.55"/>
<rect x="295.5" y="430.1" width="9" height="68.4" fill="#c00" opacity="0.55"/>
<rect x="311.5" y="434.9" width="9" height="63.6" fill="#c00" opacity="0.55"/>
<rect x="327.5" y="431.7" width="9" height="66.8" fill="#c00" opacity="0.55"/>
<rect x="343.5" y="428.5" width="9" height="70.0" fill="#188a3e" opacity="0.55"/>
<rect x="359.5" y="441.2" width="9" height="57.3" fill="#188a3e" opacity="0.55"/>
<rect x="375.5" y="446.0" width="9" height="52.5" fill="#188a3e" opacity="0.55"/>
<rect x="391.5" y="449.2" width="9" height="49.3" fill="#188a3e" opacity="0.55"/>
<rect x="407.5" y="452.4" width="9" height="46.1" fill="#188a3e" opacity="0.55"/>
<rect x="423.5" y="455.5" width="9" height="43.0" fill="#188a3e" opacity="0.55"/>
<rect x="439.5" y="458.7" width="9" height="39.8" fill="#188a3e" opacity="0.55"/>
<rect x="455.5" y="461.9" width="9" height="36.6" fill="#188a3e" opacity="0.55"/>
<rect x="471.5" y="449.2" width="9" height="49.3" fill="#188a3e" opacity="0.55"/>
<rect x="487.5" y="444.4" width="9" height="54.1" fill="#188a3e" opacity="0.55"/>
<rect x="503.5" y="441.2" width="9" height="57.3" fill="#188a3e" opacity="0.55"/>
<rect x="519.5" y="436.5" width="9" height="62.0" fill="#188a3e" opacity="0.55"/>
<rect x="535.5" y="430.1" width="9" height="68.4" fill="#188a3e" opacity="0.55"/>
<text x="24" y="422.5" fill="#555">volum</text>
<text x="332.0" y="237.2" fill="#188a3e" text-anchor="middle" style="font-weight:bold">BIM</text>
<text x="348.0" y="301.2" fill="#188a3e" text-anchor="middle" style="font-weight:bold">candelă verde → trigger</text>
<text x="24" y="520.5" fill="#188a3e">Regula e pe procent, nu pe cât de dramatică arată linia: calea NU pare o cădere mare, dar e 3.9 %.</text>
<text x="24" y="545" fill="#555">Calea DA (candele): 4.0 % la 96.00. Calea NU (punctat): 3.9 % („3.93 %” în curs) — fără intrare.</text>
<polyline points="220.0,151.6 236.0,164.2 252.0,179.9 268.0,194.6 284.0,207.2 300.0,218.8 316.0,233.5 332.0,241.9 348.0,249.2 380.0,257.6 412.0,263.9 444.0,268.1" fill="none" stroke="#c00" stroke-width="1.8" stroke-dasharray="5 4"/>
<line x1="24" y1="233.5" x2="666" y2="233.5" stroke="#c00" stroke-width="1.5" stroke-dasharray="4 3"/>
<circle cx="316.0" cy="233.5" r="3.5" fill="#c00"/>
<text x="30" y="225.5" fill="#c00">96.10 = 3.9 % — NU, sub prag</text>
<text x="30" y="280.1" fill="#7b2fbf">zona PPQ 95.80 — aici cumperi</text>
<text x="24" y="202.0" fill="#188a3e" style="font-weight:bold">calea DA (candelele)</text>
<text x="444.0" y="298.1" fill="#c00" style="font-weight:bold">calea NU (continuă în jos)</text>
</svg>

After

Width:  |  Height:  |  Size: 9.8 KiB

View File

@@ -24,10 +24,10 @@ ENTRY = 117.43 # 04_MODUL_3/03_strategia_2_atmi.md:358-363
TP = 129.17 # TP1 = +10 % pe 117.43 → 129.17 (":170-171, 358-363")
SWING_HIGH = 123.00 # construit de mine ca să conțină corecția ≥4 %
ENTRY_I = 17 # candela de intrare (verde, precedată de BIM)
TP_I = 37 # ultima candelă: TP1 atins
TP_I = 30 # ultima candelă: TP1 atins
BIM_I = ENTRY_I - 1 # BIM (bară de inversare bearish) înaintea candelei verzi
# ── structura seriei: 12 sus → 6 corecție → intrare → 20 spre TP ───────────
# ── structura seriei: 12 sus → 5 corecție → intrare → 13 luni spre TP ─────
closes = [
# ~12 candele de urcare spre swing high ~123.00
115.80, 116.50, 117.20, 117.90, 117.60, 118.30,
@@ -35,13 +35,11 @@ closes = [
# ~6 candele de corecție, de la 123.00 în zona de intrare
122.00, 121.10, 120.10, 119.00, 117.00,
117.43, # candela de intrare (verde)
# ~20 candele de urcare de la 117.43 spre 129.17
118.00, 118.55, 119.05, 119.50, 119.95,
120.40, 120.85, 121.25, 121.65, 122.10,
122.50, 122.95, 123.40, 123.85, 124.30,
125.00, 126.00, 127.10, 128.40, 129.17,
# 13 candele lunare de urcare de la 117.43 spre 129.17 — „aproximativ un an"
118.20, 119.10, 119.90, 120.60, 121.50, 122.40, 123.30,
124.20, 125.30, 126.40, 127.40, 128.30, 129.17,
]
assert len(closes) == 38, len(closes)
assert len(closes) == 31, len(closes)
wicks = [(0.25, 0.30)] * len(closes)
wicks[0] = (0.35, 0.35)
@@ -53,8 +51,8 @@ wicks[TP_I] = (0.00, 0.30) # high = 129.17 exact, ca TP să fie max(high)
vols = [42, 40, 44, 47, 39, 45, 48, 52, 50, 55, 58, 62,
57, 61, 66, 72, 84,
70,
58, 55, 53, 57, 54, 56, 59, 55, 57, 60, 58, 61,
63, 60, 64, 66, 68, 72, 76, 88]
58, 55, 53, 57, 54, 56, 59, 62, 64, 68, 72, 78, 88]
assert len(vols) == len(closes), (len(vols), len(closes))
cds = from_closes(closes, wicks=wicks, vols=vols, start=115.30)
@@ -68,7 +66,7 @@ assert abs(tp - 129.17) < 0.05, tp
assert abs(tp / entry - 1.10) < 0.005, tp / entry
assert (swing_high - entry) / swing_high >= 0.04, (swing_high, entry)
assert abs(entry - cds[ENTRY_I].c) < 0.05
assert abs(max(c.h for c in cds[-10:]) - tp) < 0.05, max(c.h for c in cds[-10:])
assert abs(max(c.h for c in cds[-13:]) - tp) < 0.05, max(c.h for c in cds[-13:])
# structura care susține afirmațiile din text
assert abs(swing_high - SWING_HIGH) < 0.05, swing_high
@@ -76,14 +74,15 @@ assert cds[ENTRY_I].c > cds[ENTRY_I].o, "candela de intrare trebuie să fie verd
assert cds[BIM_I].c < cds[BIM_I].o, "BIM-ul dinaintea intrării trebuie să fie bearish"
assert any(c.vol is not None for c in cds), "lipsește panoul de volum"
n_entry_to_tp = TP_I - ENTRY_I + 1
assert 18 <= n_entry_to_tp <= 23, n_entry_to_tp
LUNI = TP_I - ENTRY_I # câte candele lunare de la intrare la TP1
assert 12 <= LUNI <= 14, LUNI # „aproximativ un an" din material
TP_LABEL = "TP1 atins ~1 an mai târziu (data exactă neclară în transcriere — ASR)"
assert "~1 an" in TP_LABEL
TP_LABEL = f"TP1 atins {LUNI} luni mai târziu — „aproximativ un an\" în material "\
"(ziua exactă e neclară în transcriere)"
assert "aproximativ un an" in TP_LABEL
levels = [
Level(ENTRY, "intrare 117.43", "#188a3e", label_at="left"),
Level(ENTRY, "intrare 117.43", "#188a3e", label_at="right"),
Level(TP, "TP1 129.17 (+10 %)", "#1a5fb4"),
]
@@ -101,6 +100,8 @@ assert len(levels) == 2, "doar intrare și TP; strategic nu există stop standar
# etichetele lungi merg ca linii de text sub grafic, ca să nu se bată cu
# candelele din dreapta-sus (unde urcarea spre TP nu lasă loc liber)
cds[TP_I - 2].note = ("trigger-ul (BIM + candela verde daily) se petrece în interiorul "
"lunii de intrare — vezi diagrama pasului 4")
cds[TP_I - 1].note = "după TP: capital + profit → cash până la următorul trigger valid"
cds[TP_I].note = TP_LABEL
@@ -110,16 +111,17 @@ ch = Chart(
marks=marks,
mas=[MA(20, "#b06000", dash="4 3")],
scale=9.5, width=660, gap=15, body_w=9, left=40, vol_h=70,
vol_label="volum", title="SPY — weekly: intrare 117.43 (27.01.2005) → TP +10 % = 129.17",
caption="Swing high ~123.00 construit de mine; cifrele de intrare/TP sunt din material.",
vol_label="volum", title="SPY — monthly: intrare ianuarie 2005 la 117.43 → TP1 +10 % = 129.17",
caption="Grafic lunar, ca să încapă orizontul poziției. Swing high-ul e al meu; "
"intrarea și ținta sunt din material.",
)
svg = ch.render()
assert svg.count("\n\n") == 0, "linie goală în SVG — rupe markdown-ul"
OUT.write_text(svg)
print(f"serie {len(cds)} candele | entry {entry:.2f} @ {ENTRY_I} | "
print(f"serie {len(cds)} candele lunare | entry {entry:.2f} @ {ENTRY_I} | "
f"tp {tp:.2f} @ {TP_I} | swing high {swing_high:.2f} "
f"(corecție {(swing_high - entry) / swing_high * 100:.2f} %) | "
f"entry→TP {n_entry_to_tp} candele (~1 an)")
f"entry→TP {LUNI} luni")
print(f"scris {OUT}")

View File

@@ -1,10 +1,10 @@
<svg viewBox="0 0 660 363" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif">
<text x="24" y="48" fill="#333" style="font-weight:bold">SPY — weekly: intrare 117.43 (27.01.2005) → TP +10 % = 129.17</text>
<svg viewBox="0 0 660 380" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif">
<text x="24" y="48" fill="#333" style="font-weight:bold">SPY — monthly: intrare ianuarie 2005 la 117.43 → TP1 +10 % = 129.17</text>
<line x1="24" y1="167.5" x2="646" y2="167.5" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30" y="161.5" fill="#188a3e">intrare 117.43</text>
<text x="632" y="161.5" fill="#188a3e" text-anchor="end">intrare 117.43</text>
<line x1="24" y1="56.0" x2="646" y2="56.0" stroke="#1a5fb4" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="632" y="50.0" fill="#1a5fb4" text-anchor="end">TP1 129.17 (+10 %)</text>
<polyline points="325.0,152.1 340.0,150.6 355.0,149.2 370.0,147.9 385.0,146.7 400.0,145.1 415.0,143.7 430.0,142.5 445.0,141.3 460.0,140.3 475.0,139.4 490.0,138.6 505.0,138.1 520.0,137.0 535.0,135.1 550.0,132.3 565.0,128.5 580.0,123.1 595.0,117.5" fill="none" stroke="#b06000" stroke-width="1.5" stroke-dasharray="4 3"/>
<polyline points="325.0,151.8 340.0,149.8 355.0,147.9 370.0,145.9 385.0,143.7 400.0,141.0 415.0,138.2 430.0,135.2 445.0,132.0 460.0,128.7 475.0,125.2 490.0,121.7" fill="none" stroke="#b06000" stroke-width="1.5" stroke-dasharray="4 3"/>
<line x1="40.0" y1="179.7" x2="40.0" y2="191.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="35.5" y="183.0" width="9" height="4.8" fill="#188a3e"/>
<line x1="55.0" y1="174.0" x2="55.0" y2="185.9" stroke="#1a1a1a" stroke-width="1.2"/>
@@ -41,46 +41,32 @@
<rect x="275.5" y="152.6" width="9" height="19.0" fill="#c00"/>
<line x1="295.0" y1="165.6" x2="295.0" y2="175.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="290.5" y="167.5" width="9" height="4.1" fill="#188a3e"/>
<line x1="310.0" y1="159.7" x2="310.0" y2="170.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="305.5" y="162.1" width="9" height="5.4" fill="#188a3e"/>
<line x1="325.0" y1="154.5" x2="325.0" y2="165.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="320.5" y="156.9" width="9" height="5.2" fill="#188a3e"/>
<line x1="340.0" y1="149.8" x2="340.0" y2="159.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="335.5" y="152.1" width="9" height="4.8" fill="#188a3e"/>
<line x1="355.0" y1="145.5" x2="355.0" y2="155.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="350.5" y="147.9" width="9" height="4.3" fill="#188a3e"/>
<line x1="370.0" y1="141.2" x2="370.0" y2="150.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="365.5" y="143.6" width="9" height="4.3" fill="#188a3e"/>
<line x1="385.0" y1="136.9" x2="385.0" y2="146.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="380.5" y="139.3" width="9" height="4.3" fill="#188a3e"/>
<line x1="400.0" y1="132.7" x2="400.0" y2="142.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="395.5" y="135.0" width="9" height="4.3" fill="#188a3e"/>
<line x1="415.0" y1="128.9" x2="415.0" y2="137.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="410.5" y="131.2" width="9" height="3.8" fill="#188a3e"/>
<line x1="430.0" y1="125.1" x2="430.0" y2="134.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="425.5" y="127.4" width="9" height="3.8" fill="#188a3e"/>
<line x1="445.0" y1="120.8" x2="445.0" y2="130.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="440.5" y="123.2" width="9" height="4.3" fill="#188a3e"/>
<line x1="460.0" y1="117.0" x2="460.0" y2="126.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="455.5" y="119.4" width="9" height="3.8" fill="#188a3e"/>
<line x1="475.0" y1="112.7" x2="475.0" y2="122.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="470.5" y="115.1" width="9" height="4.3" fill="#188a3e"/>
<line x1="490.0" y1="108.4" x2="490.0" y2="117.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="485.5" y="110.8" width="9" height="4.3" fill="#188a3e"/>
<line x1="505.0" y1="104.2" x2="505.0" y2="113.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="500.5" y="106.5" width="9" height="4.3" fill="#188a3e"/>
<line x1="520.0" y1="99.9" x2="520.0" y2="109.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="515.5" y="102.3" width="9" height="4.3" fill="#188a3e"/>
<line x1="535.0" y1="93.2" x2="535.0" y2="105.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="530.5" y="95.6" width="9" height="6.7" fill="#188a3e"/>
<line x1="550.0" y1="83.7" x2="550.0" y2="98.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="545.5" y="86.1" width="9" height="9.5" fill="#188a3e"/>
<line x1="565.0" y1="73.3" x2="565.0" y2="89.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="560.5" y="75.7" width="9" height="10.4" fill="#188a3e"/>
<line x1="580.0" y1="60.9" x2="580.0" y2="78.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="575.5" y="63.3" width="9" height="12.4" fill="#188a3e"/>
<line x1="595.0" y1="56.0" x2="595.0" y2="66.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="590.5" y="56.0" width="9" height="7.3" fill="#188a3e"/>
<line x1="310.0" y1="157.8" x2="310.0" y2="170.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="305.5" y="160.2" width="9" height="7.3" fill="#188a3e"/>
<line x1="325.0" y1="149.3" x2="325.0" y2="163.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="320.5" y="151.7" width="9" height="8.5" fill="#188a3e"/>
<line x1="340.0" y1="141.7" x2="340.0" y2="154.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="335.5" y="144.1" width="9" height="7.6" fill="#188a3e"/>
<line x1="355.0" y1="135.0" x2="355.0" y2="146.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="350.5" y="137.4" width="9" height="6.6" fill="#188a3e"/>
<line x1="370.0" y1="126.5" x2="370.0" y2="140.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="365.5" y="128.9" width="9" height="8.6" fill="#188a3e"/>
<line x1="385.0" y1="117.9" x2="385.0" y2="131.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="380.5" y="120.3" width="9" height="8.6" fill="#188a3e"/>
<line x1="400.0" y1="109.4" x2="400.0" y2="123.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="395.5" y="111.8" width="9" height="8.5" fill="#188a3e"/>
<line x1="415.0" y1="100.8" x2="415.0" y2="114.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="410.5" y="103.2" width="9" height="8.6" fill="#188a3e"/>
<line x1="430.0" y1="90.4" x2="430.0" y2="106.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="425.5" y="92.8" width="9" height="10.4" fill="#188a3e"/>
<line x1="445.0" y1="79.9" x2="445.0" y2="95.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="440.5" y="82.3" width="9" height="10.5" fill="#188a3e"/>
<line x1="460.0" y1="70.4" x2="460.0" y2="85.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="455.5" y="72.8" width="9" height="9.5" fill="#188a3e"/>
<line x1="475.0" y1="61.9" x2="475.0" y2="75.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="470.5" y="64.3" width="9" height="8.6" fill="#188a3e"/>
<line x1="490.0" y1="56.0" x2="490.0" y2="67.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="485.5" y="56.0" width="9" height="8.3" fill="#188a3e"/>
<line x1="24" y1="287.1" x2="646" y2="287.1" stroke="#888"/>
<rect x="35.5" y="253.7" width="9" height="33.4" fill="#188a3e" opacity="0.55"/>
<rect x="50.5" y="255.3" width="9" height="31.8" fill="#188a3e" opacity="0.55"/>
@@ -107,25 +93,19 @@
<rect x="365.5" y="244.1" width="9" height="43.0" fill="#188a3e" opacity="0.55"/>
<rect x="380.5" y="242.5" width="9" height="44.5" fill="#188a3e" opacity="0.55"/>
<rect x="395.5" y="240.2" width="9" height="46.9" fill="#188a3e" opacity="0.55"/>
<rect x="410.5" y="243.3" width="9" height="43.8" fill="#188a3e" opacity="0.55"/>
<rect x="425.5" y="241.7" width="9" height="45.3" fill="#188a3e" opacity="0.55"/>
<rect x="440.5" y="239.4" width="9" height="47.7" fill="#188a3e" opacity="0.55"/>
<rect x="455.5" y="241.0" width="9" height="46.1" fill="#188a3e" opacity="0.55"/>
<rect x="470.5" y="238.6" width="9" height="48.5" fill="#188a3e" opacity="0.55"/>
<rect x="485.5" y="237.0" width="9" height="50.1" fill="#188a3e" opacity="0.55"/>
<rect x="500.5" y="239.4" width="9" height="47.7" fill="#188a3e" opacity="0.55"/>
<rect x="515.5" y="236.2" width="9" height="50.9" fill="#188a3e" opacity="0.55"/>
<rect x="530.5" y="234.6" width="9" height="52.5" fill="#188a3e" opacity="0.55"/>
<rect x="545.5" y="233.0" width="9" height="54.1" fill="#188a3e" opacity="0.55"/>
<rect x="560.5" y="229.8" width="9" height="57.3" fill="#188a3e" opacity="0.55"/>
<rect x="575.5" y="226.6" width="9" height="60.5" fill="#188a3e" opacity="0.55"/>
<rect x="590.5" y="217.1" width="9" height="70.0" fill="#188a3e" opacity="0.55"/>
<rect x="410.5" y="237.8" width="9" height="49.3" fill="#188a3e" opacity="0.55"/>
<rect x="425.5" y="236.2" width="9" height="50.9" fill="#188a3e" opacity="0.55"/>
<rect x="440.5" y="233.0" width="9" height="54.1" fill="#188a3e" opacity="0.55"/>
<rect x="455.5" y="229.8" width="9" height="57.3" fill="#188a3e" opacity="0.55"/>
<rect x="470.5" y="225.0" width="9" height="62.0" fill="#188a3e" opacity="0.55"/>
<rect x="485.5" y="217.1" width="9" height="70.0" fill="#188a3e" opacity="0.55"/>
<text x="24" y="211.1" fill="#555">volum</text>
<text x="205.0" y="104.6" fill="#c00" text-anchor="middle" style="font-weight:bold">swing high ~123.00</text>
<text x="280.0" y="141.2" fill="#777" text-anchor="middle" style="font-weight:bold">BIM</text>
<text x="295.0" y="195.4" fill="#188a3e" text-anchor="middle" style="font-weight:bold">27.01.2005</text>
<text x="607.0" y="86.2" fill="#1a5fb4" text-anchor="end" style="font-weight:bold">TP1</text>
<text x="24" y="309.1" fill="#188a3e">după TP: capital + profit → cash până la următorul trigger valid</text>
<text x="24" y="326.1" fill="#188a3e">TP1 atins ~1 an mai târziu (data exactă neclară în transcriere — ASR)</text>
<text x="24" y="351" fill="#555">Swing high ~123.00 construit de mine; cifrele de intrare/TP sunt din material.</text>
<text x="490.0" y="87.1" fill="#1a5fb4" text-anchor="middle" style="font-weight:bold">TP1</text>
<text x="24" y="309.1" fill="#188a3e">trigger-ul (BIM + candela verde daily) se petrece în interiorul lunii de intrare — vezi diagrama pasului 4</text>
<text x="24" y="326.1" fill="#188a3e">după TP: capital + profit → cash până la următorul trigger valid</text>
<text x="24" y="343.1" fill="#188a3e">TP1 atins 13 luni mai târziu — „aproximativ un an" în material (ziua exactă e neclară în transcriere)</text>
<text x="24" y="368" fill="#555">Grafic lunar, ca să încapă orizontul poziției. Swing high-ul e al meu; intrarea și ținta sunt din material.</text>
</svg>

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 9.2 KiB

View File

@@ -0,0 +1,260 @@
#!/usr/bin/env python3
"""ATMI — Pasul 3: nivelul trăiește pe weekly, declanșatorul pe daily.
Panoul din stânga (weekly) arată de unde pleacă corecția și unde stă zona de
cumpărare. Panoul din dreapta NU e o serie care vine după el: e
**descompunerea reală** a ultimelor 3 candele weekly — fiecare candelă
weekly = 5 bare daily, cu open, close, max(high) și min(low) care coincid,
verificat bară cu bară.
Sursa de adevăr e seria daily (`FINE`); candelele weekly din casetă se
calculează din ea prin agregare, deci corespondența nu poate rămâne în urmă.
Nivelul comun e PPQ 95.80 (calculat în `atmi_pivoti.py`): e desenat pe
ambele panouri, cu același număr, și legat printr-un conector — scările au
pante diferite, e o lupă, deci același preț cade la înălțimi diferite.
Rulare: python3 gen/strategii/atmi_perechi_tf.py
"""
from pathlib import Path
OUT = Path(__file__).with_suffix(".svg")
W = 720
K = 5 # 5 zile de bursă într-o săptămână
NZ = 3 # câte candele weekly se sparg în dreapta
PPQ, SQ = 95.80, 90.80 # din atmi_pivoti.py
SWING = 100.00
GREEN, RED, GRAY, INK, BLUE = "#188a3e", "#c00", "#888", "#333", "#1a5fb4"
PURPLE, CYAN, LINK = "#7b2fbf", "#0a7f9e", "#aaa"
# --- seria daily: 15 bare = 3 săptămâni ------------------------------------
D_CLOSES = [98.60, 98.20, 97.90, 97.60, 97.90, # săptămâna 1
97.50, 97.10, 96.80, 97.00, 96.60, # săptămâna 2
96.30, 96.00, 95.90, 95.70, 96.00] # săptămâna 3 (13 = BIM, 14 = intrare)
D_START = 98.90
BIM_I, ENTRY_I = 13, 14
wick = [(0.15, 0.15)] * 15
wick[BIM_I] = (0.10, 0.15) # bara de BIM coboară sub PPQ: 95.70 - 0.15 = 95.55
wick[ENTRY_I] = (0.15, 0.05)
FINE, o = [], D_START
for i, c in enumerate(D_CLOSES):
wu, wd = wick[i]
FINE.append((o, max(o, c) + wu, min(o, c) - wd, c))
o = c
# --- barele weekly dinaintea lupei ----------------------------------------
# (open, high, low, close); ultima închide exact pe open-ul primei bare daily
BASE = [(93.60, 94.80, 93.30, 94.50), (94.50, 95.90, 94.20, 95.60),
(95.60, 97.10, 95.30, 96.80), (96.80, 98.30, 96.50, 98.00),
(98.00, 99.50, 97.70, 99.20), (99.20, 100.00, 98.90, 100.00),
(100.00, 100.00, 98.60, 98.90)]
SWING_I = 5
def aggregate(fine, k, n):
out_ = []
for j in range(n):
part = fine[j * k:(j + 1) * k]
out_.append((part[0][0], max(b[1] for b in part),
min(b[2] for b in part), part[-1][3]))
return out_
ZOOM = aggregate(FINE, K, NZ)
BIG = BASE + ZOOM
# --- ce trebuie să fie adevărat -------------------------------------------
eq = lambda a, b: abs(a - b) < 0.005 # noqa: E731
assert len(FINE) == K * NZ
for name, bars in (("weekly", BIG), ("daily", FINE)):
for i, (o_, h, l, c) in enumerate(bars):
assert h >= max(o_, c) and l <= min(o_, c), f"{name}[{i}] h/l incoerent"
if i:
assert eq(o_, bars[i - 1][3]), f"{name}[{i}] open != close precedent"
# lupa se leagă de restul graficului mare
assert eq(FINE[0][0], BASE[-1][3]), "open-ul primei bare daily != close-ul ultimei weekly"
# ce pretinde textul: corecția se întinde peste mai multe candele weekly, iar
# trigger-ul cade în ultima
assert eq(max(b[1] for b in BASE), SWING), max(b[1] for b in BASE)
assert BIM_I // K == ENTRY_I // K == NZ - 1, "BIM și intrarea nu cad în aceeași săptămână"
assert (BIM_I // K) > 0, "trigger-ul ar încăpea în prima candelă weekly a lupei"
ENTRY = FINE[ENTRY_I][3]
assert eq(ENTRY, 96.00) and eq((SWING - ENTRY) / SWING * 100, 4.0), ENTRY
assert FINE[ENTRY_I][3] > FINE[ENTRY_I][0], "candela de intrare nu e verde"
assert FINE[BIM_I][2] < PPQ < ENTRY, "prețul nu intră în zona PPQ înainte de intrare"
assert eq(ZOOM[-1][3], ENTRY), "close-ul săptămânii = close-ul barei daily de intrare"
assert eq(ZOOM[-1][2], FINE[BIM_I][2]), "low-ul săptămânii != low-ul barei de BIM"
assert min(b[2] for b in BIG) > SQ, "seria desenată atinge deja SQ"
# cât de aproape e fundul de PPQ, în procente — asta face zona „atinsă"
DIST = abs(FINE[BIM_I][2] - PPQ) / PPQ * 100
assert DIST < 0.5, DIST
# --- desen -----------------------------------------------------------------
PLOT_H = 190
BX0, BGAP = 132, 16
SX0, SGAP = 392, 14
BODY_W = 9
FRAME_L = SX0 - 12
COL_X = 608
MIDX = FRAME_L - 20
PAD = 0.07
out, LABELS = [], []
def text(x, y, s, fill=INK, anchor="start", bold=False, size=12):
st = f"font-size:{size}px" + (";font-weight:bold" if bold else "")
a = f' text-anchor="{anchor}"' if anchor != "start" else ""
w = len(s) * (size * 0.5 if size < 12 else 5.7)
x0 = x if anchor == "start" else (x - w / 2 if anchor == "middle" else x - w)
assert 4 <= x0 and x0 + w <= W - 4, f"text iese din viewBox: {s!r} ({x0:.0f}..{x0 + w:.0f})"
LABELS.append((x0, x0 + w, y, s))
out.append(f'<text x="{x:.1f}" y="{y:.1f}" fill="{fill}"{a} style="{st}">{s}</text>')
def hline(x1, x2, y, color, dash, width=1.5):
out.append(f'<line x1="{x1:.1f}" y1="{y:.1f}" x2="{x2:.1f}" y2="{y:.1f}" '
f'stroke="{color}" stroke-width="{width}" stroke-dasharray="{dash}"/>')
def line(x1, y1, x2, y2, color, dash="", width=1.2, marker=""):
d = f' stroke-dasharray="{dash}"' if dash else ""
m = f' marker-end="url(#{marker})"' if marker else ""
out.append(f'<line x1="{x1:.1f}" y1="{y1:.1f}" x2="{x2:.1f}" y2="{y2:.1f}" '
f'stroke="{color}" stroke-width="{width}"{d}{m}/>')
def rect(x0_, y0_, x1, y1, color, fill_op=0.10, dash=""):
d = f' stroke-dasharray="{dash}"' if dash else ""
out.append(f'<rect x="{x0_:.1f}" y="{y0_:.1f}" width="{x1 - x0_:.1f}" '
f'height="{y1 - y0_:.1f}" fill="{color}" fill-opacity="{fill_op}" '
f'stroke="{color}" stroke-width="1.2"{d}/>')
def candles(bars, x0, gap, yf):
for i, (o_, h, l, c) in enumerate(bars):
cx = x0 + i * gap
line(cx, yf(h), cx, yf(l), "#1a1a1a", width=1.2)
top_ = yf(max(o_, c))
hh = max(yf(min(o_, c)) - top_, 1.6)
out.append(f'<rect x="{cx - BODY_W / 2:.1f}" y="{top_:.1f}" width="{BODY_W}" '
f'height="{hh:.1f}" fill="{GREEN if c >= o_ else RED}"/>')
out.append('<defs><marker id="pt" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" '
'markerHeight="7" orient="auto"><path d="M0,0 L10,5 L0,10 z" fill="#c00"/></marker>'
'</defs>')
text(20, 22, "Nivelul trăiește pe weekly, declanșatorul pe daily", bold=True, size=13)
text(20, 38, f"Fiecare candelă weekly din casetă = {K} bare daily (o săptămână de bursă):",
fill="#555", size=11)
text(20, 52, "același open, același close, max(high) și min(low) identice.",
fill="#555", size=11)
top = 104
text(20, top - 12, "weekly: de unde pleacă corecția", fill="#555", size=11)
text(FRAME_L, top - 12, f"daily: ultimele {NZ} candele weekly, desfăcute", fill="#555", size=11)
zlo_, zhi_ = min(b[2] for b in FINE), max(b[1] for b in FINE)
pad = PAD * (zhi_ - zlo_)
lo, hi = zlo_ - pad, zhi_ + pad
bmax, bmin = max(b[1] for b in BIG), min(min(b[2] for b in BIG), SQ, lo)
bs, ss = PLOT_H / (bmax - bmin), PLOT_H / (hi - lo)
yb = lambda p: top + (bmax - p) * bs # noqa: E731
ys = lambda p: top + (hi - p) * ss # noqa: E731
# ---- panoul weekly ---------------------------------------------------------
lx0, lx1 = BX0 + len(BASE) * BGAP - 7, BX0 + (len(BIG) - 1) * BGAP + 9
ly0, ly1 = yb(hi), yb(lo)
rect(lx0, ly0, lx1, ly1, BLUE, fill_op=0.06, dash="4 3")
hline(BX0 - 22, lx1, yb(PPQ), PURPLE, "4 3")
hline(BX0 - 22, lx1, yb(SQ), GREEN, "4 3")
hline(BX0 - 22, lx1, yb(SWING), "#555", "3 3", width=1.0)
text(24, yb(SWING) + 13, f"swing high {SWING:.2f}", fill="#555", size=11)
text(24, yb(PPQ) - 6, f"PPQ {PPQ:.2f}", fill=PURPLE, size=11, bold=True)
text(24, yb(SQ) - 6, f"SQ {SQ:.2f}", fill=GREEN, size=11, bold=True)
text(24, yb(SQ) + 13, "zona 2, dacă", fill=GREEN, size=10)
text(24, yb(SQ) + 25, "panica merge", fill=GREEN, size=10)
text(24, yb(SQ) + 37, "mai jos", fill=GREEN, size=10)
candles(BIG, BX0, BGAP, yb)
# paranteza corecției: de la swing high până la intrare, pe panoul mare
brx = BX0 - 16
out.append(f'<path d="M{brx + 5:.1f},{yb(SWING):.1f} H{brx:.1f} V{yb(ENTRY):.1f} '
f'H{brx + 5:.1f}" fill="none" stroke="{RED}" stroke-width="1.6"/>')
text(brx - 3, (yb(SWING) + yb(ENTRY)) / 2 + 4,
f"-{(SWING - ENTRY) / SWING * 100:.1f} %".replace(".", ","),
fill=RED, anchor="end", bold=True, size=11)
text(BX0 + 2 * BGAP, top + PLOT_H + 20,
"corecția de minim 4 % se măsoară aici, pe weekly", fill=RED, size=11)
# ---- ghidajele de lupă -----------------------------------------------------
guides = [((lx1, ly0), (FRAME_L, top)), ((lx1, ly1), (FRAME_L, top + PLOT_H))]
for a_, b_ in guides:
line(a_[0], a_[1], b_[0], b_[1], BLUE, dash="5 3", width=1.1)
# ---- conectorul nivelului comun -------------------------------------------
ycb, ycs = yb(PPQ), ys(PPQ)
mid = (lx1 + FRAME_L) / 2
out.append(f'<path d="M{lx1:.1f},{ycb:.1f} H{mid:.1f} V{ycs:.1f} H{FRAME_L:.1f}" '
f'fill="none" stroke="{LINK}" stroke-width="1.0" stroke-dasharray="3 3"/>')
text(mid + 4, (ycb + ycs) / 2 + 4, "același", fill="#999", size=10)
text(mid + 4, (ycb + ycs) / 2 + 16, "preț", fill="#999", size=10)
# ---- panoul daily ----------------------------------------------------------
frame_r = SX0 + (len(FINE) - 1) * SGAP + 10
rect(FRAME_L, top, frame_r, top + PLOT_H, BLUE, fill_op=0.03)
y_ppq, y_e = ys(PPQ), ys(ENTRY)
assert top + PLOT_H - ys(zlo_) > 6, "minimul e lipit de marginea de jos a cadrului"
assert ys(zhi_) - top > 6, "maximul e lipit de marginea de sus a cadrului"
# zona de decizie: bara de BIM + candela verde
sx0, sx1 = SX0 + BIM_I * SGAP - 10, SX0 + ENTRY_I * SGAP + 10
rect(sx0, ys(FINE[ENTRY_I][1]) - 6, sx1, ys(min(b[2] for b in FINE)) + 6, GREEN)
hline(FRAME_L, frame_r, y_ppq, PURPLE, "4 3")
hline(FRAME_L, frame_r, y_e, GREEN, "6 3")
candles(FINE, SX0, SGAP, ys)
text(COL_X, y_ppq + 4, f"PPQ {PPQ:.2f}", fill=PURPLE, size=10, bold=True)
text(COL_X, y_ppq + 16, "același nivel,", fill=PURPLE, size=10)
text(COL_X, y_ppq + 28, "văzut de aproape", fill=PURPLE, size=10)
text(COL_X, y_e - 8, f"intrare {ENTRY:.2f}", fill=GREEN, size=10, bold=True)
line(SX0 + BIM_I * SGAP, ys(FINE[BIM_I][2]) + 4, SX0 + BIM_I * SGAP,
top + PLOT_H + 14, CYAN, width=1)
text(SX0 + BIM_I * SGAP - 6, top + PLOT_H + 28, "BIM: aici se oprește vânzarea",
fill=CYAN, anchor="middle", size=11, bold=True)
text(SX0 + BIM_I * SGAP - 6, top + PLOT_H + 42,
f"(fundul e la {DIST:.2f} % de PPQ)".replace(".", ","),
fill=CYAN, anchor="middle", size=10)
text(20, top + PLOT_H + 58,
"Pe weekly nu vezi unde s-a oprit căderea; pe daily, da — de aceea intri de aici.",
fill="#555", size=11)
# --- prețurile rămân fiecare pe panoul lui, cu excepția nivelului comun ----
COMUN = {f"{PPQ:.2f}"}
MARE = {f"{SWING:.2f}", f"{SQ:.2f}"} - COMUN
MIC = {f"{ENTRY:.2f}"} - COMUN
for x0_, _x1, _y, s_ in LABELS:
rau = MARE if x0_ >= MIDX else MIC
for v in rau:
assert v not in s_, f"eticheta {s_!r} poartă prețul {v} al celuilalt panou"
st_ = [s for x0_, _x1, _y, s in LABELS if f"{PPQ:.2f}" in s and x0_ < MIDX]
dr_ = [s for x0_, _x1, _y, s in LABELS if f"{PPQ:.2f}" in s and x0_ >= MIDX]
assert st_ and dr_, f"nivelul comun {PPQ} lipsește de pe un panou ({st_} / {dr_})"
H = top + PLOT_H + 76
for i in range(len(LABELS)):
for j in range(i + 1, len(LABELS)):
xa0, xa1, ya, sa = LABELS[i]
xb0, xb1, yb_, sb = LABELS[j]
assert not (abs(ya - yb_) < 12 and xa0 < xb1 - 4 and xb0 < xa1 - 4), \
f"etichete suprapuse: {sa!r} / {sb!r}"
assert 0 < LABELS[i][2] < H, f"etichetă în afara înălțimii: {LABELS[i][3]!r}"
svg = (f'<svg viewBox="0 0 {W} {H:.0f}" xmlns="http://www.w3.org/2000/svg" '
f'style="width:100%;height:auto;font:12px sans-serif">\n ' + "\n ".join(out) + "\n</svg>")
assert "\n\n" not in svg and ".md:" not in svg
OUT.write_text(svg, encoding="utf-8")
print(f"weekly {len(BIG)} bare (ultimele {NZ} = {len(FINE)} daily) | swing {SWING:.2f} "
f"| PPQ {PPQ} | intrare {ENTRY:.2f} | fund {min(b[2] for b in FINE):.2f} "
f"({DIST:.2f} % sub PPQ) | scris {OUT.name} ({W}x{H:.0f})")

View File

@@ -0,0 +1,88 @@
<svg viewBox="0 0 720 370" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif">
<defs><marker id="pt" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto"><path d="M0,0 L10,5 L0,10 z" fill="#c00"/></marker></defs>
<text x="20.0" y="22.0" fill="#333" style="font-size:13px;font-weight:bold">Nivelul trăiește pe weekly, declanșatorul pe daily</text>
<text x="20.0" y="38.0" fill="#555" style="font-size:11px">Fiecare candelă weekly din casetă = 5 bare daily (o săptămână de bursă):</text>
<text x="20.0" y="52.0" fill="#555" style="font-size:11px">același open, același close, max(high) și min(low) identice.</text>
<text x="20.0" y="92.0" fill="#555" style="font-size:11px">weekly: de unde pleacă corecția</text>
<text x="380.0" y="92.0" fill="#555" style="font-size:11px">daily: ultimele 3 candele weekly, desfăcute</text>
<rect x="237.0" y="118.6" width="48.0" height="82.4" fill="#1a5fb4" fill-opacity="0.06" stroke="#1a5fb4" stroke-width="1.2" stroke-dasharray="4 3"/>
<line x1="110.0" y1="190.7" x2="285.0" y2="190.7" stroke="#7b2fbf" stroke-width="1.5" stroke-dasharray="4 3"/>
<line x1="110.0" y1="294.0" x2="285.0" y2="294.0" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="4 3"/>
<line x1="110.0" y1="104.0" x2="285.0" y2="104.0" stroke="#555" stroke-width="1.0" stroke-dasharray="3 3"/>
<text x="24.0" y="117.0" fill="#555" style="font-size:11px">swing high 100.00</text>
<text x="24.0" y="184.7" fill="#7b2fbf" style="font-size:11px;font-weight:bold">PPQ 95.80</text>
<text x="24.0" y="288.0" fill="#188a3e" style="font-size:11px;font-weight:bold">SQ 90.80</text>
<text x="24.0" y="307.0" fill="#188a3e" style="font-size:10px">zona 2, dacă</text>
<text x="24.0" y="319.0" fill="#188a3e" style="font-size:10px">panica merge</text>
<text x="24.0" y="331.0" fill="#188a3e" style="font-size:10px">mai jos</text>
<line x1="132.0" y1="211.4" x2="132.0" y2="242.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="127.5" y="217.6" width="9" height="18.6" fill="#188a3e"/>
<line x1="148.0" y1="188.7" x2="148.0" y2="223.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="143.5" y="194.9" width="9" height="22.7" fill="#188a3e"/>
<line x1="164.0" y1="163.9" x2="164.0" y2="201.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="159.5" y="170.1" width="9" height="24.8" fill="#188a3e"/>
<line x1="180.0" y1="139.1" x2="180.0" y2="176.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="175.5" y="145.3" width="9" height="24.8" fill="#188a3e"/>
<line x1="196.0" y1="114.3" x2="196.0" y2="151.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="191.5" y="120.5" width="9" height="24.8" fill="#188a3e"/>
<line x1="212.0" y1="104.0" x2="212.0" y2="126.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="207.5" y="104.0" width="9" height="16.5" fill="#188a3e"/>
<line x1="228.0" y1="104.0" x2="228.0" y2="132.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="223.5" y="104.0" width="9" height="22.7" fill="#c00"/>
<line x1="244.0" y1="123.6" x2="244.0" y2="156.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="239.5" y="126.7" width="9" height="20.7" fill="#c00"/>
<line x1="260.0" y1="144.3" x2="260.0" y2="177.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="255.5" y="147.4" width="9" height="26.8" fill="#c00"/>
<line x1="276.0" y1="171.1" x2="276.0" y2="195.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="271.5" y="174.2" width="9" height="12.4" fill="#c00"/>
<path d="M121.0,104.0 H116.0 V186.6 H121.0" fill="none" stroke="#c00" stroke-width="1.6"/>
<text x="113.0" y="149.3" fill="#c00" text-anchor="end" style="font-size:11px;font-weight:bold">-4,0 %</text>
<text x="164.0" y="314.0" fill="#c00" style="font-size:11px">corecția de minim 4 % se măsoară aici, pe weekly</text>
<line x1="285.0" y1="118.6" x2="380.0" y2="104.0" stroke="#1a5fb4" stroke-width="1.1" stroke-dasharray="5 3"/>
<line x1="285.0" y1="201.0" x2="380.0" y2="294.0" stroke="#1a5fb4" stroke-width="1.1" stroke-dasharray="5 3"/>
<path d="M285.0,190.7 H332.5 V270.4 H380.0" fill="none" stroke="#aaa" stroke-width="1.0" stroke-dasharray="3 3"/>
<text x="336.5" y="234.6" fill="#999" style="font-size:10px">același</text>
<text x="336.5" y="246.6" fill="#999" style="font-size:10px">preț</text>
<rect x="380.0" y="104.0" width="218.0" height="190.0" fill="#1a5fb4" fill-opacity="0.03" stroke="#1a5fb4" stroke-width="1.2"/>
<rect x="564.0" y="247.8" width="34.0" height="40.6" fill="#188a3e" fill-opacity="0.1" stroke="#188a3e" stroke-width="1.2"/>
<line x1="380.0" y1="270.4" x2="598.0" y2="270.4" stroke="#7b2fbf" stroke-width="1.5" stroke-dasharray="4 3"/>
<line x1="380.0" y1="260.9" x2="598.0" y2="260.9" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="6 3"/>
<line x1="392.0" y1="115.7" x2="392.0" y2="144.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="387.5" y="122.8" width="9" height="14.3" fill="#c00"/>
<line x1="406.0" y1="130.0" x2="406.0" y2="163.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="401.5" y="137.1" width="9" height="19.0" fill="#c00"/>
<line x1="420.0" y1="149.0" x2="420.0" y2="177.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="415.5" y="156.1" width="9" height="14.3" fill="#c00"/>
<line x1="434.0" y1="163.3" x2="434.0" y2="191.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="429.5" y="170.4" width="9" height="14.3" fill="#c00"/>
<line x1="448.0" y1="163.3" x2="448.0" y2="191.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="443.5" y="170.4" width="9" height="14.3" fill="#188a3e"/>
<line x1="462.0" y1="163.3" x2="462.0" y2="196.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="457.5" y="170.4" width="9" height="19.0" fill="#c00"/>
<line x1="476.0" y1="182.3" x2="476.0" y2="215.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="471.5" y="189.5" width="9" height="19.0" fill="#c00"/>
<line x1="490.0" y1="201.4" x2="490.0" y2="230.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="485.5" y="208.5" width="9" height="14.3" fill="#c00"/>
<line x1="504.0" y1="206.1" x2="504.0" y2="230.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="499.5" y="213.3" width="9" height="9.5" fill="#188a3e"/>
<line x1="518.0" y1="206.1" x2="518.0" y2="239.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="513.5" y="213.3" width="9" height="19.0" fill="#c00"/>
<line x1="532.0" y1="225.2" x2="532.0" y2="253.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="527.5" y="232.3" width="9" height="14.3" fill="#c00"/>
<line x1="546.0" y1="239.5" x2="546.0" y2="268.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="541.5" y="246.6" width="9" height="14.3" fill="#c00"/>
<line x1="560.0" y1="253.8" x2="560.0" y2="272.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="555.5" y="260.9" width="9" height="4.8" fill="#c00"/>
<line x1="574.0" y1="260.9" x2="574.0" y2="282.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="569.5" y="265.7" width="9" height="9.5" fill="#c00"/>
<line x1="588.0" y1="253.8" x2="588.0" y2="277.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="583.5" y="260.9" width="9" height="14.3" fill="#188a3e"/>
<text x="608.0" y="274.4" fill="#7b2fbf" style="font-size:10px;font-weight:bold">PPQ 95.80</text>
<text x="608.0" y="286.4" fill="#7b2fbf" style="font-size:10px">același nivel,</text>
<text x="608.0" y="298.4" fill="#7b2fbf" style="font-size:10px">văzut de aproape</text>
<text x="608.0" y="252.9" fill="#188a3e" style="font-size:10px;font-weight:bold">intrare 96.00</text>
<line x1="574.0" y1="286.3" x2="574.0" y2="308.0" stroke="#0a7f9e" stroke-width="1"/>
<text x="568.0" y="322.0" fill="#0a7f9e" text-anchor="middle" style="font-size:11px;font-weight:bold">BIM: aici se oprește vânzarea</text>
<text x="568.0" y="336.0" fill="#0a7f9e" text-anchor="middle" style="font-size:10px">(fundul e la 0,26 % de PPQ)</text>
<text x="20.0" y="352.0" fill="#555" style="font-size:11px">Pe weekly nu vezi unde s-a oprit căderea; pe daily, da — de aceea intri de aici.</text>
</svg>

After

Width:  |  Height:  |  Size: 7.9 KiB

View File

@@ -0,0 +1,117 @@
"""ATMI — Pasul 1: PPQ și SQ, calculați din trimestrul precedent.
Un singur grafic daily care acoperă sfârșitul trimestrului precedent (zona
gri) și începutul celui nou. Din H/L/C-ul trimestrului precedent ies, prin
formula standard de pivot point, cele două niveluri pe care ATMI cumpără:
PPQ (pivotul trimestrial) și SQ (suportul trimestrial, S1). Liniile se
prelungesc peste trimestrul nou — acolo le folosești.
Cifrele PPQ/SQ sunt COMPLETARE PROPRIE: cursul spune explicit că nu dă
valorile lor. Formula e cea confirmată „1 la 1" în material. Aici sunt
calculate în cod din seria desenată, nu scrise de mână.
Rulează: python3 gen/strategii/atmi_pivoti.py
"""
import sys
from pathlib import Path
sys.path.insert(0, "/workspace/atm-curs-dl")
from svg_candles import Chart, Level, Mark, Zone, Arrow, from_closes # noqa: E402
OUT = Path(__file__).resolve().parent / "atmi_pivoti.svg"
GRAY, RED, GREEN, BLUE, ORANGE, INK = "#777", "#c00", "#188a3e", "#1a5fb4", "#b06000", "#333"
PURPLE = "#7b2fbf"
# --- seria: 22 de bare din trimestrul precedent + 12 din cel nou -----------
# Trimestrul precedent trebuie să aibă H = 100.80, L = 90.40, C = 96.20.
Q_PREV = [95.40, 94.10, 93.00, 92.10, 90.90, 90.70, 92.20, 93.60, 95.00, 96.40,
97.90, 99.20, 100.40, 99.80, 98.60, 97.40, 96.20, 95.10, 95.90, 96.80,
97.30, 96.20]
Q_NOU = [97.00, 97.70, 98.40, 99.00, 99.60, 100.00, 99.20, 98.30, 97.40, 96.90,
96.50, 96.20]
CLOSES = Q_PREV + Q_NOU
NP = len(Q_PREV)
assert len(CLOSES) == 34
wicks = [(0.25, 0.25)] * len(CLOSES)
wicks[4] = (0.20, 0.50) # minimul trimestrului precedent: 90.90 - 0.50 = 90.40
wicks[12] = (0.40, 0.20) # maximul trimestrului precedent: 100.40 + 0.40 = 100.80
wicks[NP - 1] = (0.20, 0.20)
wicks[NP] = (0.25, 0.00) # prima bară a trimestrului nou pleacă de pe close-ul C
wicks[NP + 5] = (0.00, 0.25) # swing high-ul trimestrului nou: exact 100.00
wicks[NP + 6] = (0.00, 0.25) # nicio bară de după nu depășește swing high-ul
wicks[-3] = (0.20, 0.00)
wicks[-2] = (0.20, 0.00)
wicks[-1] = (0.15, 0.20) # low-ul ultimei bare: 96.20 - 0.20 = 96.00
cds = from_closes(CLOSES, wicks=wicks,
vols=[40 + (i * 7) % 33 for i in range(len(CLOSES))], start=96.00)
# --- pivoții, calculați din seria desenată ---------------------------------
H = round(max(c.h for c in cds[:NP]), 2)
L = round(min(c.l for c in cds[:NP]), 2)
C = round(cds[NP - 1].c, 2)
PP = round((H + L + C) / 3, 2)
S1 = round(2 * PP - H, 2)
R1 = round(2 * PP - L, 2)
assert (H, L, C) == (100.80, 90.40, 96.20), (H, L, C)
assert PP == 95.80, PP
assert S1 == 90.80, S1
assert R1 == 101.20, R1
assert S1 < PP < R1
assert abs(S1 - L) > 0.3, "S1 a ieșit chiar pe low — ar părea o coincidență, nu un calcul"
# ce afirmă textul capitolului despre trimestrul NOU
SWING = round(max(c.h for c in cds[NP:]), 2)
FUND = round(min(c.l for c in cds[NP:]), 2)
assert abs(SWING - 100.00) < 1e-9, SWING
ZONA = (PP - 0.30, PP + 0.30) # banda de cumpărare din jurul pivotului
assert abs(FUND - 96.00) < 1e-9, FUND
assert ZONA[0] <= FUND <= ZONA[1], (FUND, ZONA) # ultima bară intră în zona PPQ
assert abs((SWING - 96.00) / SWING * 100 - 4.0) < 0.05 # corecție de exact 4,0 %
assert all(c.l > S1 for c in cds[NP:]), "trimestrul nou nu trebuie să atingă SQ"
levels = [
Level(PP, f"PPQ {PP:.2f} — zona 1", PURPLE),
Level(S1, f"SQ {S1:.2f} — zona 2", GREEN),
]
marks = [
Mark(12, f"H {H:.2f}", INK, "above"),
Mark(4, f"L {L:.2f}", INK, "below"),
Mark(NP - 1, f"C {C:.2f}", INK, "above", dy=-16),
Mark(NP + 5, f"swing high {SWING:.2f}", RED, "above"),
Mark(len(cds) - 4, "corecție 4,0 % — prețul intră în zona PPQ: treci la pasul 2",
PURPLE, "below", dy=34),
]
arrows = []
zones = [Zone(0, NP - 1, "", GRAY), Zone(NP, len(cds) - 1, "", BLUE)]
ch = Chart(candles=cds, levels=levels, marks=marks, zones=zones, arrows=arrows,
scale=13.0, gap=16, body_w=9, left=52, width=720, vol_h=60, top=124,
label_gap=54,
caption="Cifrele PPQ/SQ sunt completarea mea: cursul dă regula, nu valorile. "
"Formula e cea standard, confirmată în material pentru pivoți.")
svg = ch.render()
# formula, scrisă cu cifrele desenului, ca să nu rămână o regulă abstractă
form = [f"PP = (H + L + C) / 3 = ({H:.2f} + {L:.2f} + {C:.2f}) / 3 = {PP:.2f} → PPQ",
f"S1 = 2 x PP - H = 2 x {PP:.2f} - {H:.2f} = {S1:.2f} → SQ",
f"R1 = 2 x PP - L = 2 x {PP:.2f} - {L:.2f} = {R1:.2f}"]
box = [f'<text x="24" y="22" fill="{INK}" style="font-weight:bold">'
f'SPY — daily: pivoții trimestrului nou, calculați din trimestrul precedent</text>',
f'<rect x="24" y="34" width="430" height="54" fill="#f4f4f8" stroke="#ccc"/>',
f'<text x="46" y="110" fill="{GRAY}" style="font-size:11px;font-weight:bold">'
f'trimestrul precedent</text>',
f'<text x="446" y="110" fill="{BLUE}" style="font-size:11px;font-weight:bold">'
f'trimestrul nou: aici tranzacționezi</text>']
for i, s in enumerate(form):
box.append(f'<text x="34" y="{50 + i * 15}" fill="{INK}" '
f'style="font-family:monospace;font-size:11px">{s}</text>')
i = svg.index(">") + 1
svg = svg[:i] + "\n " + "\n ".join(box) + svg[i:]
assert "\n\n" not in svg
assert ".md:" not in svg
OUT.write_text(svg)
print(f"scris {OUT.name}: H {H} L {L} C {C} -> PPQ {PP}, SQ {S1}, R1 {R1}")

View File

@@ -0,0 +1,125 @@
<svg viewBox="0 0 720 401" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif">
<text x="24" y="22" fill="#333" style="font-weight:bold">SPY — daily: pivoții trimestrului nou, calculați din trimestrul precedent</text>
<rect x="24" y="34" width="430" height="54" fill="#f4f4f8" stroke="#ccc"/>
<text x="46" y="110" fill="#777" style="font-size:11px;font-weight:bold">trimestrul precedent</text>
<text x="446" y="110" fill="#1a5fb4" style="font-size:11px;font-weight:bold">trimestrul nou: aici tranzacționezi</text>
<text x="34" y="50" fill="#333" style="font-family:monospace;font-size:11px">PP = (H + L + C) / 3 = (100.80 + 90.40 + 96.20) / 3 = 95.80 → PPQ</text>
<text x="34" y="65" fill="#333" style="font-family:monospace;font-size:11px">S1 = 2 x PP - H = 2 x 95.80 - 100.80 = 90.80 → SQ</text>
<text x="34" y="80" fill="#333" style="font-family:monospace;font-size:11px">R1 = 2 x PP - L = 2 x 95.80 - 90.40 = 101.20</text>
<rect x="42.5" y="116.0" width="355.0" height="151.2" fill="#777" fill-opacity="0.08" stroke="#777" stroke-width="1"/>
<rect x="394.5" y="126.4" width="195.0" height="68.0" fill="#1a5fb4" fill-opacity="0.08" stroke="#1a5fb4" stroke-width="1"/>
<line x1="24" y1="189.0" x2="706" y2="189.0" stroke="#7b2fbf" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="692" y="183.0" fill="#7b2fbf" text-anchor="end">PPQ 95.80 — zona 1</text>
<line x1="24" y1="254.0" x2="706" y2="254.0" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="692" y="248.0" fill="#188a3e" text-anchor="end">SQ 90.80 — zona 2</text>
<line x1="52.0" y1="183.2" x2="52.0" y2="197.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="47.5" y="186.4" width="9" height="7.8" fill="#c00"/>
<line x1="68.0" y1="191.0" x2="68.0" y2="214.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="63.5" y="194.2" width="9" height="16.9" fill="#c00"/>
<line x1="84.0" y1="207.9" x2="84.0" y2="228.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="79.5" y="211.1" width="9" height="14.3" fill="#c00"/>
<line x1="100.0" y1="222.2" x2="100.0" y2="240.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="95.5" y="225.4" width="9" height="11.7" fill="#c00"/>
<line x1="116.0" y1="234.5" x2="116.0" y2="259.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="111.5" y="237.1" width="9" height="15.6" fill="#c00"/>
<line x1="132.0" y1="249.5" x2="132.0" y2="258.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="127.5" y="252.7" width="9" height="2.6" fill="#c00"/>
<line x1="148.0" y1="232.6" x2="148.0" y2="258.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="143.5" y="235.8" width="9" height="19.5" fill="#188a3e"/>
<line x1="164.0" y1="214.4" x2="164.0" y2="239.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="159.5" y="217.6" width="9" height="18.2" fill="#188a3e"/>
<line x1="180.0" y1="196.2" x2="180.0" y2="220.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="175.5" y="199.4" width="9" height="18.2" fill="#188a3e"/>
<line x1="196.0" y1="178.0" x2="196.0" y2="202.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="191.5" y="181.2" width="9" height="18.2" fill="#188a3e"/>
<line x1="212.0" y1="158.5" x2="212.0" y2="184.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="207.5" y="161.7" width="9" height="19.5" fill="#188a3e"/>
<line x1="228.0" y1="141.6" x2="228.0" y2="165.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="223.5" y="144.8" width="9" height="16.9" fill="#188a3e"/>
<line x1="244.0" y1="124.0" x2="244.0" y2="147.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="239.5" y="129.2" width="9" height="15.6" fill="#188a3e"/>
<line x1="260.0" y1="126.0" x2="260.0" y2="140.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="255.5" y="129.2" width="9" height="7.8" fill="#c00"/>
<line x1="276.0" y1="133.8" x2="276.0" y2="155.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="271.5" y="137.0" width="9" height="15.6" fill="#c00"/>
<line x1="292.0" y1="149.4" x2="292.0" y2="171.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="287.5" y="152.6" width="9" height="15.6" fill="#c00"/>
<line x1="308.0" y1="165.0" x2="308.0" y2="187.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="303.5" y="168.2" width="9" height="15.6" fill="#c00"/>
<line x1="324.0" y1="180.6" x2="324.0" y2="201.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="319.5" y="183.8" width="9" height="14.3" fill="#c00"/>
<line x1="340.0" y1="184.5" x2="340.0" y2="201.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="335.5" y="187.7" width="9" height="10.4" fill="#188a3e"/>
<line x1="356.0" y1="172.8" x2="356.0" y2="191.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="351.5" y="176.0" width="9" height="11.7" fill="#188a3e"/>
<line x1="372.0" y1="166.3" x2="372.0" y2="179.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="367.5" y="169.5" width="9" height="6.5" fill="#188a3e"/>
<line x1="388.0" y1="166.9" x2="388.0" y2="186.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="383.5" y="169.5" width="9" height="14.3" fill="#c00"/>
<line x1="404.0" y1="170.2" x2="404.0" y2="183.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="399.5" y="173.4" width="9" height="10.4" fill="#188a3e"/>
<line x1="420.0" y1="161.1" x2="420.0" y2="176.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="415.5" y="164.3" width="9" height="9.1" fill="#188a3e"/>
<line x1="436.0" y1="152.0" x2="436.0" y2="167.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="431.5" y="155.2" width="9" height="9.1" fill="#188a3e"/>
<line x1="452.0" y1="144.2" x2="452.0" y2="158.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="447.5" y="147.4" width="9" height="7.8" fill="#188a3e"/>
<line x1="468.0" y1="136.4" x2="468.0" y2="150.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="463.5" y="139.6" width="9" height="7.8" fill="#188a3e"/>
<line x1="484.0" y1="134.4" x2="484.0" y2="142.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="479.5" y="134.4" width="9" height="5.2" fill="#188a3e"/>
<line x1="500.0" y1="134.4" x2="500.0" y2="148.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="495.5" y="134.4" width="9" height="10.4" fill="#c00"/>
<line x1="516.0" y1="141.6" x2="516.0" y2="159.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="511.5" y="144.8" width="9" height="11.7" fill="#c00"/>
<line x1="532.0" y1="153.3" x2="532.0" y2="171.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="527.5" y="156.5" width="9" height="11.7" fill="#c00"/>
<line x1="548.0" y1="165.6" x2="548.0" y2="174.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="543.5" y="168.2" width="9" height="6.5" fill="#c00"/>
<line x1="564.0" y1="172.1" x2="564.0" y2="179.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="559.5" y="174.7" width="9" height="5.2" fill="#c00"/>
<line x1="580.0" y1="178.0" x2="580.0" y2="186.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="575.5" y="179.9" width="9" height="3.9" fill="#c00"/>
<line x1="24" y1="359.2" x2="706" y2="359.2" stroke="#888"/>
<rect x="47.5" y="325.9" width="9" height="33.3" fill="#c00" opacity="0.55"/>
<rect x="63.5" y="320.0" width="9" height="39.2" fill="#c00" opacity="0.55"/>
<rect x="79.5" y="314.2" width="9" height="45.0" fill="#c00" opacity="0.55"/>
<rect x="95.5" y="308.4" width="9" height="50.8" fill="#c00" opacity="0.55"/>
<rect x="111.5" y="302.5" width="9" height="56.7" fill="#c00" opacity="0.55"/>
<rect x="127.5" y="324.2" width="9" height="35.0" fill="#c00" opacity="0.55"/>
<rect x="143.5" y="318.4" width="9" height="40.8" fill="#188a3e" opacity="0.55"/>
<rect x="159.5" y="312.5" width="9" height="46.7" fill="#188a3e" opacity="0.55"/>
<rect x="175.5" y="306.7" width="9" height="52.5" fill="#188a3e" opacity="0.55"/>
<rect x="191.5" y="300.9" width="9" height="58.3" fill="#188a3e" opacity="0.55"/>
<rect x="207.5" y="322.5" width="9" height="36.7" fill="#188a3e" opacity="0.55"/>
<rect x="223.5" y="316.7" width="9" height="42.5" fill="#188a3e" opacity="0.55"/>
<rect x="239.5" y="310.9" width="9" height="48.3" fill="#188a3e" opacity="0.55"/>
<rect x="255.5" y="305.0" width="9" height="54.2" fill="#c00" opacity="0.55"/>
<rect x="271.5" y="299.2" width="9" height="60.0" fill="#c00" opacity="0.55"/>
<rect x="287.5" y="320.9" width="9" height="38.3" fill="#c00" opacity="0.55"/>
<rect x="303.5" y="315.0" width="9" height="44.2" fill="#c00" opacity="0.55"/>
<rect x="319.5" y="309.2" width="9" height="50.0" fill="#c00" opacity="0.55"/>
<rect x="335.5" y="303.4" width="9" height="55.8" fill="#188a3e" opacity="0.55"/>
<rect x="351.5" y="325.0" width="9" height="34.2" fill="#188a3e" opacity="0.55"/>
<rect x="367.5" y="319.2" width="9" height="40.0" fill="#188a3e" opacity="0.55"/>
<rect x="383.5" y="313.4" width="9" height="45.8" fill="#c00" opacity="0.55"/>
<rect x="399.5" y="307.5" width="9" height="51.7" fill="#188a3e" opacity="0.55"/>
<rect x="415.5" y="301.7" width="9" height="57.5" fill="#188a3e" opacity="0.55"/>
<rect x="431.5" y="323.4" width="9" height="35.8" fill="#188a3e" opacity="0.55"/>
<rect x="447.5" y="317.5" width="9" height="41.7" fill="#188a3e" opacity="0.55"/>
<rect x="463.5" y="311.7" width="9" height="47.5" fill="#188a3e" opacity="0.55"/>
<rect x="479.5" y="305.9" width="9" height="53.3" fill="#188a3e" opacity="0.55"/>
<rect x="495.5" y="300.0" width="9" height="59.2" fill="#c00" opacity="0.55"/>
<rect x="511.5" y="321.7" width="9" height="37.5" fill="#c00" opacity="0.55"/>
<rect x="527.5" y="315.9" width="9" height="43.3" fill="#c00" opacity="0.55"/>
<rect x="543.5" y="310.0" width="9" height="49.2" fill="#c00" opacity="0.55"/>
<rect x="559.5" y="304.2" width="9" height="55.0" fill="#c00" opacity="0.55"/>
<rect x="575.5" y="325.9" width="9" height="33.3" fill="#c00" opacity="0.55"/>
<text x="24" y="293.2" fill="#555">volum</text>
<text x="244.0" y="114.0" fill="#333" text-anchor="middle" style="font-weight:bold">H 100.80</text>
<text x="116.0" y="273.2" fill="#333" text-anchor="middle" style="font-weight:bold">L 90.40</text>
<text x="388.0" y="140.9" fill="#333" text-anchor="middle" style="font-weight:bold">C 96.20</text>
<text x="484.0" y="124.4" fill="#c00" text-anchor="middle" style="font-weight:bold">swing high 100.00</text>
<text x="532.0" y="225.5" fill="#7b2fbf" text-anchor="middle" style="font-weight:bold">corecție 4,0 % — prețul intră în zona PPQ: treci la pasul 2</text>
<text x="24" y="389" fill="#555">Cifrele PPQ/SQ sunt completarea mea: cursul dă regula, nu valorile. Formula e cea standard, confirmată în material pentru pivoți.</text>
</svg>

After

Width:  |  Height:  |  Size: 10 KiB

View File

@@ -0,0 +1,134 @@
#!/usr/bin/env python3
"""ATMI — Pasul 6: ieșirea la +10 %, cash, apoi reinvestirea integrală.
Nu e un grafic de preț: e ciclul banilor. Trei cicluri, fiecare cu aceeași
regulă — ieși cu TOATĂ poziția la +10 %, banii stau în cash până la
următorul trigger valid, iar acolo intră înapoi integral, plus contribuția
nouă. Coloana din dreapta arată ce iese dacă reinvestești doar contribuțiile
și lași profitul deoparte: aceeași sumă pusă, mai puțin la final.
Contribuția de 600 $/trimestru e cifra cursului („1 unitate SPY"); ținta de
+10 % e regula lui. Suma finală e calculată aici, nu preluată din backtest —
backtest-ul cursului (~16.300 $ → ~52-53.000 $ în 20 de ani) are alt
orizont și e citat în text, nu desenat.
Rulează: python3 gen/strategii/atmi_reinvestire.py
"""
from pathlib import Path
OUT = Path(__file__).with_suffix(".svg")
W = 700
CONTRIB, TINTA = 600.0, 0.10
N = 3
GREEN, RED, BLUE, INK, GRAY, PURPLE = "#188a3e", "#c00", "#1a5fb4", "#333", "#777", "#7b2fbf"
# --- cele două scenarii ----------------------------------------------------
cicluri, capital = [], 0.0
for i in range(N):
intrat = round(capital + CONTRIB, 2)
iesit = round(intrat * (1 + TINTA), 2)
cicluri.append((i + 1, intrat, iesit))
capital = iesit
fara = round(N * CONTRIB * (1 + TINTA), 2) # fiecare contribuție câștigă 10 % o dată
pus = round(N * CONTRIB, 2)
assert cicluri[0] == (1, 600.00, 660.00), cicluri[0]
assert cicluri[1] == (2, 1260.00, 1386.00), cicluri[1]
assert cicluri[2] == (3, 1986.00, 2184.60), cicluri[2]
assert fara == 1980.00 and pus == 1800.00
CASTIG = round(cicluri[-1][2] - fara, 2)
assert CASTIG == 204.60, CASTIG
# fiecare ciclu intră cu exact ce a ieșit din precedentul plus contribuția
for (_, intr, _), (_, _, ies) in zip(cicluri[1:], cicluri):
assert round(intr - ies, 2) == CONTRIB
assert all(round(ies / intr, 3) == 1.100 for _, intr, ies in cicluri)
# --- desen -----------------------------------------------------------------
out, LABELS = [], []
BASE_Y = 250 # linia de zero a coloanelor
PXPU = 0.072 # px per dolar
COL_W, X0, STEP = 46, 60, 190
assert cicluri[-1][2] * PXPU < BASE_Y - 80, "coloana cea mai înaltă iese din desen"
def text(x, y, s, fill=INK, anchor="start", bold=False, size=12):
st = f"font-size:{size}px" + (";font-weight:bold" if bold else "")
a = f' text-anchor="{anchor}"' if anchor != "start" else ""
w = len(s) * (size * 0.52)
x0 = x if anchor == "start" else (x - w / 2 if anchor == "middle" else x - w)
assert 2 <= x0 and x0 + w <= W - 2, f"text iese din panză: {s!r} ({x0:.0f}..{x0 + w:.0f})"
LABELS.append((x0, x0 + w, y, s))
out.append(f'<text x="{x:.1f}" y="{y:.1f}" fill="{fill}"{a} style="{st}">{s}</text>')
def bar(x, val, color, label, sub):
h = val * PXPU
out.append(f'<rect x="{x:.1f}" y="{BASE_Y - h:.1f}" width="{COL_W}" height="{h:.1f}" '
f'fill="{color}" fill-opacity="0.85"/>')
text(x + COL_W / 2, BASE_Y - h - 8, label, fill=color, anchor="middle", bold=True, size=11)
text(x + COL_W / 2, BASE_Y + 15, sub, fill=GRAY, anchor="middle", size=10)
out.append('<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" '
f'markerHeight="7" orient="auto"><path d="M0,0 L10,5 L0,10 z" fill="{BLUE}"/></marker>'
'</defs>')
text(20, 22, "Ciclul ATMI: ieși cu tot la +10 %, stai în cash, reintri cu tot plus contribuția",
bold=True, size=13)
text(20, 40, f"Contribuție {CONTRIB:.0f} $ la fiecare trigger valid; ținta +10 % pe poziție.",
fill="#555", size=11)
for i, (nr, intrat, iesit) in enumerate(cicluri):
xa = X0 + i * STEP
xb = xa + COL_W + 26
text(xa, 72, f"ciclul {nr}", fill=INK, bold=True, size=12)
bar(xa, intrat, BLUE, f"{intrat:,.0f} $".replace(",", "."), "intri cu tot")
bar(xb, iesit, GREEN, f"{iesit:,.2f} $".replace(",", "x").replace(".", ",").replace("x", "."),
"ieși la +10 %")
# săgeata dintre intrare și ieșire (ce face trade-ul)
out.append(f'<line x1="{xa + COL_W + 4:.1f}" y1="{BASE_Y - 30:.1f}" x2="{xb - 6:.1f}" '
f'y2="{BASE_Y - 30:.1f}" stroke="{GREEN}" stroke-width="1.4" '
f'marker-end="url(#ar)"/>')
if i + 1 < len(cicluri):
# săgeata spre ciclul următor: cash + contribuție nouă
xn = X0 + (i + 1) * STEP
y = BASE_Y + 46
out.append(f'<path d="M{xb + COL_W / 2:.1f},{BASE_Y + 22:.1f} V{y:.1f} '
f'H{xn + COL_W / 2:.1f} V{BASE_Y + 22:.1f}" fill="none" stroke="{BLUE}" '
f'stroke-width="1.4" stroke-dasharray="4 3" marker-end="url(#ar)"/>')
text((xb + xn) / 2 + COL_W / 2, y + 16,
f"cash, apoi + {CONTRIB:.0f} $ nou", fill=BLUE,
anchor="middle", size=11, bold=True)
out.append(f'<line x1="24" y1="{BASE_Y:.1f}" x2="{W - 24}" y2="{BASE_Y:.1f}" stroke="#bbb"/>')
# comparația de la final
yc = BASE_Y + 92
out.append(f'<rect x="24" y="{yc - 16:.0f}" width="{W - 48}" height="56" fill="#f6f6f9" '
f'stroke="#ccc"/>')
text(34, yc, f"Ai pus în total {pus:,.0f} $".replace(",", ".") + ", în trei contribuții egale.",
fill=INK, size=11, bold=True)
text(34, yc + 17, f"Cu reinvestire integrală: "
f"{cicluri[-1][2]:,.2f} $".replace(",", "x").replace(".", ",").replace("x", ".")
+ f" · dacă lași profitul deoparte: {fara:,.0f} $".replace(",", ".")
+ f" · diferența: {CASTIG:,.2f} $".replace(",", "x").replace(".", ",").replace("x", "."),
fill=INK, size=11)
text(34, yc + 34, "Cifrele astea sunt calculul meu pe trei cicluri, nu backtest-ul cursului.",
fill=GRAY, size=10)
H = yc + 56
for i in range(len(LABELS)):
for j in range(i + 1, len(LABELS)):
xa0, xa1, ya, sa = LABELS[i]
xb0, xb1, yb_, sb = LABELS[j]
assert not (abs(ya - yb_) < 12 and xa0 < xb1 - 4 and xb0 < xa1 - 4), \
f"etichete suprapuse: {sa!r} / {sb!r}"
assert 0 < LABELS[i][2] < H, f"etichetă în afara înălțimii: {LABELS[i][3]!r}"
svg = (f'<svg viewBox="0 0 {W} {H:.0f}" xmlns="http://www.w3.org/2000/svg" '
f'style="width:100%;height:auto;font:12px sans-serif">\n ' + "\n ".join(out) + "\n</svg>")
assert "\n\n" not in svg and ".md:" not in svg
OUT.write_text(svg, encoding="utf-8")
print(" | ".join(f"c{n}: {a:.0f} -> {b:.2f}" for n, a, b in cicluri)
+ f" | fără reinvestire {fara:.0f} | diferență {CASTIG:.2f} | scris {OUT.name} ({W}x{H:.0f})")

View File

@@ -0,0 +1,38 @@
<svg viewBox="0 0 700 398" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif">
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto"><path d="M0,0 L10,5 L0,10 z" fill="#1a5fb4"/></marker></defs>
<text x="20.0" y="22.0" fill="#333" style="font-size:13px;font-weight:bold">Ciclul ATMI: ieși cu tot la +10 %, stai în cash, reintri cu tot plus contribuția</text>
<text x="20.0" y="40.0" fill="#555" style="font-size:11px">Contribuție 600 $ la fiecare trigger valid; ținta +10 % pe poziție.</text>
<text x="60.0" y="72.0" fill="#333" style="font-size:12px;font-weight:bold">ciclul 1</text>
<rect x="60.0" y="206.8" width="46" height="43.2" fill="#1a5fb4" fill-opacity="0.85"/>
<text x="83.0" y="198.8" fill="#1a5fb4" text-anchor="middle" style="font-size:11px;font-weight:bold">600 $</text>
<text x="83.0" y="265.0" fill="#777" text-anchor="middle" style="font-size:10px">intri cu tot</text>
<rect x="132.0" y="202.5" width="46" height="47.5" fill="#188a3e" fill-opacity="0.85"/>
<text x="155.0" y="194.5" fill="#188a3e" text-anchor="middle" style="font-size:11px;font-weight:bold">660,00 $</text>
<text x="155.0" y="265.0" fill="#777" text-anchor="middle" style="font-size:10px">ieși la +10 %</text>
<line x1="110.0" y1="220.0" x2="126.0" y2="220.0" stroke="#188a3e" stroke-width="1.4" marker-end="url(#ar)"/>
<path d="M155.0,272.0 V296.0 H273.0 V272.0" fill="none" stroke="#1a5fb4" stroke-width="1.4" stroke-dasharray="4 3" marker-end="url(#ar)"/>
<text x="214.0" y="312.0" fill="#1a5fb4" text-anchor="middle" style="font-size:11px;font-weight:bold">cash, apoi + 600 $ nou</text>
<text x="250.0" y="72.0" fill="#333" style="font-size:12px;font-weight:bold">ciclul 2</text>
<rect x="250.0" y="159.3" width="46" height="90.7" fill="#1a5fb4" fill-opacity="0.85"/>
<text x="273.0" y="151.3" fill="#1a5fb4" text-anchor="middle" style="font-size:11px;font-weight:bold">1.260 $</text>
<text x="273.0" y="265.0" fill="#777" text-anchor="middle" style="font-size:10px">intri cu tot</text>
<rect x="322.0" y="150.2" width="46" height="99.8" fill="#188a3e" fill-opacity="0.85"/>
<text x="345.0" y="142.2" fill="#188a3e" text-anchor="middle" style="font-size:11px;font-weight:bold">1.386,00 $</text>
<text x="345.0" y="265.0" fill="#777" text-anchor="middle" style="font-size:10px">ieși la +10 %</text>
<line x1="300.0" y1="220.0" x2="316.0" y2="220.0" stroke="#188a3e" stroke-width="1.4" marker-end="url(#ar)"/>
<path d="M345.0,272.0 V296.0 H463.0 V272.0" fill="none" stroke="#1a5fb4" stroke-width="1.4" stroke-dasharray="4 3" marker-end="url(#ar)"/>
<text x="404.0" y="312.0" fill="#1a5fb4" text-anchor="middle" style="font-size:11px;font-weight:bold">cash, apoi + 600 $ nou</text>
<text x="440.0" y="72.0" fill="#333" style="font-size:12px;font-weight:bold">ciclul 3</text>
<rect x="440.0" y="107.0" width="46" height="143.0" fill="#1a5fb4" fill-opacity="0.85"/>
<text x="463.0" y="99.0" fill="#1a5fb4" text-anchor="middle" style="font-size:11px;font-weight:bold">1.986 $</text>
<text x="463.0" y="265.0" fill="#777" text-anchor="middle" style="font-size:10px">intri cu tot</text>
<rect x="512.0" y="92.7" width="46" height="157.3" fill="#188a3e" fill-opacity="0.85"/>
<text x="535.0" y="84.7" fill="#188a3e" text-anchor="middle" style="font-size:11px;font-weight:bold">2.184,60 $</text>
<text x="535.0" y="265.0" fill="#777" text-anchor="middle" style="font-size:10px">ieși la +10 %</text>
<line x1="490.0" y1="220.0" x2="506.0" y2="220.0" stroke="#188a3e" stroke-width="1.4" marker-end="url(#ar)"/>
<line x1="24" y1="250.0" x2="676" y2="250.0" stroke="#bbb"/>
<rect x="24" y="326" width="652" height="56" fill="#f6f6f9" stroke="#ccc"/>
<text x="34.0" y="342.0" fill="#333" style="font-size:11px;font-weight:bold">Ai pus în total 1.800 $, în trei contribuții egale.</text>
<text x="34.0" y="359.0" fill="#333" style="font-size:11px">Cu reinvestire integrală: 2.184,60 $ · dacă lași profitul deoparte: 1.980 $ · diferența: 204,60 $</text>
<text x="34.0" y="376.0" fill="#777" style="font-size:10px">Cifrele astea sunt calculul meu pe trei cicluri, nu backtest-ul cursului.</text>
</svg>

After

Width:  |  Height:  |  Size: 4.2 KiB

100
gen/strategii/atmi_risc.py Normal file
View File

@@ -0,0 +1,100 @@
"""ATMI — Pasul 5: ce înseamnă „fără stop-loss", desenat.
Același trade ca în restul capitolului (intrare 96.00, țintă +10 % = 105.60),
dar arătând drumul, nu doar capetele: între intrare și țintă poziția trece
printr-un drawdown — pierdere flotantă — de 20 % pe poziție, fără ca nimic
să te scoată din ea. Cifra de 20-30 % pe poziție fără levier e a cursului
(COVID 2020, 2018); traseul barelor e construit de mine.
Coloana din dreapta traduce aceeași cădere de 20 % a indicelui în pierdere
pe poziție, pe trei variante de instrument — calculul e în cod.
Rulează: python3 gen/strategii/atmi_risc.py
"""
import sys
from pathlib import Path
sys.path.insert(0, "/workspace/atm-curs-dl")
from svg_candles import Chart, Level, Mark, from_closes # noqa: E402
OUT = Path(__file__).resolve().parent / "atmi_risc.svg"
GRAY, RED, GREEN, BLUE, INK, PURPLE = "#777", "#c00", "#188a3e", "#1a5fb4", "#333", "#7b2fbf"
ENTRY, TP, PPQ = 96.00, 105.60, 95.80
DD_PCT = 20.0 # drawdown pe poziție, fără levier
FUND = round(ENTRY * (1 - DD_PCT / 100), 2) # 76.80
# 3 bare de context + intrarea + 14 bare în jos + 17 bare de revenire
CLOSES = ([98.20, 97.10, 96.40, ENTRY]
+ [94.60, 92.80, 90.90, 89.40, 90.70, 88.60, 86.30, 84.40,
85.60, 83.10, 81.00, 79.20, 78.10, FUND]
+ [78.40, 80.60, 82.90, 84.50, 86.80, 88.40, 90.10, 92.30,
94.00, ENTRY, 97.80, 99.40, 100.90, 102.20, 103.40, 104.50, TP])
ENTRY_I, FUND_I, BE_I, TP_I = 3, 17, 27, len(CLOSES) - 1
assert CLOSES[ENTRY_I] == ENTRY and CLOSES[FUND_I] == FUND
assert CLOSES[BE_I] == ENTRY and CLOSES[TP_I] == TP
wicks = [(0.35, 0.35)] * len(CLOSES)
wicks[ENTRY_I] = (0.30, 0.10)
wicks[FUND_I] = (0.30, 0.00) # fundul e exact -20 %
wicks[FUND_I + 1] = (0.35, 0.00) # nicio bară de după nu coboară sub fund
wicks[TP_I] = (0.00, 0.35) # ținta e exact maximul seriei
cds = from_closes(CLOSES, wicks=wicks, vols=[44 + (i * 11) % 41 for i in range(len(CLOSES))],
start=98.90)
# --- ce susține textul -----------------------------------------------------
fund = round(min(c.l for c in cds), 2)
assert fund == FUND, fund
assert round((ENTRY - fund) / ENTRY * 100, 1) == DD_PCT
assert round(max(c.h for c in cds), 2) == TP
assert round(TP / ENTRY, 3) == 1.100
assert cds[FUND_I].l == fund and all(c.l >= fund for c in cds)
assert FUND < PPQ, "fundul trebuie să fie sub pivotul pe care ai cumpărat"
assert BE_I > FUND_I and CLOSES[BE_I] == ENTRY, "lipsește revenirea pe zero"
DURATA_JOS = BE_I - ENTRY_I # câte bare stai sub prețul de intrare
assert DURATA_JOS == 24, DURATA_JOS
# aceeași cădere de 20 % pe indice, tradusă pe trei instrumente
VARIANTE = [("ETF simplu (SPY)", 1), ("ETF cu levier 2x", 2), ("ETF cu levier 3x (SPXL)", 3)]
PIERDERI = [(n, round(DD_PCT * k, 1)) for n, k in VARIANTE]
assert PIERDERI[-1][1] == 60.0, PIERDERI
COVID = 34.0 # SPY în 2020, cifra cursului
assert round(COVID * 3, 1) > 100.0, "3x pe -34 % trebuie să treacă de -100 %"
levels = [
Level(TP, f"TP +10 % = {TP:.2f}", BLUE),
Level(ENTRY, f"intrare {ENTRY:.2f}", GREEN, label_at="right"),
Level(fund, f"fund {fund:.2f} = -{DD_PCT:.0f} % pe poziție", RED, label_at="left"),
]
marks = [
Mark(FUND_I, f"-{DD_PCT:.0f} %: nimic nu te scoate", RED, "below"),
Mark(BE_I, "abia aici ești pe zero", GRAY, "above", dy=-22),
Mark(TP_I, "TP", BLUE, "below"),
]
ch = Chart(candles=cds, levels=levels, marks=marks,
scale=5.6, gap=16, body_w=9, left=56, width=720, vol_h=60, top=152,
label_gap=46,
caption="Cifra de 20-30 % pe poziție fără levier e a cursului; traseul barelor "
"e construit de mine, ca să se vadă cât durează.")
svg = ch.render()
titlu = ('<text x="24" y="24" fill="#333" style="font-weight:bold">'
'SPY — daily: fără stop, între intrare și țintă treci prin toată căderea</text>')
sub = (f'<text x="24" y="42" fill="#555" style="font-size:11px">'
f'{DURATA_JOS} de bare sub prețul de intrare, fără niciun ordin care să te scoată '
f'— ăsta e costul regulii „fără stop-loss".</text>')
box = [f'<rect x="424" y="58" width="284" height="76" fill="#fff4f4" stroke="{RED}" '
f'stroke-opacity="0.5"/>',
f'<text x="436" y="76" fill="{RED}" style="font-size:11px;font-weight:bold">'
f'aceeași cădere de {DD_PCT:.0f} % pe indice, pe poziție:</text>']
for i, (nume, pct) in enumerate(PIERDERI):
box.append(f'<text x="436" y="{94 + i * 15}" fill="{INK}" style="font-size:11px">'
f'{nume}: -{pct:.0f} %</text>')
i = svg.index(">") + 1
svg = svg[:i] + "\n " + "\n ".join([titlu, sub] + box) + svg[i:]
assert "\n\n" not in svg and ".md:" not in svg
OUT.write_text(svg)
print(f"scris {OUT.name}: intrare {ENTRY} fund {fund} (-{DD_PCT} %) TP {TP}, "
f"{DURATA_JOS} bare sub apă")

126
gen/strategii/atmi_risc.svg Normal file
View File

@@ -0,0 +1,126 @@
<svg viewBox="0 0 720 441" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif">
<text x="24" y="24" fill="#333" style="font-weight:bold">SPY — daily: fără stop, între intrare și țintă treci prin toată căderea</text>
<text x="24" y="42" fill="#555" style="font-size:11px">24 de bare sub prețul de intrare, fără niciun ordin care să te scoată — ăsta e costul regulii „fără stop-loss".</text>
<rect x="424" y="58" width="284" height="76" fill="#fff4f4" stroke="#c00" stroke-opacity="0.5"/>
<text x="436" y="76" fill="#c00" style="font-size:11px;font-weight:bold">aceeași cădere de 20 % pe indice, pe poziție:</text>
<text x="436" y="94" fill="#333" style="font-size:11px">ETF simplu (SPY): -20 %</text>
<text x="436" y="109" fill="#333" style="font-size:11px">ETF cu levier 2x: -40 %</text>
<text x="436" y="124" fill="#333" style="font-size:11px">ETF cu levier 3x (SPXL): -60 %</text>
<line x1="24" y1="152.0" x2="706" y2="152.0" stroke="#1a5fb4" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="692" y="146.0" fill="#1a5fb4" text-anchor="end">TP +10 % = 105.60</text>
<line x1="24" y1="205.8" x2="706" y2="205.8" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="692" y="199.8" fill="#188a3e" text-anchor="end">intrare 96.00</text>
<line x1="24" y1="313.3" x2="706" y2="313.3" stroke="#c00" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30" y="307.3" fill="#c00">fund 76.80 = -20 % pe poziție</text>
<line x1="56.0" y1="187.6" x2="56.0" y2="195.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="51.5" y="189.5" width="9" height="3.9" fill="#c00"/>
<line x1="72.0" y1="191.5" x2="72.0" y2="201.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="67.5" y="193.4" width="9" height="6.2" fill="#c00"/>
<line x1="88.0" y1="197.6" x2="88.0" y2="205.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="83.5" y="199.6" width="9" height="3.9" fill="#c00"/>
<line x1="104.0" y1="201.8" x2="104.0" y2="206.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="99.5" y="203.5" width="9" height="2.2" fill="#c00"/>
<line x1="120.0" y1="203.8" x2="120.0" y2="215.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="115.5" y="205.8" width="9" height="7.8" fill="#c00"/>
<line x1="136.0" y1="211.6" x2="136.0" y2="225.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="131.5" y="213.6" width="9" height="10.1" fill="#c00"/>
<line x1="152.0" y1="221.7" x2="152.0" y2="236.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="147.5" y="223.7" width="9" height="10.6" fill="#c00"/>
<line x1="168.0" y1="232.4" x2="168.0" y2="244.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="163.5" y="234.3" width="9" height="8.4" fill="#c00"/>
<line x1="184.0" y1="233.5" x2="184.0" y2="244.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="179.5" y="235.4" width="9" height="7.3" fill="#188a3e"/>
<line x1="200.0" y1="233.5" x2="200.0" y2="249.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="195.5" y="235.4" width="9" height="11.8" fill="#c00"/>
<line x1="216.0" y1="245.2" x2="216.0" y2="262.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="211.5" y="247.2" width="9" height="12.9" fill="#c00"/>
<line x1="232.0" y1="258.1" x2="232.0" y2="272.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="227.5" y="260.1" width="9" height="10.6" fill="#c00"/>
<line x1="248.0" y1="262.0" x2="248.0" y2="272.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="243.5" y="264.0" width="9" height="6.7" fill="#188a3e"/>
<line x1="264.0" y1="262.0" x2="264.0" y2="280.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="259.5" y="264.0" width="9" height="14.0" fill="#c00"/>
<line x1="280.0" y1="276.0" x2="280.0" y2="291.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="275.5" y="278.0" width="9" height="11.8" fill="#c00"/>
<line x1="296.0" y1="287.8" x2="296.0" y2="301.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="291.5" y="289.8" width="9" height="10.1" fill="#c00"/>
<line x1="312.0" y1="297.9" x2="312.0" y2="308.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="307.5" y="299.8" width="9" height="6.2" fill="#c00"/>
<line x1="328.0" y1="304.3" x2="328.0" y2="313.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="323.5" y="306.0" width="9" height="7.3" fill="#c00"/>
<line x1="344.0" y1="302.4" x2="344.0" y2="313.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="339.5" y="304.3" width="9" height="9.0" fill="#188a3e"/>
<line x1="360.0" y1="290.0" x2="360.0" y2="306.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="355.5" y="292.0" width="9" height="12.3" fill="#188a3e"/>
<line x1="376.0" y1="277.2" x2="376.0" y2="294.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="371.5" y="279.1" width="9" height="12.9" fill="#188a3e"/>
<line x1="392.0" y1="268.2" x2="392.0" y2="281.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="387.5" y="270.2" width="9" height="9.0" fill="#188a3e"/>
<line x1="408.0" y1="255.3" x2="408.0" y2="272.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="403.5" y="257.3" width="9" height="12.9" fill="#188a3e"/>
<line x1="424.0" y1="246.4" x2="424.0" y2="259.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="419.5" y="248.3" width="9" height="9.0" fill="#188a3e"/>
<line x1="440.0" y1="236.8" x2="440.0" y2="250.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="435.5" y="238.8" width="9" height="9.5" fill="#188a3e"/>
<line x1="456.0" y1="224.5" x2="456.0" y2="240.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="451.5" y="226.5" width="9" height="12.3" fill="#188a3e"/>
<line x1="472.0" y1="215.0" x2="472.0" y2="228.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="467.5" y="217.0" width="9" height="9.5" fill="#188a3e"/>
<line x1="488.0" y1="203.8" x2="488.0" y2="218.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="483.5" y="205.8" width="9" height="11.2" fill="#188a3e"/>
<line x1="504.0" y1="193.7" x2="504.0" y2="207.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="499.5" y="195.7" width="9" height="10.1" fill="#188a3e"/>
<line x1="520.0" y1="184.8" x2="520.0" y2="197.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="515.5" y="186.7" width="9" height="9.0" fill="#188a3e"/>
<line x1="536.0" y1="176.4" x2="536.0" y2="188.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="531.5" y="178.3" width="9" height="8.4" fill="#188a3e"/>
<line x1="552.0" y1="169.1" x2="552.0" y2="180.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="547.5" y="171.0" width="9" height="7.3" fill="#188a3e"/>
<line x1="568.0" y1="162.4" x2="568.0" y2="173.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="563.5" y="164.3" width="9" height="6.7" fill="#188a3e"/>
<line x1="584.0" y1="156.2" x2="584.0" y2="166.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="579.5" y="158.2" width="9" height="6.2" fill="#188a3e"/>
<line x1="600.0" y1="152.0" x2="600.0" y2="160.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="595.5" y="152.0" width="9" height="6.2" fill="#188a3e"/>
<line x1="24" y1="399.3" x2="706" y2="399.3" stroke="#888"/>
<rect x="51.5" y="367.9" width="9" height="31.4" fill="#c00" opacity="0.55"/>
<rect x="67.5" y="360.0" width="9" height="39.3" fill="#c00" opacity="0.55"/>
<rect x="83.5" y="352.1" width="9" height="47.1" fill="#c00" opacity="0.55"/>
<rect x="99.5" y="344.3" width="9" height="55.0" fill="#c00" opacity="0.55"/>
<rect x="115.5" y="365.7" width="9" height="33.6" fill="#c00" opacity="0.55"/>
<rect x="131.5" y="357.9" width="9" height="41.4" fill="#c00" opacity="0.55"/>
<rect x="147.5" y="350.0" width="9" height="49.3" fill="#c00" opacity="0.55"/>
<rect x="163.5" y="342.1" width="9" height="57.1" fill="#c00" opacity="0.55"/>
<rect x="179.5" y="363.6" width="9" height="35.7" fill="#188a3e" opacity="0.55"/>
<rect x="195.5" y="355.7" width="9" height="43.6" fill="#c00" opacity="0.55"/>
<rect x="211.5" y="347.9" width="9" height="51.4" fill="#c00" opacity="0.55"/>
<rect x="227.5" y="340.0" width="9" height="59.3" fill="#c00" opacity="0.55"/>
<rect x="243.5" y="361.4" width="9" height="37.9" fill="#188a3e" opacity="0.55"/>
<rect x="259.5" y="353.6" width="9" height="45.7" fill="#c00" opacity="0.55"/>
<rect x="275.5" y="345.7" width="9" height="53.6" fill="#c00" opacity="0.55"/>
<rect x="291.5" y="367.1" width="9" height="32.1" fill="#c00" opacity="0.55"/>
<rect x="307.5" y="359.3" width="9" height="40.0" fill="#c00" opacity="0.55"/>
<rect x="323.5" y="351.4" width="9" height="47.9" fill="#c00" opacity="0.55"/>
<rect x="339.5" y="343.6" width="9" height="55.7" fill="#188a3e" opacity="0.55"/>
<rect x="355.5" y="365.0" width="9" height="34.3" fill="#188a3e" opacity="0.55"/>
<rect x="371.5" y="357.1" width="9" height="42.1" fill="#188a3e" opacity="0.55"/>
<rect x="387.5" y="349.3" width="9" height="50.0" fill="#188a3e" opacity="0.55"/>
<rect x="403.5" y="341.4" width="9" height="57.9" fill="#188a3e" opacity="0.55"/>
<rect x="419.5" y="362.9" width="9" height="36.4" fill="#188a3e" opacity="0.55"/>
<rect x="435.5" y="355.0" width="9" height="44.3" fill="#188a3e" opacity="0.55"/>
<rect x="451.5" y="347.1" width="9" height="52.1" fill="#188a3e" opacity="0.55"/>
<rect x="467.5" y="339.3" width="9" height="60.0" fill="#188a3e" opacity="0.55"/>
<rect x="483.5" y="360.7" width="9" height="38.6" fill="#188a3e" opacity="0.55"/>
<rect x="499.5" y="352.9" width="9" height="46.4" fill="#188a3e" opacity="0.55"/>
<rect x="515.5" y="345.0" width="9" height="54.3" fill="#188a3e" opacity="0.55"/>
<rect x="531.5" y="366.4" width="9" height="32.9" fill="#188a3e" opacity="0.55"/>
<rect x="547.5" y="358.6" width="9" height="40.7" fill="#188a3e" opacity="0.55"/>
<rect x="563.5" y="350.7" width="9" height="48.6" fill="#188a3e" opacity="0.55"/>
<rect x="579.5" y="342.9" width="9" height="56.4" fill="#188a3e" opacity="0.55"/>
<rect x="595.5" y="364.3" width="9" height="35.0" fill="#188a3e" opacity="0.55"/>
<text x="24" y="333.3" fill="#555">volum</text>
<text x="328.0" y="327.3" fill="#c00" text-anchor="middle" style="font-weight:bold">-20 %: nimic nu te scoate</text>
<text x="488.0" y="171.8" fill="#777" text-anchor="middle" style="font-weight:bold">abia aici ești pe zero</text>
<text x="600.0" y="180.1" fill="#1a5fb4" text-anchor="middle" style="font-weight:bold">TP</text>
<text x="24" y="429" fill="#555">Cifra de 20-30 % pe poziție fără levier e a cursului; traseul barelor e construit de mine, ca să se vadă cât durează.</text>
</svg>

After

Width:  |  Height:  |  Size: 10 KiB

View File

@@ -0,0 +1,187 @@
#!/usr/bin/env python3
"""ATMI — Pasul 4: trigger-ul. DA (BIM, apoi candela verde) vs. NU (verde fără BIM).
Două panouri, unul sub altul, cu exact aceleași patru bare de corecție. Sus:
prețul intră în zona PPQ, apare săgeata BIM, iar prima candelă verde daily de
după ea închide la 96.00 — acolo intri. Jos: candela verde vine ÎNAINTE de
orice BIM, deci nu e trigger; prețul continuă să cadă spre SQ — „cuțitul în
cădere" din curs.
Numerele sunt cele ale capitolului: PPQ 95.80, SQ 90.80 (calculate în
`atmi_pivoti.py`), intrare 96.00 la close-ul candelei verzi.
Rulare: python3 gen/strategii/atmi_trigger.py
"""
import re
import sys
from pathlib import Path
sys.path.insert(0, "/workspace/atm-curs-dl")
from svg_candles import Arrow, Chart, from_closes # noqa: E402
OUT = Path(__file__).with_suffix(".svg")
W = 660
SCALE = 46.0
LEFT, GAP = 66, 44
RED, GREEN, BLUE, GREY, CYAN, PURPLE = "#c00", "#188a3e", "#1a5fb4", "#555", "#0a7f9e", "#7b2fbf"
PPQ, SQ, ENTRY = 95.80, 90.80, 96.00
COMUN = [98.60, 97.80, 97.00, 96.40] # corecția, identică pe ambele panouri
CLOSES_DA = COMUN + [95.70, 96.00, 96.60] # 4: BIM 5: prima verde = intrare
CLOSES_NU = COMUN + [96.80, 96.10, 95.10, 94.00, 92.90] # 4: verde fără BIM
w_da = [(0.15, 0.15)] * len(CLOSES_DA)
w_da[4] = (0.10, 0.15) # bara BIM coboară sub PPQ: 95.55
w_da[5] = (0.10, 0.10)
w_nu = [(0.15, 0.15)] * len(CLOSES_NU)
w_nu[4] = (0.10, 0.10)
START = COMUN[0] + 0.30
cds_da = from_closes(CLOSES_DA, wicks=w_da, start=START)
cds_nu = from_closes(CLOSES_NU, wicks=w_nu, start=START)
BIM_I, VERDE_DA, VERDE_NU = 4, 5, 4
# --- ce trebuie să fie adevărat ca desenul să susțină textul ---------------
ser = lambda c: (round(c.o, 2), round(c.h, 2), round(c.l, 2), round(c.c, 2)) # noqa: E731
assert [ser(c) for c in cds_da[:4]] == [ser(c) for c in cds_nu[:4]], \
"panourile nu pleacă din aceeași corecție"
# DA: BIM înainte de verde; verdele e chiar verde; close-ul lui = intrarea
assert BIM_I < VERDE_DA
assert cds_da[BIM_I].c < cds_da[BIM_I].o, "bara de BIM e bara de epuizare, roșie"
assert cds_da[VERDE_DA].c > cds_da[VERDE_DA].o, "candela de intrare nu e verde"
assert abs(cds_da[VERDE_DA].c - ENTRY) < 1e-9, cds_da[VERDE_DA].c
# criteriul A+: candela de intrare închide DEASUPRA pivotului
assert cds_da[VERDE_DA].c > PPQ, "candela de intrare nu închide peste PPQ"
# prețul a intrat efectiv în zona PPQ (a coborât sub pivot și a fost respins)
assert cds_da[BIM_I].l < PPQ < cds_da[VERDE_DA].c, (cds_da[BIM_I].l, PPQ)
assert min(c.l for c in cds_da) == cds_da[BIM_I].l, "fundul nu e pe bara de BIM"
# NU: verdele vine primul, și după el prețul face minime tot mai joase
assert cds_nu[VERDE_NU].c > cds_nu[VERDE_NU].o, "bara 4 de pe panoul NU nu e verde"
lows = [c.l for c in cds_nu[VERDE_NU + 1:]]
assert all(b < a for a, b in zip(lows, lows[1:])), "cuțitul nu cade continuu"
assert cds_nu[-1].c < PPQ - 2.5, "căderea de pe panoul NU e prea mică ca să se vadă"
assert min(c.l for c in cds_nu) > SQ, "căderea desenată trece deja de SQ"
# cele două panouri au aceeași scară, deci căderile se compară cu ochiul
PIERDERE = round((cds_nu[-1].c - cds_nu[VERDE_NU].c) / cds_nu[VERDE_NU].c * 100, 1)
assert PIERDERE < -3.0, PIERDERE
ch_da = Chart(
candles=cds_da,
marks=[],
arrows=[
Arrow(BIM_I, "BIM: săgeata indicatorului\ncyan = momentul în care\ntrendul se schimbă",
where="below", color=CYAN),
Arrow(VERDE_DA, f"AICI INTRI, la close {ENTRY:.2f}\nînchide peste pivot, deci\n"
f"cumpărătorii au ținut zona",
price=ENTRY, where="right", color=GREEN, dx=18, dy=40),
],
scale=SCALE, gap=GAP, body_w=13, left=LEFT, width=W,
title="DA — BIM, apoi prima candelă verde daily",
)
ch_nu = Chart(
candles=cds_nu,
marks=[],
arrows=[
Arrow(VERDE_NU, "aici NU intri: verdele a venit\nînainte de BIM, deci nimic\n"
"nu confirmă că vânzarea s-a oprit",
where="below", color=RED, dx=40),
Arrow(len(cds_nu) - 1, f"căderea continuă: {abs(PIERDERE):.1f} % mai jos\nde la candela verde —\n"
f"„cuțitul prins în cădere”",
where="below", color=RED, dx=-30),
],
scale=SCALE, gap=GAP, body_w=13, left=LEFT, width=W,
title="NU — candelă verde înainte de BIM",
)
def panel(ch):
svg = ch._render()
m = re.search(r'viewBox="0 0 ([\d.]+) ([\d.]+)"', svg)
assert float(m.group(1)) == W, f"o etichetă iese din {W}px"
return svg[svg.index(">") + 1:svg.rindex("</svg>")], float(m.group(2))
def level(ch, price, text, color, below=False):
y = ch._y(price)
out = [f'<line x1="24" y1="{y:.1f}" x2="{W - 14}" y2="{y:.1f}" stroke="{color}" '
f'stroke-width="1.5" stroke-dasharray="4 3"/>']
for k, s in enumerate(text):
ty = (y + 15 + 14 * k) if below else (y - 6 - 14 * (len(text) - 1 - k))
out.append(f'<text x="30" y="{ty:.1f}" fill="{color}" style="font-weight:bold">{s}</text>')
return out
def zone(ch, i0, i1, label, color, lift=0.0):
cds = ch.candles[i0:i1 + 1]
x0, x1 = ch._cx(i0) - 17, ch._cx(i1) + 17
y0 = ch._y(max(c.h for c in cds)) - 8 - lift
y1 = ch._y(min(c.l for c in cds)) + 8
return [f'<rect x="{x0:.1f}" y="{y0:.1f}" width="{x1 - x0:.1f}" height="{y1 - y0:.1f}" '
f'fill="{color}" fill-opacity="0.12" stroke="{color}" stroke-width="1"/>',
f'<text x="{x0 + 6:.1f}" y="{y0 - 7:.1f}" fill="{color}" '
f'style="font-weight:bold">{label}</text>']
body_da, h_da = panel(ch_da)
body_nu, h_nu = panel(ch_nu)
extra_da = (zone(ch_da, BIM_I, VERDE_DA, "zona de decizie: BIM + verde", BLUE, lift=16)
+ level(ch_da, PPQ, [f"PPQ {PPQ:.2f} — pivotul trimestrial"], PURPLE, below=True))
extra_nu = (zone(ch_nu, VERDE_NU, len(cds_nu) - 1, "fără BIM, nimic nu confirmă", RED, lift=16)
+ level(ch_nu, PPQ, [f"PPQ {PPQ:.2f} — pivotul trimestrial"], PURPLE, below=True))
CAP = ["Aceleași patru bare de corecție pe ambele panouri, aceeași scară.",
"PPQ 95.80 e calculat în diagrama pasului 1; intrarea 96.00 e close-ul candelei verzi."]
assert all(len(s) * 6.3 < W - 40 for s in CAP), "caption prea lung"
cap_top = h_da + h_nu + 20
H = cap_top + 24
svg = "\n ".join([
f'<svg viewBox="0 0 {W} {H:.0f}" xmlns="http://www.w3.org/2000/svg" '
f'style="width:100%;height:auto;font:12px sans-serif">',
f'<g transform="translate(0,0)">{"".join(extra_da)}{body_da}</g>',
f'<g transform="translate(0,{h_da:.0f})">{"".join(extra_nu)}{body_nu}</g>',
f'<text x="24" y="{cap_top:.0f}" fill="{GREY}">{CAP[0]}</text>',
f'<text x="24" y="{cap_top + 16:.0f}" fill="{GREY}">{CAP[1]}</text>',
"</svg>"])
assert "\n\n" not in svg and ".md:" not in svg
TEXT = re.compile(r'<text x="([-\d.]+)" y="([-\d.]+)"([^>]*)>(.*?)</text>', re.S)
def labels(body, y_off, tag):
out = []
for m in TEXT.finditer(body):
x, y, attrs, s = float(m.group(1)), float(m.group(2)) + y_off, m.group(3), m.group(4)
anchor = "end" if 'text-anchor="end"' in attrs else (
"middle" if 'text-anchor="middle"' in attrs else "start")
w = len(s) * 12 * (0.62 if "bold" in attrs else 0.52)
lf = x - w if anchor == "end" else (x - w / 2 if anchor == "middle" else x)
out.append((lf, lf + w, y, s, tag))
return out
LB = (labels(body_da + "".join(extra_da), 0.0, "DA")
+ labels(body_nu + "".join(extra_nu), h_da, "NU"))
for lf, rt, y, s, tag in LB:
assert -2 <= lf and rt <= W + 2, f"[{tag}] text iese din panză: {s!r}"
assert 0 <= y <= H, f"[{tag}] text în afara înălțimii: {s!r}"
for i in range(len(LB)):
for j in range(i + 1, len(LB)):
li, ri, yi, si, ti = LB[i]
lj, rj, yj, sj, tj = LB[j]
assert not (ti == tj and abs(yi - yj) < 12 and li < rj - 4 and lj < ri - 4), \
f"[{ti}] texte suprapuse: {si!r} / {sj!r}"
# niciun preț scris într-o etichetă care nu e un nivel desenat pe panoul lui
for lf, rt, y, s, tag in LB:
for p in re.findall(r"\d+\.\d\d", s):
assert float(p) in (PPQ, ENTRY), f"[{tag}] prețul {p} din {s!r} nu e un nivel desenat"
OUT.write_text(svg)
print(f"DA: BIM la {BIM_I} (low {cds_da[BIM_I].l:.2f} < PPQ {PPQ}), intrare {ENTRY:.2f}")
print(f"NU: verde la {VERDE_NU} fără BIM, apoi {PIERDERE:.1f} % în jos "
f"(ultimul close {cds_nu[-1].c:.2f}, peste SQ {SQ})")
print(f"scris {OUT.name} ({W}x{H:.0f})")

View File

@@ -0,0 +1,62 @@
<svg viewBox="0 0 660 821" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif">
<g transform="translate(0,0)"><rect x="225.0" y="149.3" width="78.0" height="75.7" fill="#1a5fb4" fill-opacity="0.12" stroke="#1a5fb4" stroke-width="1"/><text x="231.0" y="142.3" fill="#1a5fb4" style="font-weight:bold">zona de decizie: BIM + verde</text><line x1="24" y1="205.5" x2="646" y2="205.5" stroke="#7b2fbf" stroke-width="1.5" stroke-dasharray="4 3"/><text x="30" y="220.5" fill="#7b2fbf" style="font-weight:bold">PPQ 95.80 — pivotul trimestrial</text>
<text x="24" y="48" fill="#333" style="font-weight:bold">DA — BIM, apoi prima candelă verde daily</text>
<line x1="66.0" y1="56.0" x2="66.0" y2="83.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="59.5" y="62.9" width="13" height="13.8" fill="#c00"/>
<line x1="110.0" y1="69.8" x2="110.0" y2="120.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="103.5" y="76.7" width="13" height="36.8" fill="#c00"/>
<line x1="154.0" y1="106.6" x2="154.0" y2="157.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="147.5" y="113.5" width="13" height="36.8" fill="#c00"/>
<line x1="198.0" y1="143.4" x2="198.0" y2="184.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="191.5" y="150.3" width="13" height="27.6" fill="#c00"/>
<line x1="242.0" y1="173.3" x2="242.0" y2="217.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="235.5" y="177.9" width="13" height="32.2" fill="#c00"/>
<line x1="286.0" y1="191.7" x2="286.0" y2="214.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="279.5" y="196.3" width="13" height="13.8" fill="#188a3e"/>
<line x1="330.0" y1="161.8" x2="330.0" y2="203.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="323.5" y="168.7" width="13" height="27.6" fill="#188a3e"/>
<line x1="242.0" y1="247.0" x2="242.0" y2="229.0" stroke="#0a7f9e" stroke-width="1.8"/>
<polygon points="242.0,221.0 246.0,229.0 238.0,229.0" fill="#0a7f9e"/>
<text x="242.0" y="261.0" fill="#0a7f9e" text-anchor="middle" style="font-weight:bold">BIM: săgeata indicatorului</text>
<text x="242.0" y="275.0" fill="#0a7f9e" text-anchor="middle" style="font-weight:bold">cyan = momentul în care</text>
<text x="242.0" y="289.0" fill="#0a7f9e" text-anchor="middle" style="font-weight:bold">trendul se schimbă</text>
<line x1="344.5" y1="236.3" x2="302.6" y2="201.4" stroke="#188a3e" stroke-width="1.8"/>
<polygon points="296.5,196.3 305.2,198.3 300.1,204.5" fill="#188a3e"/>
<text x="348.5" y="226.3" fill="#188a3e" text-anchor="start" style="font-weight:bold">AICI INTRI, la close 96.00</text>
<text x="348.5" y="240.3" fill="#188a3e" text-anchor="start" style="font-weight:bold">închide peste pivot, deci</text>
<text x="348.5" y="254.3" fill="#188a3e" text-anchor="start" style="font-weight:bold">cumpărătorii au ținut zona</text>
</g>
<g transform="translate(0,324)"><rect x="225.0" y="128.6" width="210.0" height="225.2" fill="#c00" fill-opacity="0.12" stroke="#c00" stroke-width="1"/><text x="231.0" y="121.6" fill="#c00" style="font-weight:bold">fără BIM, nimic nu confirmă</text><line x1="24" y1="205.5" x2="646" y2="205.5" stroke="#7b2fbf" stroke-width="1.5" stroke-dasharray="4 3"/><text x="30" y="220.5" fill="#7b2fbf" style="font-weight:bold">PPQ 95.80 — pivotul trimestrial</text>
<text x="24" y="48" fill="#333" style="font-weight:bold">NU — candelă verde înainte de BIM</text>
<line x1="66.0" y1="56.0" x2="66.0" y2="83.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="59.5" y="62.9" width="13" height="13.8" fill="#c00"/>
<line x1="110.0" y1="69.8" x2="110.0" y2="120.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="103.5" y="76.7" width="13" height="36.8" fill="#c00"/>
<line x1="154.0" y1="106.6" x2="154.0" y2="157.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="147.5" y="113.5" width="13" height="36.8" fill="#c00"/>
<line x1="198.0" y1="143.4" x2="198.0" y2="184.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="191.5" y="150.3" width="13" height="27.6" fill="#c00"/>
<line x1="242.0" y1="154.9" x2="242.0" y2="182.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="235.5" y="159.5" width="13" height="18.4" fill="#188a3e"/>
<line x1="286.0" y1="152.6" x2="286.0" y2="198.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="279.5" y="159.5" width="13" height="32.2" fill="#c00"/>
<line x1="330.0" y1="184.8" x2="330.0" y2="244.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="323.5" y="191.7" width="13" height="46.0" fill="#c00"/>
<line x1="374.0" y1="230.8" x2="374.0" y2="295.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="367.5" y="237.7" width="13" height="50.6" fill="#c00"/>
<line x1="418.0" y1="281.4" x2="418.0" y2="345.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="411.5" y="288.3" width="13" height="50.6" fill="#c00"/>
<line x1="282.0" y1="303.2" x2="244.6" y2="194.1" stroke="#c00" stroke-width="1.8"/>
<polygon points="242.0,186.5 248.4,192.8 240.8,195.4" fill="#c00"/>
<text x="282.0" y="317.2" fill="#c00" text-anchor="middle" style="font-weight:bold">aici NU intri: verdele a venit</text>
<text x="282.0" y="331.2" fill="#c00" text-anchor="middle" style="font-weight:bold">înainte de BIM, deci nimic</text>
<text x="282.0" y="345.2" fill="#c00" text-anchor="middle" style="font-weight:bold">nu confirmă că vânzarea s-a oprit</text>
<line x1="388.0" y1="375.8" x2="412.0" y2="355.0" stroke="#c00" stroke-width="1.8"/>
<polygon points="418.0,349.8 414.6,358.1 409.3,352.0" fill="#c00"/>
<text x="388.0" y="389.8" fill="#c00" text-anchor="middle" style="font-weight:bold">căderea continuă: 4.0 % mai jos</text>
<text x="388.0" y="403.8" fill="#c00" text-anchor="middle" style="font-weight:bold">de la candela verde —</text>
<text x="388.0" y="417.8" fill="#c00" text-anchor="middle" style="font-weight:bold">„cuțitul prins în cădere”</text>
</g>
<text x="24" y="797" fill="#555">Aceleași patru bare de corecție pe ambele panouri, aceeași scară.</text>
<text x="24" y="813" fill="#555">PPQ 95.80 e calculat în diagrama pasului 1; intrarea 96.00 e close-ul candelei verzi.</text>
</svg>

After

Width:  |  Height:  |  Size: 6.0 KiB

View File

@@ -1,5 +1,9 @@
"""Buy hammer — diagrama de ansamblu (daily, ticker ilustrativ XYZ).
Seria de aici e SURSA UNICĂ a trade-ului din Partea A: `hammer_mbt10_bh_stop`
și `hammer_mbt10_bh_iesire` importă `serie()` și pornesc din aceleași bare
(hammer 63.30 / 62.10, intrare 63.35, SL 62.05, TP 65.95 = 2R).
Citește specificația `gen/strategii/hammer_mbt10_bh_ansamblu.spec.txt`.
Seria de 34 de candele e construită din lista de close-uri dată, cu open-ul
fiecărei bare = close-ul precedentului; wick-urile sunt fixate ca nivelurile
@@ -10,109 +14,117 @@ import re
import sys; sys.path.insert(0, "/workspace/atm-curs-dl")
from svg_candles import Chart, Level, Mark, from_closes
# --- seria: 34 de close-uri, exact ca în specificație ------------------------
closes = [
72.00, 71.20, 71.50, 70.40, 69.60, 70.00, 68.90, 68.10, 68.40, 67.30, # 0-9
66.50, 66.80, 65.70, 64.90, 65.20, 64.10, 63.40, 63.70, 63.05, # 10-18
63.30, # 19 = hammer: o 63.05, c/h 63.30, l 62.10 (H = C, fitil sus 0)
63.35, # 20 = confirmare: close peste 63.30 => intrare
63.80, 64.20, 64.60, 64.40, 64.90, 65.20, 65.50, 65.80, 66.10, # 21-29
66.00, 65.70, 65.40, 65.60, # 30-33
]
assert len(closes) == 34
def serie():
"""Cele 34 de bare ale trade-ului XYZ, cu verificările specificației."""
# --- seria: 34 de close-uri, exact ca în specificație ------------------------
closes = [
72.00, 71.20, 71.50, 70.40, 69.60, 70.00, 68.90, 68.10, 68.40, 67.30, # 0-9
66.50, 66.80, 65.70, 64.90, 65.20, 64.10, 63.40, 63.70, 63.05, # 10-18
63.30, # 19 = hammer: o 63.05, c/h 63.30, l 62.10 (H = C, fitil sus 0)
63.35, # 20 = confirmare: close peste 63.30 => intrare
63.80, 64.20, 64.60, 64.40, 64.90, 65.20, 65.50, 65.80, 66.10, # 21-29
66.00, 65.70, 65.40, 65.60, # 30-33
]
assert len(closes) == 34
# wick-uri: (up, down) implicite (0.25, 0.30) + excepțiile din specificație
wicks = [(0.25, 0.30)] * 34
wicks[19] = (0.00, 0.95) # hammer: high 63.30 (= close), low 62.10
# bara 20: wu=0.15 => high 63.50. Spec-ul dă wd=0.15 cu „low 63.20", dar
# wd se măsoară de la min(o,c)=63.30, deci 0.15 dă 63.15; folosim tuplul
# literal din specificație (0.15, 0.15), low-ul barei 20 nu e etichetat.
wicks[20] = (0.15, 0.15)
# wick-uri: (up, down) implicite (0.25, 0.30) + excepțiile din specificație
wicks = [(0.25, 0.30)] * 34
wicks[19] = (0.00, 0.95) # hammer: high 63.30 (= close), low 62.10
# bara 20: wu=0.15 => high 63.50. Spec-ul dă wd=0.15 cu „low 63.20", dar
# wd se măsoară de la min(o,c)=63.30, deci 0.15 dă 63.15; folosim tuplul
# literal din specificație (0.15, 0.15), low-ul barei 20 nu e etichetat.
wicks[20] = (0.15, 0.15)
# volum relativ ales de generator (materialul nu dă volum pe exemplul construit):
# normal pe downtrend, în creștere pe hammer (19) și pe confirmare (20), normal după
vols = [50, 48, 47, 46, 45, 46, 44, 43, 45, 42,
41, 43, 40, 39, 41, 38, 37, 39, 55,
90, 95,
58, 55, 53, 50, 52, 54, 56, 60, 64,
58, 55, 52, 50]
assert len(vols) == 34
media_vol = sum(vols) / len(vols)
assert vols[19] > media_vol and vols[20] > media_vol, "volum peste medie pe hammer/confirmare"
# volum relativ ales de generator (materialul nu dă volum pe exemplul construit):
# normal pe downtrend, în creștere pe hammer (19) și pe confirmare (20), normal după
vols = [50, 48, 47, 46, 45, 46, 44, 43, 45, 42,
41, 43, 40, 39, 41, 38, 37, 39, 55,
90, 95,
58, 55, 53, 50, 52, 54, 56, 60, 64,
58, 55, 52, 50]
assert len(vols) == 34
media_vol = sum(vols) / len(vols)
assert vols[19] > media_vol and vols[20] > media_vol, "volum peste medie pe hammer/confirmare"
cds = from_closes(closes, wicks=wicks, vols=vols, start=72.00)
cds = from_closes(closes, wicks=wicks, vols=vols, start=72.00)
hammer, conf = cds[19], cds[20]
# confirmarea o punem ca notă sub grafic: un Mark deasupra barei 20 s-ar
# suprapune cu fitilul lung al hammer-ului (bara 19)
conf.note = "bara 20: confirmare — close 63.35 peste high-ul hammer-ului 63.30 (intrare)"
intrare, sl, tp = 63.35, 62.05, 65.95
hammer, conf = cds[19], cds[20]
# confirmarea o punem ca notă sub grafic: un Mark deasupra barei 20 s-ar
# suprapune cu fitilul lung al hammer-ului (bara 19)
conf.note = "bara 20: confirmare — close 63.35 peste high-ul hammer-ului 63.30 (intrare)"
intrare, sl, tp = 63.35, 62.05, 65.95
# --- cele 8 assert-uri cerute de specificație -------------------------------
# 1. hammer: H = C = 63.30, L = 62.10
assert abs(cds[19].c - 63.30) < 1e-9 and abs(cds[19].h - 63.30) < 1e-9, "H != C la hammer"
assert abs(cds[19].l - 62.10) < 1e-9, f"low[19]={cds[19].l} != 62.10"
# 2. open[19] = close[18]; corp 0.25; fitil jos 0.95 >= 2*0.25
assert abs(cds[19].o - cds[18].c) < 1e-9 and abs(cds[19].o - 63.05) < 1e-9, "open[19] != close[18]"
corp = hammer.c - hammer.o
fitil_jos = hammer.o - hammer.l
assert abs(corp - 0.25) < 1e-9, f"corp={corp} != 0.25"
assert abs(fitil_jos - 0.95) < 1e-9, f"fitil jos={fitil_jos} != 0.95"
assert fitil_jos >= 2 * corp, "fitilul nu e cel puțin dublul corpului"
# 3. confirmarea închide peste high-ul hammer-ului
assert abs(conf.c - intrare) < 1e-9, f"close[20]={conf.c} != 63.35"
assert conf.c > hammer.h and abs(hammer.h - 63.30) < 1e-9, "close[20] nu e peste high[19]"
# 4. SL = low-ul hammer-ului - 0.05
assert abs(sl - (cds[19].l - 0.05)) < 1e-9, "SL != low[19] - 0.05"
# 5. risc 1.30, TP 2.60 = 2R exact
assert abs(abs(intrare - sl) - 1.30) < 1e-9, "risc != 1.30"
assert abs(abs(tp - intrare) - 2.60) < 1e-9, "TP != 2R exact"
# 6. primul high >= TP e bara 28 (65.80 + wick 0.25 = 66.05)
primul_tp = next(i for i in range(21, len(cds)) if cds[i].h >= tp)
assert primul_tp == 28, f"TP 65.95 atins întâi la bara {primul_tp}, nu 28"
# 7. downtrend vizibil
assert cds[18].c < cds[0].c - 8, "downtrend prea mic"
# 8. ordinea nivelurilor
assert sl < intrare < tp, "SL / intrare / TP nu sunt în ordine"
# --- cele 8 assert-uri cerute de specificație -------------------------------
# 1. hammer: H = C = 63.30, L = 62.10
assert abs(cds[19].c - 63.30) < 1e-9 and abs(cds[19].h - 63.30) < 1e-9, "H != C la hammer"
assert abs(cds[19].l - 62.10) < 1e-9, f"low[19]={cds[19].l} != 62.10"
# 2. open[19] = close[18]; corp 0.25; fitil jos 0.95 >= 2*0.25
assert abs(cds[19].o - cds[18].c) < 1e-9 and abs(cds[19].o - 63.05) < 1e-9, "open[19] != close[18]"
corp = hammer.c - hammer.o
fitil_jos = hammer.o - hammer.l
assert abs(corp - 0.25) < 1e-9, f"corp={corp} != 0.25"
assert abs(fitil_jos - 0.95) < 1e-9, f"fitil jos={fitil_jos} != 0.95"
assert fitil_jos >= 2 * corp, "fitilul nu e cel puțin dublul corpului"
# 3. confirmarea închide peste high-ul hammer-ului
assert abs(conf.c - intrare) < 1e-9, f"close[20]={conf.c} != 63.35"
assert conf.c > hammer.h and abs(hammer.h - 63.30) < 1e-9, "close[20] nu e peste high[19]"
# 4. SL = low-ul hammer-ului - 0.05
assert abs(sl - (cds[19].l - 0.05)) < 1e-9, "SL != low[19] - 0.05"
# 5. risc 1.30, TP 2.60 = 2R exact
assert abs(abs(intrare - sl) - 1.30) < 1e-9, "risc != 1.30"
assert abs(abs(tp - intrare) - 2.60) < 1e-9, "TP != 2R exact"
# 6. primul high >= TP e bara 28 (65.80 + wick 0.25 = 66.05)
primul_tp = next(i for i in range(21, len(cds)) if cds[i].h >= tp)
assert primul_tp == 28, f"TP 65.95 atins întâi la bara {primul_tp}, nu 28"
# 7. downtrend vizibil
assert cds[18].c < cds[0].c - 8, "downtrend prea mic"
# 8. ordinea nivelurilor
assert sl < intrare < tp, "SL / intrare / TP nu sunt în ordine"
print(f"hammer H/C {hammer.h:.2f} L {hammer.l:.2f} intrare {conf.c:.2f} "
f"SL {sl:.2f} TP {tp:.2f} = {abs(tp-intrare)/abs(intrare-sl):.1f}R "
f"TP atins la bara {primul_tp} (high {cds[primul_tp].h:.2f})")
print(f"hammer H/C {hammer.h:.2f} L {hammer.l:.2f} intrare {conf.c:.2f} "
f"SL {sl:.2f} TP {tp:.2f} = {abs(tp-intrare)/abs(intrare-sl):.1f}R "
f"TP atins la bara {primul_tp} (high {cds[primul_tp].h:.2f})")
return cds, hammer, conf
# --- desenul ----------------------------------------------------------------
ch = Chart(
candles=cds,
levels=[
Level(sl, "SL 62.05 — sub low-ul hammer-ului", "#c00", label_at="left"),
Level(intrare, "intrare 63.35", "#188a3e"),
Level(tp, "TP 65.95 = 2R", "#1a5fb4"),
],
marks=[
Mark(19, "hammer 63.30 / 62.10", "#b06000", "below"),
],
scale=32.0, gap=15, body_w=9, left=44, width=720, vol_h=70,
vol_label="volum", title="Buy hammer — daily (ticker ilustrativ XYZ, din lecția de pattern)",
caption="", # legenda e pusă manual, pe două rânduri, ca să nu iasă din pânză
)
svg = ch.render()
assert "<svg" in svg and "\n\n" not in svg, "linie goală în SVG"
if __name__ == "__main__":
cds, hammer, conf = serie()
intrare, sl, tp = 63.35, 62.05, 65.95
# legenda din specificație e mai lată decât pânza: o rupem pe două rânduri și
# extindem viewBox-ul ca să nu fie tăiată
m = re.search(r'viewBox="0 0 (\d+) (\d+)"', svg)
W, H = int(m.group(1)), int(m.group(2))
legenda = [
"Exemplu ilustrativ (XYZ) din lecția de pattern (01_MODUL_1/05_patternuri_candele.md:210-215);",
"prețurile sunt cele ale lecției, structura barelor dintre ele e construită.",
]
extra = 16 * len(legenda) + 6
svg = svg.replace(f'viewBox="0 0 {W} {H}"', f'viewBox="0 0 {W} {H + extra}"')
svg = svg.replace("</svg>", "".join(
f'<text x="24" y="{H + 12 + 16 * i}" fill="#555">{t}</text>'
for i, t in enumerate(legenda)) + "</svg>")
assert "\n\n" not in svg, "linie goală în SVG după legendă"
# --- desenul ----------------------------------------------------------------
ch = Chart(
candles=cds,
levels=[
Level(sl, "SL 62.05 — sub low-ul hammer-ului", "#c00", label_at="left"),
Level(intrare, "intrare 63.35", "#188a3e"),
Level(tp, "TP 65.95 = 2R", "#1a5fb4"),
],
marks=[
Mark(19, "hammer 63.30 / 62.10", "#b06000", "below"),
],
scale=32.0, gap=15, body_w=9, left=44, width=720, vol_h=70,
vol_label="volum", title="Buy hammer — daily (ticker ilustrativ XYZ, din lecția de pattern)",
caption="", # legenda e pusă manual, pe două rânduri, ca să nu iasă din pânză
)
with open("/workspace/atm-curs-dl/gen/strategii/hammer_mbt10_bh_ansamblu.svg", "w") as f:
f.write(svg)
print("scris gen/strategii/hammer_mbt10_bh_ansamblu.svg")
svg = ch.render()
assert "<svg" in svg and "\n\n" not in svg, "linie goală în SVG"
# legenda din specificație e mai lată decât pânza: o rupem pe două rânduri și
# extindem viewBox-ul ca să nu fie tăiată
m = re.search(r'viewBox="0 0 (\d+) (\d+)"', svg)
W, H = int(m.group(1)), int(m.group(2))
legenda = [
"Exemplu ilustrativ (XYZ) din lecția de pattern (01_MODUL_1/05_patternuri_candele.md:210-215);",
"prețurile sunt cele ale lecției, structura barelor dintre ele e construită.",
]
extra = 16 * len(legenda) + 6
svg = svg.replace(f'viewBox="0 0 {W} {H}"', f'viewBox="0 0 {W} {H + extra}"')
svg = svg.replace("</svg>", "".join(
f'<text x="24" y="{H + 12 + 16 * i}" fill="#555">{t}</text>'
for i, t in enumerate(legenda)) + "</svg>")
assert "\n\n" not in svg, "linie goală în SVG după legendă"
with open("/workspace/atm-curs-dl/gen/strategii/hammer_mbt10_bh_ansamblu.svg", "w") as f:
f.write(svg)
print("scris gen/strategii/hammer_mbt10_bh_ansamblu.svg")

View File

@@ -1,166 +1,203 @@
"""Diagrama de ansamblu MDSRT long (strategii, marcajul `ansamblu`).
"""MDSRT — diagrama de ansamblu (Nivelul 1) și seria canonică a capitolului.
„SPY — 5 min: al doilea picior mai jos la 589.80, sub suportul 590.00 →
divergență bull (M) preț-vs-volum → candela-trigger Buy Hammer/Doji →
intrare 590.20 → SL 589.40 (risc 0.80) → TP1 591.00 (1:1) → poziția rămasă
pe trail, ieșire la close 592.40 (≈ 2.75R)."
Aici trăiește singurul exemplu construit al capitolului: SPY pe 5 minute,
suport/pivot daily 590.00, piciorul 1 la 590.10 (ține nivelul), piciorul 2 la
589.50 (îl rupe, cu divergență pe volum), candela-trigger = Buy Hammer,
intrare 590.20, SL 589.40, risc 0.80, TP1 591.00 (1:1), ieșire pe trail la
592.40 (2.75R).
Toate close-urile, wick-urile speciale și nivelurile vin din
`gen/strategii/mdsrt_ansamblu.spec.txt`. Structura M→A→P, suportul 590.00,
minimul 589.80 și riscul 0.80 sunt din exemplul cursului
(`05_MODUL_4/02_strategia_5_mdsrt.md:159-177, 246, 308-311`). Intrare/SL/TP
sunt exemplul construit al autorului sumarului, marcat explicit ca NU citat
din curs (`...:166-177, 439-445`); transcrierea se întrerupe înainte de
planul numeric. Volumele sunt relative, alese de generator (materialul nu dă
volum pentru acest exemplu).
Celelalte generatoare de preț ale capitolului (picior, trigger, stop, iesire)
IMPORTĂ seria de aici. Așa o regulă numerică — marja stopului, distanța până
la țintă — nu poate să difere de la o diagramă la alta.
Rulează:
python3 gen/strategii/mdsrt_ansamblu.py
Scrie lângă el `mdsrt_ansamblu.svg`.
Regulile numerice ale capitolului, definite o singură dată, aici:
MARJA = 0.10 — stopul stă cu atât sub low-ul piciorului 2
intrarea = close-ul candelei care sparge high-ul candelei-trigger
TP1 = intrare + (intrare − SL)
Ce e din curs și ce nu: structura M→A→P e a cursului; suportul 590.00 și
minimul piciorului 2 vin din exemplul construit al autorului sumarului
(`05_MODUL_4/02_strategia_5_mdsrt.md:166-177, 439-445`), nu din transcriere —
transcrierea se întrerupe înainte de planul numeric.
Rulează: python3 gen/strategii/mdsrt_ansamblu.py
"""
import re
import sys
from pathlib import Path
sys.path.insert(0, "/workspace/atm-curs-dl")
from svg_candles import Chart, Level, Mark, MA, from_closes # noqa: E402
from svg_candles import Chart, Level, Mark, MA, Zone, Arrow, from_closes # noqa: E402
OUT = Path(__file__).resolve().parent / "mdsrt_ansamblu.svg"
OUT = Path(__file__).with_suffix(".svg")
GRAY, RED, GREEN, BLUE, ORANGE = "#777", "#c00", "#188a3e", "#1a5fb4", "#b06000"
# ---------------------------------------------------------------- seria (30 bare)
# ------------------------------------------------- regulile numerice ale capitolului
MARJA = 0.10 # stopul, sub low-ul piciorului 2
SUPORT = 590.00 # pivotul daily (nivelul de pe TF-ul mare)
LEG1, TRIG, CONF = 10, 18, 19 # indicii: piciorul 1, candela-trigger, candela de intrare
STOP_BARS = 4 # low-ul se caută pe ultimele 4 candele, ca la Buy Doji
CLOSES = [
596.00, 595.20, 595.60, 594.80, 594.10, 593.40, 593.70, 592.90, # 0-7
592.20, 591.60, 591.90, 591.30, 590.80, 590.30, 590.55, 590.10, # 8-15
589.85, 590.05, # 16-17
589.80, # 18 = al doilea picior mai jos + candela-trigger (hammer)
590.20, # 19 = intrare (close = entry; sparge high-ul trigger-ului)
590.60, 590.90, 591.00, # 20-22 (22 = TP1 1:1)
592.20, 591.60,
590.40, # 10 = piciorul 1
590.90, 591.40, 591.10, 591.30, 590.90, 590.50, 590.05, # 11-17
589.80, # 18 = piciorul 2 (Buy Hammer)
590.20, # 19 = intrarea
590.60, 590.90, 591.00, # 20-22 (22 = TP1)
591.30, 591.10, 591.45, 591.70, 591.95, 592.15, # 23-28
592.40, # 29 = ieșire pe trail (close)
592.80, 593.10, 592.90, # 29-31 = ultimul impuls
592.40, # 32 = ieșire pe trail
]
assert len(CLOSES) == 30, len(CLOSES)
WICKS = [(0.25, 0.30)] * 33
WICKS[LEG1] = (0.25, 0.30) # piciorul 1: low 590.10, deasupra suportului
WICKS[16] = (0.20, 0.15)
WICKS[17] = (0.15, 0.10) # low 589.95 — prețul intră în zonă, fără să facă minim nou
WICKS[TRIG] = (0.10, 0.30) # hammer: high 590.15, low 589.50
WICKS[CONF] = (0.10, 0.05)
WICKS[20] = (0.25, 0.15) # retestul nivelului ține: low 590.05, peste pivot
WICKS[21] = (0.05, 0.15) # high 590.95 < TP1: ținta e atinsă prima dată la bara 22
# fitile (sus, jos): (0.25, 0.30) peste tot, cu excepțiile din spec.
WICKS = [(0.25, 0.30)] * 30
WICKS[18] = (0.10, 0.40) # hammer: high 590.15, low 589.40 (= SL)
WICKS[19] = (0.10, 0.05) # intrare: high 590.30, low 589.75
# bara 21 coborâtă sub TP1 (high 590.95 < 591.00), ca TP1 să fie atins exact
# prima dată la bara 22 (altfel assert-ul 5 ar pica pe „primul high").
WICKS[21] = (0.05, 0.30)
# volum relativ (ales de generator): 16-19 crescător, 18-19 peste medie,
# vol[18] > vol[10] (higher low pe volum la lower low pe preț).
VOLS = [
48, 46, 44, 45, 43, 41, 40, 42, 44, 46, # 0-9
52, 38, 40, 42, 39, 44, # 10-15
50, 58, 72, 85, # 16-19 absorbție la minim
70, 64, 58, 60, 55, 52, 50, 48, 46, 44, # 20-29
48, 46, 44, 45, 43, 41, 40, 42, 44, 46, # 0-9
52, # 10 = volumul piciorului 1
38, 40, 42, 39, 44, 50, 58, # 11-17
88, 80, # 18-19 absorbție la minim
70, 64, 58, 60, 55, 52, 50, 48, 46, # 20-28
52, 48, 42, 46, # 29-32
]
assert len(VOLS) == 30, len(VOLS)
assert len(CLOSES) == len(WICKS) == len(VOLS) == 33
cds = from_closes(CLOSES, wicks=WICKS, vols=VOLS, start=596.60)
# ---------------------------------------------------------------- assert-urile din spec
entry = cds[19].c
sl = cds[18].l
tp1 = cds[22].c
EXIT_I = 32 # bara pe care se închide poziția, sub linia de trail
# 1. minimul și SL-ul pe bara 18
assert cds[18].c == 589.80, cds[18].c
assert cds[18].l == 589.40, cds[18].l
# 2. al doilea picior rupe suportul/pivotul 590.00
assert cds[18].l < 590.00, cds[18].l
# 3. intrarea = close-ul barei 19 și sparge high-ul trigger-ului
assert cds[19].c == 590.20, cds[19].c
assert cds[19].c == entry
assert cds[19].c > cds[18].h, (cds[19].c, cds[18].h)
# 4. TP1 exact 1:1
assert abs((entry - sl) - (tp1 - entry)) < 1e-9, (entry - sl, tp1 - entry)
assert abs((entry - sl) - 0.80) < 1e-9
# 5. TP1 atins la bara 22 (și nu mai devreme)
assert cds[22].c == 591.00, cds[22].c
assert cds[22].c == tp1
assert max(c.h for c in cds[20:22]) < tp1, [c.h for c in cds[20:22]]
# 6. ieșirea pe trail e pe profit
assert cds[29].c == 592.40, cds[29].c
assert cds[29].c > entry, (cds[29].c, entry)
# 7. hammer: corp mic, coadă lungă în jos
body = abs(cds[18].o - cds[18].c)
rng = cds[18].h - cds[18].l
tail = min(cds[18].o, cds[18].c) - cds[18].l
assert body == 0.25, body
assert body <= 0.5 * rng, (body, rng)
assert tail > body, (tail, body)
# 8. downtrend vizibil
assert cds[13].c < cds[0].c - 5, (cds[13].c, cds[0].c)
# 9. divergență pe volum: lower low pe preț, higher low pe volum
assert cds[18].l < cds[10].l, (cds[18].l, cds[10].l)
assert VOLS[18] > VOLS[10], (VOLS[18], VOLS[10])
# barele 16-19 au volum crescător; 18-19 peste media seriei
assert VOLS[16] < VOLS[17] < VOLS[18] < VOLS[19], VOLS[16:20]
avg_vol = sum(VOLS) / len(VOLS)
assert VOLS[18] > avg_vol and VOLS[19] > avg_vol, (VOLS[18], VOLS[19], avg_vol)
# 10. fiecare open == close-ul barei anterioare
for a, b in zip(cds, cds[1:]):
assert a.c == b.o, (a.c, b.o)
r_mult = (cds[29].c - entry) / (entry - sl)
assert abs(r_mult - 2.75) < 1e-9, r_mult
def bull_trail(cds, start):
"""Bull Trail, definiția cursului: low-ul fiecărei candele care se închide
peste high-ul candelei dinainte; linia urcă, nu coboară niciodată.
Întoarce lista [(index, nivel)] de la bara `start` încolo."""
out, cur = [], None
for i in range(start, len(cds)):
if cds[i].c > cds[i - 1].h:
cur = round(cds[i].l, 2) if cur is None else max(cur, round(cds[i].l, 2))
if cur is not None:
out.append((i, cur))
return out
# ---------------------------------------------------------------- niveluri, marks
levels = [
Level(590.00, "suport / pivot 590.00", BLUE, label_at="left"),
Level(sl, f"SL {sl:.2f} — risc 0.80", RED, label_at="left"),
# stânga: altfel eticheta din dreapta se calcă pe textul „SMA-20" al mediei
Level(tp1, f"TP1 {tp1:.2f} = 1:1", GREEN, label_at="left"),
]
marks = [
Mark(18, f"minim 589.80 — divergență (M)", RED, "below"),
# ridicat deasupra vârfurilor candelelor de urcare (altfel textul cade peste
# fitilele barelor 20-22) — bara 19 e totuși exact sub el
Mark(19, f"intrare {entry:.2f}", GREEN, "above", dy=-46),
Mark(29, f"ieșire trail {cds[29].c:.2f}", GREEN, "above"),
]
def serie():
"""Seria canonică a capitolului, 33 de candele de 5 minute."""
return from_closes(CLOSES, wicks=WICKS, vols=VOLS, start=596.60)
# titlul e injectat pe două linii: textul din spec (82 caractere) nu încape
# pe un singur rând în 640 px fără să fie tăiat la margine
TITLE = ["SPY — 5 min (exemplu construit pe scara lecției;",
"cifrele planului nu vin din curs)"]
ch = Chart(
candles=cds, levels=levels, marks=marks,
mas=[MA(20, ORANGE, dash="4 3", text="SMA-20")],
scale=48.0, gap=15, body_w=9, left=44, width=640, top=64, vol_h=70,
vol_label="volum",
title="", caption="",
)
svg = ch.render()
title_svg = "\n ".join(
f'<text x="24" y="{26 + 18 * i}" fill="#333" style="font-weight:bold">{t}</text>'
for i, t in enumerate(TITLE))
i = svg.index(">") + 1
svg = svg[:i] + "\n " + title_svg + svg[i:]
cds = serie()
leg1_l = cds[LEG1].l
leg2_l = cds[TRIG].l
ENTRY = cds[CONF].c
SL = round(leg2_l - MARJA, 2)
R = round(ENTRY - SL, 2)
TP1 = round(ENTRY + R, 2)
# ---------------------------------------------------------------- legenda (onestitate)
m = re.search(r'viewBox="0 0 (\d+) ([0-9.]+)"', svg)
W, H0 = int(m.group(1)), float(m.group(2))
legend = [
"Legendă: entry/SL/TP/trail sunt exemplul construit al autorului sumarului,",
"nu citate din curs (transcrierea se întrerupe înainte de planul numeric).",
]
legend_svg = [f'<text x="24" y="{H0 + 16 + 17 * i:.1f}" fill="#555">{t}</text>'
for i, t in enumerate(legend)]
new_h = H0 + 16 + 17 * (len(legend) - 1) + 14
svg = re.sub(r'(viewBox="0 0 \d+ )[0-9.]+(")',
lambda mm: mm.group(1) + f"{new_h:.0f}" + mm.group(2), svg, count=1)
svg = svg.replace("\n</svg>", "\n " + "\n ".join(legend_svg) + "\n</svg>")
# ------------------------------------------------------------------ assert-urile
for i, c in enumerate(cds):
assert c.h >= max(c.o, c.c) and c.l <= min(c.o, c.c), f"bara {i}: h/l incoerent"
if i:
assert abs(c.o - cds[i - 1].c) < 1e-9, f"open[{i}] != close[{i-1}]"
assert svg.count("\n\n") == 0, "linie goală în SVG rupe blocul din markdown"
assert f"TP1 {tp1:.2f}" in svg and f"intrare {entry:.2f}" in svg
OUT.write_text(svg)
print(f"scris {OUT.name}: {len(cds)} candele, suport 590.00, minim {cds[18].l:.2f}, "
f"intrare {entry:.2f}, SL {sl:.2f} (risc 0.80), TP1 {tp1:.2f} (1:1), "
f"ieșire {cds[29].c:.2f} = {r_mult:.2f}R, vol[18]={VOLS[18]} > vol[10]={VOLS[10]}")
# 1. piciorul 1 ține nivelul, piciorul 2 îl rupe — asta e povestea capitolului
assert leg1_l == 590.10 and leg1_l > SUPORT, leg1_l
assert leg2_l == 589.50 and leg2_l < SUPORT, leg2_l
assert leg2_l < leg1_l, (leg2_l, leg1_l)
# 2. cele două picioare sunt minimele locale, nu doar două bare oarecare
assert leg1_l == min(c.l for c in cds[:LEG1 + 6]), "piciorul 1 nu e minimul zonei lui"
assert leg2_l == min(c.l for c in cds), "piciorul 2 nu e minimul seriei"
# 3. distanța dintre picioare depășește minimul de 5 candele cerut de curs
assert TRIG - LEG1 == 8, TRIG - LEG1
# 4. hammer: corp mic sus, coadă lungă în jos
body = abs(cds[TRIG].o - cds[TRIG].c)
rng = cds[TRIG].h - cds[TRIG].l
tail = min(cds[TRIG].o, cds[TRIG].c) - cds[TRIG].l
assert body <= 0.5 * rng and tail > body, (body, rng, tail)
# 5. intrarea sparge high-ul candelei-trigger (regula de intrare a capitolului)
assert ENTRY == 590.20 and ENTRY > cds[TRIG].h, (ENTRY, cds[TRIG].h)
# 6. stopul: marja sub cel mai jos low din ultimele 4 candele
low4 = min(c.l for c in cds[CONF - STOP_BARS + 1:CONF + 1])
assert low4 == leg2_l, (low4, leg2_l)
assert SL == 589.40 and R == 0.80, (SL, R)
# 7. TP1 e 1:1 exact și e atins prima dată la bara 22
assert abs((ENTRY - SL) - (TP1 - ENTRY)) < 1e-9
assert TP1 == 591.00
assert next(i for i in range(CONF + 1, len(cds)) if cds[i].h >= TP1 - 1e-9) == 22
# 8. downtrend vizibil înainte de piciorul 1
assert cds[LEG1].c < cds[0].c - 5, (cds[LEG1].c, cds[0].c)
# 9. divergența: lower low pe preț, higher low pe volum
assert cds[TRIG].l < cds[LEG1].l and VOLS[TRIG] > VOLS[LEG1]
assert VOLS[16] < VOLS[17] < VOLS[TRIG] == max(VOLS)
# 10. după intrare, retestul ține: nicio bară nu mai închide sub pivot
assert all(c.c > SUPORT for c in cds[CONF + 1:]), "prețul recade sub pivot după intrare"
assert min(c.l for c in cds[CONF + 1:]) > SUPORT, "o bară de după intrare rupe iar pivotul"
# 11. ieșirea pe trail: ultimul swing low înainte de întoarcere e linia de trail,
# iar bara de ieșire e prima care se închide sub ea
_trail = bull_trail(cds, CONF)
TRAIL = dict(_trail)[EXIT_I] # nivelul liniei de trail când vine bara de ieșire
assert TRAIL == 592.50, TRAIL
assert [p for _, p in _trail] == sorted(p for _, p in _trail), "linia de trail coboară"
assert all(cds[i].c > p for i, p in _trail if i < EXIT_I), "trail-ul era rupt mai devreme"
assert cds[EXIT_I].c == 592.40 < TRAIL, (cds[EXIT_I].c, TRAIL)
r_mult = round((cds[EXIT_I].c - ENTRY) / R, 2)
assert r_mult == 2.75, r_mult
if __name__ == "__main__":
levels = [
Level(SUPORT, f"pivot daily {SUPORT:.2f} — zona (M)", BLUE, label_at="left"),
Level(SL, f"SL {SL:.2f} = 0.10 sub piciorul 2 (risc {R:.2f})", RED),
Level(TP1, f"TP1 {TP1:.2f} = 1:1", GREEN, label_at="left"),
]
marks = [
Mark(LEG1, f"piciorul 1: low {leg1_l:.2f}", GRAY, "below"),
Mark(TRIG, f"piciorul 2: low {leg2_l:.2f}", RED, "below", dy=16),
]
arrows = [
Arrow(TRIG, "Buy Hammer: coadă lungă în jos\nvânzătorii au dus prețul sub nivel\nși nu l-au putut ține acolo",
where="below", price=leg2_l, color=RED, dx=210, dy=58),
Arrow(CONF, f"intrare {ENTRY:.2f}: intri abia aici,\nla close peste high-ul candelei-trigger",
where="above", color=GREEN, dx=40, dy=-44),
Arrow(EXIT_I, f"ieșire pe trail {cds[EXIT_I].c:.2f} = {r_mult:.2f}R\nprima închidere sub linia de trail",
where="right", color=GREEN, dy=-6),
]
ch = Chart(
candles=cds, levels=levels, marks=marks, zones=[
Zone(LEG1, CONF, "M (zonă + divergență) → A (trigger) → P (plan)", BLUE)],
arrows=arrows,
mas=[MA(20, ORANGE, dash="4 3", text="SMA-20")],
scale=48.0, gap=15, body_w=9, left=44, width=660, top=74, vol_h=70,
vol_label="volum: la piciorul 2, volum mai mare decât la piciorul 1 = divergență",
)
svg = ch.render()
TITLE = ["SPY — 5 min (exemplu construit pe scara lecției;",
"cifrele planului nu vin din curs)"]
title_svg = "\n ".join(
f'<text x="24" y="{26 + 18 * i}" fill="#333" style="font-weight:bold">{t}</text>'
for i, t in enumerate(TITLE))
i = svg.index(">") + 1
svg = svg[:i] + "\n " + title_svg + svg[i:]
m = re.search(r'viewBox="0 0 (\d+) ([0-9.]+)"', svg)
W, H0 = int(m.group(1)), float(m.group(2))
legend = [
"Legendă: structura M → A → P e a cursului; nivelurile (590.00, 589.50) și planul",
"(intrare, SL, TP) sunt exemplul construit al autorului sumarului, nu citate din curs.",
]
legend_svg = [f'<text x="24" y="{H0 + 16 + 17 * i:.1f}" fill="#555">{t}</text>'
for i, t in enumerate(legend)]
new_h = H0 + 16 + 17 * (len(legend) - 1) + 14
svg = re.sub(r'(viewBox="0 0 \d+ )[0-9.]+(")',
lambda mm: mm.group(1) + f"{new_h:.0f}" + mm.group(2), svg, count=1)
svg = svg.replace("\n</svg>", "\n " + "\n ".join(legend_svg) + "\n</svg>")
assert "\n\n" not in svg, "linie goală în SVG"
OUT.write_text(svg)
print(f"scris {OUT.name}: picior 1 {leg1_l:.2f} / picior 2 {leg2_l:.2f} sub {SUPORT:.2f}, "
f"intrare {ENTRY:.2f}, SL {SL:.2f} (risc {R:.2f}), TP1 {TP1:.2f}, ieșire {r_mult:.2f}R")

View File

@@ -1,109 +1,132 @@
<svg viewBox="0 0 640 591" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif">
<svg viewBox="0 0 785 735" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif">
<text x="24" y="26" fill="#333" style="font-weight:bold">SPY — 5 min (exemplu construit pe scara lecției;</text>
<text x="24" y="44" fill="#333" style="font-weight:bold">cifrele planului nu vin din curs)</text>
<line x1="24" y1="392.8" x2="626" y2="392.8" stroke="#1a5fb4" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30" y="386.8" fill="#1a5fb4">suport / pivot 590.00</text>
<line x1="24" y1="421.6" x2="626" y2="421.6" stroke="#c00" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30" y="415.6" fill="#c00">SL 589.40 — risc 0.80</text>
<line x1="24" y1="344.8" x2="626" y2="344.8" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30" y="338.8" fill="#188a3e">TP1 591.00 = 1:1</text>
<polyline points="329.0,286.4 344.0,299.3 359.0,309.6 374.0,320.7 389.0,329.1 404.0,336.3 419.0,341.0 434.0,345.8 449.0,348.0 464.0,348.2 479.0,346.2" fill="none" stroke="#b06000" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="485" y="340" fill="#b06000">SMA-20</text>
<line x1="44.0" y1="64.0" x2="44.0" y2="119.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="39.5" y="76.0" width="9" height="28.8" fill="#c00"/>
<line x1="59.0" y1="92.8" x2="59.0" y2="157.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="54.5" y="104.8" width="9" height="38.4" fill="#c00"/>
<line x1="74.0" y1="112.0" x2="74.0" y2="157.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="69.5" y="124.0" width="9" height="19.2" fill="#188a3e"/>
<line x1="89.0" y1="112.0" x2="89.0" y2="176.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="84.5" y="124.0" width="9" height="38.4" fill="#c00"/>
<line x1="104.0" y1="150.4" x2="104.0" y2="210.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="99.5" y="162.4" width="9" height="33.6" fill="#c00"/>
<line x1="119.0" y1="184.0" x2="119.0" y2="244.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="114.5" y="196.0" width="9" height="33.6" fill="#c00"/>
<line x1="134.0" y1="203.2" x2="134.0" y2="244.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="129.5" y="215.2" width="9" height="14.4" fill="#188a3e"/>
<line x1="149.0" y1="203.2" x2="149.0" y2="268.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="144.5" y="215.2" width="9" height="38.4" fill="#c00"/>
<line x1="164.0" y1="241.6" x2="164.0" y2="301.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="159.5" y="253.6" width="9" height="33.6" fill="#c00"/>
<line x1="179.0" y1="275.2" x2="179.0" y2="330.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="174.5" y="287.2" width="9" height="28.8" fill="#c00"/>
<line x1="194.0" y1="289.6" x2="194.0" y2="330.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="189.5" y="301.6" width="9" height="14.4" fill="#188a3e"/>
<line x1="209.0" y1="289.6" x2="209.0" y2="344.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="204.5" y="301.6" width="9" height="28.8" fill="#c00"/>
<line x1="224.0" y1="318.4" x2="224.0" y2="368.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="219.5" y="330.4" width="9" height="24.0" fill="#c00"/>
<line x1="239.0" y1="342.4" x2="239.0" y2="392.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="234.5" y="354.4" width="9" height="24.0" fill="#c00"/>
<line x1="254.0" y1="354.4" x2="254.0" y2="392.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="249.5" y="366.4" width="9" height="12.0" fill="#188a3e"/>
<line x1="269.0" y1="354.4" x2="269.0" y2="402.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="264.5" y="366.4" width="9" height="21.6" fill="#c00"/>
<line x1="284.0" y1="376.0" x2="284.0" y2="414.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="279.5" y="388.0" width="9" height="12.0" fill="#c00"/>
<line x1="299.0" y1="378.4" x2="299.0" y2="414.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="294.5" y="390.4" width="9" height="9.6" fill="#188a3e"/>
<line x1="314.0" y1="385.6" x2="314.0" y2="421.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="309.5" y="390.4" width="9" height="12.0" fill="#c00"/>
<line x1="329.0" y1="378.4" x2="329.0" y2="404.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="324.5" y="383.2" width="9" height="19.2" fill="#188a3e"/>
<line x1="344.0" y1="352.0" x2="344.0" y2="397.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="339.5" y="364.0" width="9" height="19.2" fill="#188a3e"/>
<line x1="359.0" y1="347.2" x2="359.0" y2="378.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="354.5" y="349.6" width="9" height="14.4" fill="#188a3e"/>
<line x1="374.0" y1="332.8" x2="374.0" y2="364.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="369.5" y="344.8" width="9" height="4.8" fill="#188a3e"/>
<line x1="389.0" y1="318.4" x2="389.0" y2="359.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="384.5" y="330.4" width="9" height="14.4" fill="#188a3e"/>
<line x1="404.0" y1="318.4" x2="404.0" y2="354.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="399.5" y="330.4" width="9" height="9.6" fill="#c00"/>
<line x1="419.0" y1="311.2" x2="419.0" y2="354.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="414.5" y="323.2" width="9" height="16.8" fill="#188a3e"/>
<line x1="434.0" y1="299.2" x2="434.0" y2="337.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="429.5" y="311.2" width="9" height="12.0" fill="#188a3e"/>
<line x1="449.0" y1="287.2" x2="449.0" y2="325.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="444.5" y="299.2" width="9" height="12.0" fill="#188a3e"/>
<line x1="464.0" y1="277.6" x2="464.0" y2="313.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="459.5" y="289.6" width="9" height="9.6" fill="#188a3e"/>
<line x1="479.0" y1="265.6" x2="479.0" y2="304.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="474.5" y="277.6" width="9" height="12.0" fill="#188a3e"/>
<line x1="24" y1="517.6" x2="626" y2="517.6" stroke="#888"/>
<rect x="39.5" y="478.1" width="9" height="39.5" fill="#c00" opacity="0.55"/>
<rect x="54.5" y="479.7" width="9" height="37.9" fill="#c00" opacity="0.55"/>
<rect x="69.5" y="481.4" width="9" height="36.2" fill="#188a3e" opacity="0.55"/>
<rect x="84.5" y="480.5" width="9" height="37.1" fill="#c00" opacity="0.55"/>
<rect x="99.5" y="482.2" width="9" height="35.4" fill="#c00" opacity="0.55"/>
<rect x="114.5" y="483.8" width="9" height="33.8" fill="#c00" opacity="0.55"/>
<rect x="129.5" y="484.7" width="9" height="32.9" fill="#188a3e" opacity="0.55"/>
<rect x="144.5" y="483.0" width="9" height="34.6" fill="#c00" opacity="0.55"/>
<rect x="159.5" y="481.4" width="9" height="36.2" fill="#c00" opacity="0.55"/>
<rect x="174.5" y="479.7" width="9" height="37.9" fill="#c00" opacity="0.55"/>
<rect x="189.5" y="474.8" width="9" height="42.8" fill="#188a3e" opacity="0.55"/>
<rect x="204.5" y="486.3" width="9" height="31.3" fill="#c00" opacity="0.55"/>
<rect x="219.5" y="484.7" width="9" height="32.9" fill="#c00" opacity="0.55"/>
<rect x="234.5" y="483.0" width="9" height="34.6" fill="#c00" opacity="0.55"/>
<rect x="249.5" y="485.5" width="9" height="32.1" fill="#188a3e" opacity="0.55"/>
<rect x="264.5" y="481.4" width="9" height="36.2" fill="#c00" opacity="0.55"/>
<rect x="279.5" y="476.4" width="9" height="41.2" fill="#c00" opacity="0.55"/>
<rect x="294.5" y="469.8" width="9" height="47.8" fill="#188a3e" opacity="0.55"/>
<rect x="309.5" y="458.3" width="9" height="59.3" fill="#c00" opacity="0.55"/>
<rect x="324.5" y="447.6" width="9" height="70.0" fill="#188a3e" opacity="0.55"/>
<rect x="339.5" y="460.0" width="9" height="57.6" fill="#188a3e" opacity="0.55"/>
<rect x="354.5" y="464.9" width="9" height="52.7" fill="#188a3e" opacity="0.55"/>
<rect x="369.5" y="469.8" width="9" height="47.8" fill="#188a3e" opacity="0.55"/>
<rect x="384.5" y="468.2" width="9" height="49.4" fill="#188a3e" opacity="0.55"/>
<rect x="399.5" y="472.3" width="9" height="45.3" fill="#c00" opacity="0.55"/>
<rect x="414.5" y="474.8" width="9" height="42.8" fill="#188a3e" opacity="0.55"/>
<rect x="429.5" y="476.4" width="9" height="41.2" fill="#188a3e" opacity="0.55"/>
<rect x="444.5" y="478.1" width="9" height="39.5" fill="#188a3e" opacity="0.55"/>
<rect x="459.5" y="479.7" width="9" height="37.9" fill="#188a3e" opacity="0.55"/>
<rect x="474.5" y="481.4" width="9" height="36.2" fill="#188a3e" opacity="0.55"/>
<text x="24" y="441.6" fill="#555">volum</text>
<text x="314.0" y="435.6" fill="#c00" text-anchor="middle" style="font-weight:bold">minim 589.80 — divergență (M)</text>
<text x="329.0" y="322.4" fill="#188a3e" text-anchor="middle" style="font-weight:bold">intrare 590.20</text>
<text x="479.0" y="255.6" fill="#188a3e" text-anchor="middle" style="font-weight:bold">ieșire trail 592.40</text>
<text x="24" y="560.0" fill="#555">Legendă: entry/SL/TP/trail sunt exemplul construit al autorului sumarului,</text>
<text x="24" y="577.0" fill="#555">nu citate din curs (transcrierea se întrerupe înainte de planul numeric).</text>
<rect x="184.5" y="306.0" width="154.0" height="128.8" fill="#1a5fb4" fill-opacity="0.08" stroke="#1a5fb4" stroke-width="1"/>
<text x="184.5" y="278.6" fill="#1a5fb4" style="font-weight:bold">M (zonă + divergență) → A (trigger) → P (plan)</text>
<line x1="24" y1="402.8" x2="771" y2="402.8" stroke="#1a5fb4" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30" y="396.8" fill="#1a5fb4">pivot daily 590.00 — zona (M)</text>
<line x1="24" y1="431.6" x2="771" y2="431.6" stroke="#c00" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="757" y="425.6" fill="#c00" text-anchor="end">SL 589.40 = 0.10 sub piciorul 2 (risc 0.80)</text>
<line x1="24" y1="354.8" x2="771" y2="354.8" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30" y="348.8" fill="#188a3e">TP1 591.00 = 1:1</text>
<polyline points="329.0,292.3 344.0,305.2 359.0,315.6 374.0,326.6 389.0,335.0 404.0,342.2 419.0,346.9 434.0,351.7 449.0,354.0 464.0,354.1 479.0,351.2 494.0,344.7 509.0,339.9 524.0,337.5" fill="none" stroke="#b06000" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="530" y="332" fill="#b06000">SMA-20</text>
<line x1="44.0" y1="74.0" x2="44.0" y2="129.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="39.5" y="86.0" width="9" height="28.8" fill="#c00"/>
<line x1="59.0" y1="102.8" x2="59.0" y2="167.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="54.5" y="114.8" width="9" height="38.4" fill="#c00"/>
<line x1="74.0" y1="122.0" x2="74.0" y2="167.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="69.5" y="134.0" width="9" height="19.2" fill="#188a3e"/>
<line x1="89.0" y1="122.0" x2="89.0" y2="186.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="84.5" y="134.0" width="9" height="38.4" fill="#c00"/>
<line x1="104.0" y1="160.4" x2="104.0" y2="220.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="99.5" y="172.4" width="9" height="33.6" fill="#c00"/>
<line x1="119.0" y1="194.0" x2="119.0" y2="254.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="114.5" y="206.0" width="9" height="33.6" fill="#c00"/>
<line x1="134.0" y1="213.2" x2="134.0" y2="254.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="129.5" y="225.2" width="9" height="14.4" fill="#188a3e"/>
<line x1="149.0" y1="213.2" x2="149.0" y2="278.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="144.5" y="225.2" width="9" height="38.4" fill="#c00"/>
<line x1="164.0" y1="251.6" x2="164.0" y2="311.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="159.5" y="263.6" width="9" height="33.6" fill="#c00"/>
<line x1="179.0" y1="285.2" x2="179.0" y2="340.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="174.5" y="297.2" width="9" height="28.8" fill="#c00"/>
<line x1="194.0" y1="314.0" x2="194.0" y2="398.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="189.5" y="326.0" width="9" height="57.6" fill="#c00"/>
<line x1="209.0" y1="347.6" x2="209.0" y2="398.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="204.5" y="359.6" width="9" height="24.0" fill="#188a3e"/>
<line x1="224.0" y1="323.6" x2="224.0" y2="374.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="219.5" y="335.6" width="9" height="24.0" fill="#188a3e"/>
<line x1="239.0" y1="323.6" x2="239.0" y2="364.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="234.5" y="335.6" width="9" height="14.4" fill="#c00"/>
<line x1="254.0" y1="328.4" x2="254.0" y2="364.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="249.5" y="340.4" width="9" height="9.6" fill="#188a3e"/>
<line x1="269.0" y1="328.4" x2="269.0" y2="374.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="264.5" y="340.4" width="9" height="19.2" fill="#c00"/>
<line x1="284.0" y1="350.0" x2="284.0" y2="386.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="279.5" y="359.6" width="9" height="19.2" fill="#c00"/>
<line x1="299.0" y1="371.6" x2="299.0" y2="405.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="294.5" y="378.8" width="9" height="21.6" fill="#c00"/>
<line x1="314.0" y1="395.6" x2="314.0" y2="426.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="309.5" y="400.4" width="9" height="12.0" fill="#c00"/>
<line x1="329.0" y1="388.4" x2="329.0" y2="414.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="324.5" y="393.2" width="9" height="19.2" fill="#188a3e"/>
<line x1="344.0" y1="362.0" x2="344.0" y2="400.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="339.5" y="374.0" width="9" height="19.2" fill="#188a3e"/>
<line x1="359.0" y1="357.2" x2="359.0" y2="381.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="354.5" y="359.6" width="9" height="14.4" fill="#188a3e"/>
<line x1="374.0" y1="342.8" x2="374.0" y2="374.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="369.5" y="354.8" width="9" height="4.8" fill="#188a3e"/>
<line x1="389.0" y1="328.4" x2="389.0" y2="369.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="384.5" y="340.4" width="9" height="14.4" fill="#188a3e"/>
<line x1="404.0" y1="328.4" x2="404.0" y2="364.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="399.5" y="340.4" width="9" height="9.6" fill="#c00"/>
<line x1="419.0" y1="321.2" x2="419.0" y2="364.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="414.5" y="333.2" width="9" height="16.8" fill="#188a3e"/>
<line x1="434.0" y1="309.2" x2="434.0" y2="347.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="429.5" y="321.2" width="9" height="12.0" fill="#188a3e"/>
<line x1="449.0" y1="297.2" x2="449.0" y2="335.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="444.5" y="309.2" width="9" height="12.0" fill="#188a3e"/>
<line x1="464.0" y1="287.6" x2="464.0" y2="323.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="459.5" y="299.6" width="9" height="9.6" fill="#188a3e"/>
<line x1="479.0" y1="256.4" x2="479.0" y2="314.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="474.5" y="268.4" width="9" height="31.2" fill="#188a3e"/>
<line x1="494.0" y1="242.0" x2="494.0" y2="282.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="489.5" y="254.0" width="9" height="14.4" fill="#188a3e"/>
<line x1="509.0" y1="242.0" x2="509.0" y2="278.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="504.5" y="254.0" width="9" height="9.6" fill="#c00"/>
<line x1="524.0" y1="251.6" x2="524.0" y2="302.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="519.5" y="263.6" width="9" height="24.0" fill="#c00"/>
<line x1="24" y1="661.8" x2="771" y2="661.8" stroke="#888"/>
<rect x="39.5" y="623.6" width="9" height="38.2" fill="#c00" opacity="0.55"/>
<rect x="54.5" y="625.2" width="9" height="36.6" fill="#c00" opacity="0.55"/>
<rect x="69.5" y="626.8" width="9" height="35.0" fill="#188a3e" opacity="0.55"/>
<rect x="84.5" y="626.0" width="9" height="35.8" fill="#c00" opacity="0.55"/>
<rect x="99.5" y="627.6" width="9" height="34.2" fill="#c00" opacity="0.55"/>
<rect x="114.5" y="629.2" width="9" height="32.6" fill="#c00" opacity="0.55"/>
<rect x="129.5" y="630.0" width="9" height="31.8" fill="#188a3e" opacity="0.55"/>
<rect x="144.5" y="628.4" width="9" height="33.4" fill="#c00" opacity="0.55"/>
<rect x="159.5" y="626.8" width="9" height="35.0" fill="#c00" opacity="0.55"/>
<rect x="174.5" y="625.2" width="9" height="36.6" fill="#c00" opacity="0.55"/>
<rect x="189.5" y="620.4" width="9" height="41.4" fill="#c00" opacity="0.55"/>
<rect x="204.5" y="631.6" width="9" height="30.2" fill="#188a3e" opacity="0.55"/>
<rect x="219.5" y="630.0" width="9" height="31.8" fill="#188a3e" opacity="0.55"/>
<rect x="234.5" y="628.4" width="9" height="33.4" fill="#c00" opacity="0.55"/>
<rect x="249.5" y="630.8" width="9" height="31.0" fill="#188a3e" opacity="0.55"/>
<rect x="264.5" y="626.8" width="9" height="35.0" fill="#c00" opacity="0.55"/>
<rect x="279.5" y="622.0" width="9" height="39.8" fill="#c00" opacity="0.55"/>
<rect x="294.5" y="615.7" width="9" height="46.1" fill="#c00" opacity="0.55"/>
<rect x="309.5" y="591.8" width="9" height="70.0" fill="#c00" opacity="0.55"/>
<rect x="324.5" y="598.2" width="9" height="63.6" fill="#188a3e" opacity="0.55"/>
<rect x="339.5" y="606.1" width="9" height="55.7" fill="#188a3e" opacity="0.55"/>
<rect x="354.5" y="610.9" width="9" height="50.9" fill="#188a3e" opacity="0.55"/>
<rect x="369.5" y="615.7" width="9" height="46.1" fill="#188a3e" opacity="0.55"/>
<rect x="384.5" y="614.1" width="9" height="47.7" fill="#188a3e" opacity="0.55"/>
<rect x="399.5" y="618.1" width="9" height="43.8" fill="#c00" opacity="0.55"/>
<rect x="414.5" y="620.4" width="9" height="41.4" fill="#188a3e" opacity="0.55"/>
<rect x="429.5" y="622.0" width="9" height="39.8" fill="#188a3e" opacity="0.55"/>
<rect x="444.5" y="623.6" width="9" height="38.2" fill="#188a3e" opacity="0.55"/>
<rect x="459.5" y="625.2" width="9" height="36.6" fill="#188a3e" opacity="0.55"/>
<rect x="474.5" y="620.4" width="9" height="41.4" fill="#188a3e" opacity="0.55"/>
<rect x="489.5" y="623.6" width="9" height="38.2" fill="#188a3e" opacity="0.55"/>
<rect x="504.5" y="628.4" width="9" height="33.4" fill="#c00" opacity="0.55"/>
<rect x="519.5" y="625.2" width="9" height="36.6" fill="#c00" opacity="0.55"/>
<text x="24" y="585.8" fill="#555">volum: la piciorul 2, volum mai mare decât la piciorul 1 = divergență</text>
<text x="194.0" y="418.0" fill="#777" text-anchor="middle" style="font-weight:bold">piciorul 1: low 590.10</text>
<text x="314.0" y="445.6" fill="#c00" text-anchor="middle" style="font-weight:bold">piciorul 2: low 589.50</text>
<line x1="524.0" y1="514.8" x2="321.4" y2="433.8" stroke="#c00" stroke-width="1.8"/>
<polygon points="314.0,430.8 322.9,430.1 319.9,437.5" fill="#c00"/>
<text x="524.0" y="528.8" fill="#c00" text-anchor="middle" style="font-weight:bold">Buy Hammer: coadă lungă în jos</text>
<text x="524.0" y="542.8" fill="#c00" text-anchor="middle" style="font-weight:bold">vânzătorii au dus prețul sub nivel</text>
<text x="524.0" y="556.8" fill="#c00" text-anchor="middle" style="font-weight:bold">și nu l-au putut ține acolo</text>
<line x1="369.0" y1="190.0" x2="330.6" y2="376.6" stroke="#188a3e" stroke-width="1.8"/>
<polygon points="329.0,384.4 326.7,375.8 334.5,377.4" fill="#188a3e"/>
<text x="369.0" y="171.0" fill="#188a3e" text-anchor="middle" style="font-weight:bold">intrare 590.20: intri abia aici,</text>
<text x="369.0" y="185.0" fill="#188a3e" text-anchor="middle" style="font-weight:bold">la close peste high-ul candelei-trigger</text>
<line x1="562.5" y1="281.6" x2="540.3" y2="286.0" stroke="#188a3e" stroke-width="1.8"/>
<polygon points="532.5,287.6 539.6,282.1 541.1,290.0" fill="#188a3e"/>
<text x="566.5" y="278.6" fill="#188a3e" text-anchor="start" style="font-weight:bold">ieșire pe trail 592.40 = 2.75R</text>
<text x="566.5" y="292.6" fill="#188a3e" text-anchor="start" style="font-weight:bold">prima închidere sub linia de trail</text>
<text x="24" y="704.0" fill="#555">Legendă: structura M → A → P e a cursului; nivelurile (590.00, 589.50) și planul</text>
<text x="24" y="721.0" fill="#555">(intrare, SL, TP) sunt exemplul construit al autorului sumarului, nu citate din curs.</text>
</svg>

Before

Width:  |  Height:  |  Size: 8.8 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -30,9 +30,10 @@ GRAY, RED, GREEN, BLUE, ORANGE = "#777", "#c00", "#188a3e", "#1a5fb4", "#b06000"
PIVOT = 622.00 # pivot daily, suportul
LEG1 = 622.40 # swing low picior 1
LEG2 = 621.40 # picior 2 (mai jos, rupe pivotul)
ENTRY = 622.60 # close-ul Buy Hammer (construit)
HAMMER_C = 622.60 # close-ul Buy Hammer — cifră reală, din sesiunea Q&A
ENTRY = 623.00 # close-ul candelei care sparge high-ul hammer-ului (construit)
SL = 621.30 # 0.10 sub low-ul piciorului 2 (construit)
TP1 = 623.90 # entry + risc = 1:1 (construit)
TP1 = 624.70 # entry + risc = 1:1 (construit)
# ── seria: 30 de close-uri, exact ca în specificație ───────────────────────
CLOSES = [
@@ -100,11 +101,13 @@ assert abs(corp - 0.30) < 1e-9, corp
assert abs(coada - 0.90) < 1e-9, coada
assert coada > corp, (coada, corp)
# 6. entry = close-ul trigger-ului (construit), SL 0.10 sub low-ul piciorului 2
assert cds[18].c == ENTRY
# 6. regula de intrare a capitolului: close-ul candelei care sparge high-ul
# candelei-trigger (aici bara 19), nu close-ul hammer-ului însuși
assert cds[18].c == HAMMER_C
assert cds[19].c == ENTRY and cds[19].c > cds[18].h, (cds[19].c, cds[18].h)
assert abs(cds[18].l - SL - 0.10) < 1e-9, (cds[18].l, SL)
risk = ENTRY - SL
assert abs(risk - 1.30) < 1e-9, risk
risk = round(ENTRY - SL, 2)
assert risk == 1.70, risk
# 7. TP1 simetric 1:1
assert abs((ENTRY - SL) - (TP1 - ENTRY)) < 1e-9
@@ -112,9 +115,9 @@ assert abs((ENTRY - SL) - (TP1 - ENTRY)) < 1e-9
# 8. după trigger, primul close care atinge 623.90 e bara 21 (nu mai devreme).
# Seria pornește la 627.00, deci „atinge" se citește de jos în sus, din zona
# picioarelor: barele 10-20 rămân sub TP1, bara 21 îl atinge.
assert all(c.c < TP1 for c in cds[10:21]), [c.c for c in cds[10:21]]
assert max(c.h for c in cds[19:21]) < TP1, [c.h for c in cds[19:21]]
assert cds[21].c == TP1, cds[21].c
assert max(c.h for c in cds[19:25]) < TP1, [c.h for c in cds[19:25]]
assert cds[25].h >= TP1 > cds[25].o, (cds[25].h, cds[25].o)
TP_BAR = 25
# 9. divergență: lower low pe preț, higher low pe volum
assert cds[18].l < cds[10].l, (cds[18].l, cds[10].l)
@@ -136,9 +139,8 @@ def cx(i: int) -> float:
levels = [
Level(PIVOT, "pivot daily 622.00", ORANGE, label_at="left"),
Level(SL, "SL 621.30 (construit)", RED, label_at="left"),
Level(ENTRY, "intrare 622.60 (construit)", GREEN, label_at="left"),
Level(TP1, "TP1 623.90 = 1:1 (construit)", GREEN, label_at="left"),
Level(LEG1, "picior 1 = 622.40", BLUE, label_at="right"),
Level(ENTRY, "intrare 623.00 (construit)", GREEN, label_at="right"),
Level(TP1, "TP1 624.70 = 1:1 (construit)", GREEN, label_at="left"),
]
# dy-uri calculate manual ca etichetele „below" să nu calce linia pivotului
@@ -146,7 +148,8 @@ levels = [
marks = [
Mark(10, "picior 1 = 622.40", BLUE, "below", dy=15),
Mark(18, "picior 2 = 621.40 (mai jos) · Buy Hammer", RED, "below"),
Mark(18, "hammer închide 622.60, înapoi peste pivot", GREEN, "above", dy=-20),
Mark(18, "hammer închide 622.60, înapoi peste pivot", GREEN, "above", dy=-42),
Mark(19, "intri aici: close peste high-ul hammer-ului", GREEN, "above", dy=-62),
]
ch = Chart(
@@ -162,7 +165,7 @@ svg = ch.render()
# ── legenda de onestitate (assert 11): ce e real, ce e construit ───────────
legend = [
"Legendă: nivelurile 622.40 / 622.00 / 621.40 / 622.60 și cele 8 candele dintre",
"picioare sunt reale, din curs. Intrarea 622.60, SL-ul 621.30 și TP-ul 623.90",
"picioare sunt reale, din curs. Intrarea 623.00, SL-ul 621.30 și TP-ul 624.70",
"sunt construcția mea — materialul nu le dă.",
]
m = re.search(r'viewBox="0 0 (\d+) ([0-9.]+)"', svg)
@@ -182,8 +185,8 @@ assert "sunt reale, din curs" in svg and "construcția mea" in svg, \
for eticheta in ("pivot daily 622.00", "picior 1 = 622.40",
"picior 2 = 621.40 (mai jos) · Buy Hammer",
"hammer închide 622.60, înapoi peste pivot",
"intrare 622.60 (construit)", "SL 621.30 (construit)",
"TP1 623.90 = 1:1 (construit)"):
"intrare 623.00 (construit)", "SL 621.30 (construit)",
"TP1 624.70 = 1:1 (construit)"):
assert eticheta in svg, f"lipsește eticheta: {eticheta!r}"
assert "SPY — 5 min" in svg, "lipsește titlul"
@@ -218,5 +221,5 @@ OUT.write_text(svg, encoding="utf-8")
print(f"scris {OUT.name}: {len(cds)} candele | picior 1 {cds[10].l:.2f} (close "
f"{cds[10].c:.2f}) | picior 2 {cds[18].l:.2f} (mai jos) | hammer închide "
f"{cds[18].c:.2f} | intrare {ENTRY:.2f} | SL {SL:.2f} (risc {risk:.2f}) | "
f"TP1 {TP1:.2f} = {(TP1 - ENTRY) / risk:.2f}:1 la bara 21 | "
f"TP1 {TP1:.2f} = {(TP1 - ENTRY) / risk:.2f}:1 la bara {TP_BAR} | "
f"vol[18]={VOLS[18]} > vol[10]={VOLS[10]}")

View File

@@ -4,12 +4,10 @@
<text x="30" y="367.4" fill="#b06000">pivot daily 622.00</text>
<line x1="24" y1="416.8" x2="626" y2="416.8" stroke="#c00" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30" y="410.8" fill="#c00">SL 621.30 (construit)</text>
<line x1="24" y1="336.2" x2="626" y2="336.2" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30" y="330.2" fill="#188a3e">intrare 622.60 (construit)</text>
<line x1="24" y1="255.6" x2="626" y2="255.6" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30" y="249.6" fill="#188a3e">TP1 623.90 = 1:1 (construit)</text>
<line x1="24" y1="348.6" x2="626" y2="348.6" stroke="#1a5fb4" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="612" y="342.6" fill="#1a5fb4" text-anchor="end">picior 1 = 622.40</text>
<line x1="24" y1="311.4" x2="626" y2="311.4" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="612" y="305.4" fill="#188a3e" text-anchor="end">intrare 623.00 (construit)</text>
<line x1="24" y1="206.0" x2="626" y2="206.0" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30" y="200.0" fill="#188a3e">TP1 624.70 = 1:1 (construit)</text>
<polyline points="329.0,253.2 344.0,264.3 359.0,272.1 374.0,279.8 389.0,286.0 404.0,289.1 419.0,289.1 434.0,286.6 449.0,281.1 464.0,274.5 479.0,265.6" fill="none" stroke="#b06000" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="485" y="260" fill="#b06000">SMA-20</text>
<line x1="44.0" y1="57.2" x2="44.0" y2="69.6" stroke="#1a1a1a" stroke-width="1.2"/>
@@ -106,8 +104,9 @@
<text x="24" y="436.8" fill="#555">volum</text>
<text x="194.0" y="386.7" fill="#1a5fb4" text-anchor="middle" style="font-weight:bold">picior 1 = 622.40</text>
<text x="314.0" y="430.6" fill="#c00" text-anchor="middle" style="font-weight:bold">picior 2 = 621.40 (mai jos) · Buy Hammer</text>
<text x="314.0" y="300.0" fill="#188a3e" text-anchor="middle" style="font-weight:bold">hammer închide 622.60, înapoi peste pivot</text>
<text x="314.0" y="278.0" fill="#188a3e" text-anchor="middle" style="font-weight:bold">hammer închide 622.60, înapoi peste pivot</text>
<text x="329.0" y="232.0" fill="#188a3e" text-anchor="middle" style="font-weight:bold">intri aici: close peste high-ul hammer-ului</text>
<text x="24" y="555.0" fill="#555">Legendă: nivelurile 622.40 / 622.00 / 621.40 / 622.60 și cele 8 candele dintre</text>
<text x="24" y="572.0" fill="#555">picioare sunt reale, din curs. Intrarea 622.60, SL-ul 621.30 și TP-ul 623.90</text>
<text x="24" y="572.0" fill="#555">picioare sunt reale, din curs. Intrarea 623.00, SL-ul 621.30 și TP-ul 624.70</text>
<text x="24" y="589.0" fill="#555">sunt construcția mea — materialul nu le dă.</text>
</svg>

Before

Width:  |  Height:  |  Size: 9.2 KiB

After

Width:  |  Height:  |  Size: 9.2 KiB

View File

@@ -113,12 +113,7 @@ add(W / 2, 468,
add(W / 2, 486,
"aliniere în cadranul 1, nu divergență (contradicția 2.4).",
13, "normal", GRAY)
add(W / 2, 512,
"Sursa: 05_MODUL_4/02_strategia_5_mdsrt.md:6-8, 34-42, 59-61, 85-88;",
13, "normal", GRAY)
add(W / 2, 530,
"08_ANALIZA_ZILNICA/11_selectia_simbolului.md:612-627.",
13, "normal", GRAY)
# trimiterile la material stau în fișa de surse a capitolului, nu pe desen
# --------------------------------------------------------------- emitere
head = (f'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 {W} {H}" '
@@ -127,6 +122,7 @@ head = (f'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 {W} {H}" '
f'Volume sau Relative Strength; varianta Trinity are toți trei '
f'indicatori în divergență simultan, pe aceeași zonă de preț">')
parts.insert(0, f'<rect x="0" y="0" width="{W}" height="{H}" fill="#ffffff"/>')
assert ".md:" not in "".join(parts), "trimiteri fișier:linie pe desen"
parts.insert(0, head)
body = []

View File

@@ -25,6 +25,4 @@
<text x="350.0" y="448.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="middle">La MDSRT, „Trinity” se folosește local cu sensul „toți trei în divergență”.</text>
<text x="350.0" y="468.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="middle">Lecția de selecție dă aceluiași cuvânt alt sens:</text>
<text x="350.0" y="486.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="middle">aliniere în cadranul 1, nu divergență (contradicția 2.4).</text>
<text x="350.0" y="512.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="middle">Sursa: 05_MODUL_4/02_strategia_5_mdsrt.md:6-8, 34-42, 59-61, 85-88;</text>
<text x="350.0" y="530.0" font-size="13" font-weight="normal" fill="#777777" text-anchor="middle">08_ANALIZA_ZILNICA/11_selectia_simbolului.md:612-627.</text>
</svg>

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@@ -389,7 +389,7 @@ formulă de tip „risc % din cont"** în material pentru ATMI.
Aceeași corecție, două deznodăminte. Diagrama le pune alături.
<!-- DIAGRAMA: aplus -->
<!-- DIAGRAMA: corectie -->
<svg viewBox="0 0 680 508" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif">
<rect x="24" y="221.6" width="642" height="18.0" fill="#777" opacity="0.10"/>
<text x="24" y="48" fill="#333" style="font-weight:bold">SPY — daily: aceeași corecție, 4.0 % (DA) vs. 3.9 % (NU)</text>
@@ -509,7 +509,7 @@ Aceeași corecție, două deznodăminte. Diagrama le pune alături.
<text x="24" y="183.8" fill="#188a3e" style="font-weight:bold">calea DA (candelele)</text>
<text x="444.0" y="272.7" fill="#c00" style="font-weight:bold">calea NU (continuă în jos)</text>
</svg>
<!-- /DIAGRAMA: aplus -->
<!-- /DIAGRAMA: corectie -->
| | **A+** | **Mediocru / NU** |
|---|---|---|

View File

@@ -0,0 +1,94 @@
# Surse — 5. ATMI
Trimiterile la material pentru [`05_atmi.md`](../05_atmi.md). Stau aici, nu în
capitol: în corpul tutorialului îngreunează cititul, dar fără ele nu se mai
poate verifica nimic. Cifrele sunt linii din fișierele de sumarizare, nu din
transcrieri.
Textul fără trimitere e explicația mea și nu adaugă reguli; ce completez eu
începe cu **Completare proprie**. Toate diagramele sunt exemple construite:
din curs vin regulile (corecție minim 4 %, zona quarterly, BIM înainte de
candela verde, ținta +10 %, fără stop) și cifrele exemplului SPY 2005
(117.43 → 129.17). Valorile pivoților — **PPQ 95.80, SQ 90.80** — sunt
calculate de mine cu formula standard, pentru că materialul spune explicit că
nu le dă.
**Prescurtări:**
`main` = [`03_strategia_2_atmi.md`](../../04_MODUL_3/03_strategia_2_atmi.md)
(lecția principală, integral) ·
`bim` = [`10_buysell_momentum_trigger.md`](../../03_MODUL_2/10_buysell_momentum_trigger.md)
(definiția indicatorului BIM) ·
`tf` = [`03_timeframes_set_up.md`](../../03_MODUL_2/03_timeframes_set_up.md)
(pivoți quarterly) ·
`filtre` = [`01_filtre_scaner_bull_bear_reversal_pp.md`](../../04_MODUL_3/01_filtre_scaner_bull_bear_reversal_pp.md)
(câmpul de scaner „PP or Support") ·
`DECIZII` = [`triaj/DECIZII.md`](../../../triaj/DECIZII.md) (registrul de triaj
al materialului) ·
fișierele datate sunt sesiuni Q&A din `../../09_QA/`.
**Nivelul 1 — ce face strategia** — `main`: 4-5, 5-6, 26-29, 31-45, 39-45,
164-169, 170-179, 505-508 · `27_2025-05-28`: 466-467.
**Pasul 1 — instrumentul, trimestrul și pivoții** — `main`: 6-8, 26-29,
47-54 (formula nu e explicitată cifric), 143 (cursul nu dă cifrele PPQ/SQ),
146-154 · `tf`: 73-79 · `filtre`: 29-34 · `14_2025-10-21`: 501-535
(indici precalculați în TradeStation) · `27_2025-05-28`: 466-467
(~2 tranzacții pe trimestru) · `09_2025-12-09`: 1177-1180 (pivoții clasici,
confirmați „1 la 1").
**Pasul 2 — corecția de minim 4 %** — `main`: 153-154, 249-319 (cazul de
3,93 % / 3,9 %), 502-504.
**Pasul 3 — zona SQ / PPQ** — `main`: 146-149 (intrarea sub SQ, rară, doar
în crize reale), 146-154, 151-179 (harta MAPP) · `12_2025-11-18`: 294-296 ·
`25_2025-07-08`: 840-843 · `13_2025-10-28`: 104 · `DECIZII`: 234, 324.
**Pasul 4 — BIM, apoi prima candelă verde** — `main`: 156-159 (verdele de
dinainte de BIM nu e trigger), 156-162, 159-162 (ideal închide deasupra
pivotului), 16-21 (ATMI trimite la BIM fără să-l definească), 497-501
(„cuțitul prins în cădere") · `bim`: 3-12 (definiția: `jbv2`, două moving
averages, săgeți cyan/crimson).
**Pasul 5 — fără stop, mărimea contribuției** — `main`: 10-11, 164-169
(absența stopului e regulă), 166-169 (opțional -100 % pe poziție), 173-175
(1 unitate SPY ≈ 600 $, ajustabil 0.2-0.5), 470-489 (levierul), 491-494
(drawdown 20-30 % pe poziție, ~3 momente în 20 de ani), 509-512 ·
`11_2025-11-25`: 489-500, 498-500 (dimensionezi ca și cum poți pierde 100 %) ·
`04_2026-08-04`: 194-195 (lichiditatea ETF-urilor cu levier), 217-220
(riscul e emoțional, nu matematic) · `13_2025-10-28`: 69-72 (CFD-urile, doar
1-3 zile).
**Pasul 6 — ieșirea la +10 % și reinvestirea** — `main`: 170-171 (ieși cu
toată poziția), 176-177 (cash până la următorul trigger), 178-179
(reinvestești tot + contribuția nouă), 321-356 (dobânda compusă), 349-356
(poziții în paralel, cu maturități diferite), 465-468 (backtest: ~16.300 $ în
20 de ani → ~52-53.000 $) · `27_2025-05-28`: 456-467, 462-467 (aceleași cifre,
altă formulare; estimarea de 16.000 → 100.000 după a doua reinvestire).
**A+ vs. mediocru** — `main`: 31-45 (mecanismul Buffett), 146-154, 156-162,
159-162, 185-247 (exemplul „DA"), 249-319 (exemplul „NU"), 39-45, 505-508 ·
`DECIZII`: 234, 324.
**Exemplul real (SPY 2005)** — `main`: 358-363 (intrare 117.43, TP1 +10 % =
129.17, atins „aproximativ un an mai târziu"; ziua exactă e neclară în
transcriere), 164-171, 465-468.
**Transfer pe prop** — `26_2025-06-11`: 214-222 (limita zilnică se calculează
și pe pozițiile deschise; cazul participantului căruia i s-au închis
tranzacții aflate în profit), 216-222, 225-227 (varianta „swing, 2 săptămâni",
pentru calificare — vezi contradicția 1) · `main`: 470-494.
**Transfer pe BVB** — `09_2025-12-09`: 1177-1180 (pivoții clasici, „1 la 1") ·
`28_2025-05-27`: 374-377 (pragurile US de lichiditate: volum > 500k, preț
> 30-40 $) · `main`: 39-45, 505-508 (premisa cade pe acțiuni individuale),
497-501 (fără BIM, trigger-ul devine cuțitul în cădere).
**Contradicții și puncte neclare** — (1) orizontul: `main`: 26-29, 358-363
vs. `26_2025-06-11`: 225-227; (2) aritmetica contribuției: `main`: 173-175 vs.
465-468; (3) formula PPQ/SQ, nedată cifric: `main`: 47-54, 143; (4) trailing /
tranșe / ieșire anticipată, neacoperite: `main`: 170-179; (5) data exactă a
atingerii TP1 (ASR): `main`: 358-363; (6) extinderea acronimului „ATMI" nu
apare nicăieri în material.
**Legături** — `26_2025-06-11`: 915-917 (autorul recomandă combinarea ATMI cu
MP² la suport/pivot important).