02_mp2: capitol reconstruit dupa sablon

Nivelurile 1-2-3, cei 6 pasi cu diagrama fiecare, mini-glosar de 34 de
termeni, oglinda pe short cu diagrama ei proprie, checklist. Sursele in
fise/02_mp2_surse.md.

Toate diagramele procedurii ies acum dintr-o singura serie
(mp2_serie.py), deci capitolul nu mai poate avea doua reguli numerice.
Ansamblul folosea NVDA cu stop la swing low absolut (-23 %), adica alta
regula decat procedura celor 4 bare; NVDA a devenit "bottom", la nivelul
3, marcat explicit ca exceptie.

perechi_tf e diagrama cu doua timeframe-uri: panoul mic e descompunerea
reala a ultimelor 2 candele daily (1 zi = 7 bare de 60 min), cu pivotul
weekly pe ambele panouri si conector. Pivotii se calculeaza din serie, nu
sunt scrisi de mana.

Reparate: trail-ul din proza era 600.05, calculul din serie da 600.75;
doua SVG-uri aveau trimiteri fisier:linie desenate pe ele.

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:51:58 +00:00
parent 9b047e10bb
commit 2ea599f265
25 changed files with 4449 additions and 1666 deletions

View File

@@ -1,139 +1,72 @@
"""Diagrama de ansamblu MP² — bottom major NVDA (strategii/02_mp2.md, Nivel 0).
"""MP² — tot trade-ul pe o singură diagramă (Nivelul 1 din `02_mp2.md`).
„NVDA — weekly (pre-split 1:10)": downtrend masiv → bază/bottom oct. 2022 →
crossing-ul pivotului weekly (mic) peste cel monthly (mare) → candela de
trigger care închide peste pivotul mic (M+A) → intrare 13.80 → SL la swing
low-ul absolut 10.63 (−23 %) → urcare spre TP 17.25 (+25 %, ~9 săptămâni).
Aceeași serie ca restul capitolului (`mp2_serie.py`): 5 ședințe de câte 7
bare de 60 de minute. Pe desen: pivotul weekly (mare) ca linie orizontală,
pivotul daily (mic) ca linie în trepte care se recalculează în fiecare zi,
crossing-ul, bara de trigger, stopul, TP1 și ieșirea pe trail.
Cifrele (13.80 / 10.63 / 17.25 / −23 % / +25 %) sunt din
`summaries/04_MODUL_3/04_strategia_2_mp_patrat.md:341-357,435`.
Traseul de preț și cele două linii de pivot sunt schematice: cursul nu dă
valorile pivoților, doar faptul că micul trece deasupra marelui la crossing
(`...:326-335`).
Rulează:
python3 gen/strategii/mp2_ansamblu.py
Scrie lângă el `mp2_ansamblu.svg`.
Rulare: python3 gen/strategii/mp2_ansamblu.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
sys.path.insert(0, str(Path(__file__).parent))
from svg_candles import Arrow, Chart, Level, Zone # noqa: E402
import mp2_serie as S # noqa: E402
OUT = Path(__file__).resolve().parent / "mp2_ansamblu.svg"
OUT = Path(__file__).with_suffix(".svg")
GREEN, RED, BLUE, GRAY, ORANGE = "#188a3e", "#c00", "#1a5fb4", "#777", "#b06000"
W = 720
GRAY, RED, GREEN, BLUE = "#777", "#c00", "#188a3e", "#1a5fb4"
zi4a, zi4b = S.ZI4 * S.BARE_ZI, (S.ZI4 + 1) * S.BARE_ZI - 1
# ------------------------------------------------------------------ seria (38 bare)
# 16 bare de downtrend 32.00 -> 11.40 (minimul absolut 10.63 e fitilul barei 15),
# 10 bare de bază/recuperare 11.80 -> 13.80 (bara 25 = intrarea, după M+A),
# 12 bare de urcare 14.10 -> 17.25 (ținta). open-ul = close-ul precedentului.
DOWN = [32.00, 30.80, 29.60, 28.70, 27.40, 26.50, 25.30, 24.20, 23.60,
22.30, 21.10, 19.90, 18.50, 16.90, 15.20, 11.40] # 0-15
BASE = [11.80, 12.10, 12.35, 12.20, 12.55, 12.85, 13.05, 13.35, 13.55,
13.80] # 16-25
UP = [14.10, 14.45, 14.80, 15.10, 15.45, 15.80, 16.10, 15.90, 16.30,
16.60, 16.95, 17.25] # 26-37
CLOSES = DOWN + BASE + UP
assert len(CLOSES) == 38, len(CLOSES)
CAPIT, ENTRY, LAST = 15, 25, 37
# fitile (sus, jos) per bară; bara 15 are fitilul de jos până la minimul absolut
WICKS = ([(0.35, 0.35)] * 14
+ [(0.30, 0.30)] # 14
+ [(0.20, 0.77)] # 15: low = 11.40 - 0.77 = 10.63
+ [(0.30, 0.30)] * 9 # 16-24
+ [(0.25, 0.20)] # 25: candela de intrare
+ [(0.30, 0.30)] * 12) # 26-37
assert len(WICKS) == len(CLOSES)
VOLS = ([52, 55, 50, 58, 54, 49, 56, 52, 60, 57, 63, 68, 72, 80, 90, 120] # 0-15
+ [100, 72, 60, 55, 58, 62, 66, 70, 78, 95] # 16-25
+ [88, 80, 74, 70, 68, 72, 76, 70, 74, 78, 84, 92]) # 26-37
assert len(VOLS) == len(CLOSES)
cds = from_closes(CLOSES, wicks=WICKS, vols=VOLS, start=32.60)
# ------------------------------------------------- liniile de pivot (trepte)
# Stepped, schematice (cursul nu dă valorile): monthly „mare" se recalculează
# rar, weekly „mic" mai des. Crossing: micul trece deasupra marelui exact pe
# candela de intrare.
PMARE = [31.00] * 10 + [21.00] * 10 + [13.55] * 8 + [13.20] * 10 # monthly
PMIC = ([30.50] * 5 + [29.00] * 5 + [20.00] * 4 + [17.00] * 4
+ [12.60] * 3 + [12.95] * 2 + [13.20] * 2 + [13.70] * 3
+ [14.20] * 4 + [14.60] * 6) # weekly
assert len(PMARE) == len(PMIC) == len(CLOSES)
# ---------------------------------------------------------- assert-urile din spec
entry = cds[ENTRY].c
sl, tp = 10.63, cds[LAST].c
assert abs(entry - 13.80) < 0.05 # close-ul intrării == 13.80
assert abs(sl - 10.63) < 0.05 and sl < entry # SL = swing low absolut, sub entry
assert abs(tp - 17.25) < 0.10 and tp > entry # TP = 17.25, peste entry
# spec: `abs((entry/sl - 1)*100 - 23)`; formula din spec e inversată (dă +29.8,
# nu −23). Pierderea corectă din entry până la SL e (sl/entry - 1), deci o scriu așa:
loss_pct = (sl / entry - 1) * 100
assert abs(loss_pct + 23) < 1.5, loss_pct # SL ≈ −23 %
assert abs((tp / entry - 1) * 100 - 25) < 1.5 # TP ≈ +25 %
assert abs(min(c.l for c in cds) - 10.63) < 0.01 # minimul absolut al seriei = SL
assert min(c.l for c in cds[-5:-1]) > 10.63 # stopul de 4 bare ar fi mult mai sus
# crossing-ul pivoților, înainte/după candela de intrare
assert all(PMIC[i] < PMARE[i] for i in range(ENTRY - 4, ENTRY)), "mic < mare înainte de intrare"
assert all(PMIC[i] > PMARE[i] for i in range(ENTRY, ENTRY + 4)), "mic > mare după intrare"
assert cds[ENTRY].c > PMIC[ENTRY], "candela de trigger nu închide peste pivotul mic"
assert abs(cds[CAPIT].l - sl) < 1e-9, "fitilul barei 15 nu atinge exact SL-ul"
levels = [
Level(13.80, "entry ~13.80 (după M+A)", GREEN, label_at="left"),
Level(sl, "SL swing low absolut 10.63, −23%", RED, label_at="left"),
Level(tp, "TP ~+25% (17.25), ~9 săpt.", BLUE, label_at="left"),
]
marks = [
Mark(CAPIT, f"minim absolut {sl:.2f}", RED, "below", dy=-6),
Mark(ENTRY, "M+A", BLUE, "above"),
]
ch = Chart(candles=cds, levels=levels, marks=marks,
scale=17.0, gap=15, body_w=9, left=44, width=720, top=64, vol_h=70,
vol_label="volum", title="NVDA — weekly (pre-split 1:10)",
caption="Bottom oct. 2022: entry ~13.80, −23%, ~+25% în ~9 săpt. "
"Traseu și pivoți construiți (cursul nu dă valorile lor).")
ch = Chart(
candles=S.CDS,
levels=[Level(S.TP1, f"TP1 {S.TP1:.2f} — poziția 1", GREEN, "2 3", "left"),
Level(S.ENTRY, f"intrarea {S.ENTRY:.2f}", "#333", "4 3", "left"),
Level(S.SL, f"stopul {S.SL:.2f}", RED, "6 3", "left"),
Level(S.PPW, f"pivot weekly (mare) {S.PPW:.2f}", GRAY, "8 4", "right")],
zones=[Zone(zi4a, zi4b, "ziua a 4-a: pivotul mic e deja peste cel mare", BLUE)],
arrows=[
Arrow(S.TRIGGER, f"aici intri: {S.ENTRY:.2f}\nprima bară care ÎNCHIDE\npeste pivotul mic",
where="above", color=GREEN, dx=-118, dy=-6),
Arrow(22, f"stopul: {S.SL:.2f}\nminimul ultimelor {S.BARE_STOP} bare —\n"
f"sub el, cumpărătorii nu mai au controlul",
where="below", price=S.SL, color=RED, dx=126, dy=4),
Arrow(S.I_TP1, f"poziția 1 iese la {S.TP1:.2f}:\nexact cât ai riscat (1:1)",
where="right", price=S.TP1, color=GREEN, dx=78, dy=-40),
Arrow(S.IESIRE, f"poziția 2 iese la {S.IES_PRET:.2f},\nprima închidere sub trail",
where="right", color=ORANGE, dy=44),
],
scale=17.0, gap=15, body_w=9, left=52, width=W, top=40, vol_h=64,
vol_label="volum", title="Exemplu construit — bare de 60 de minute, 5 ședințe",
caption=f"Crossing: pivotul mic urcă de la {S.PPD[S.ZI4 - 1]:.2f} la {S.PPD[S.ZI4]:.2f}, "
f"peste cel mare ({S.PPW:.2f}) — de-abia de acolo cauți trigger-ul.")
svg = ch.render()
def step_points(vals: list[float]) -> str:
"""Polilinie în trepte: orizontal pe fiecare palier, vertical la schimbare."""
pts: list[tuple[float, float]] = []
for i, v in enumerate(vals):
x, y = ch._cx(i), ch._y(v)
if i == 0:
pts.append((x, y))
elif v != vals[i - 1]:
pts.append((x, ch._y(vals[i - 1]))) # orizontal până la bara nouă
pts.append((x, y)) # salt vertical la nivelul nou
else:
pts.append((x, y))
return " ".join(f"{x:.1f},{y:.1f}" for x, y in pts)
# injectate imediat după tag-ul de deschidere => desenate în spatele candelelor
off = S.offset(svg, ch)
y_ppd = ch._y(S.PPD[-1]) + off
inject = [
f'<polyline points="{step_points(PMARE)}" fill="none" stroke="{GRAY}" stroke-width="1.6"/>',
f'<polyline points="{step_points(PMIC)}" fill="none" stroke="{BLUE}" stroke-width="1.6"/>',
f'<text x="712" y="{ch._y(PMIC[-1]) - 6:.1f}" fill="{BLUE}" text-anchor="end">'
f'pivot weekly (mic)</text>',
f'<text x="712" y="{ch._y(PMARE[-1]) + 14:.1f}" fill="{GRAY}" text-anchor="end">'
f'pivot monthly (mare)</text>',
f'<polyline points="{S.trepte(ch, S.PPD_BARA, off)}" fill="none" stroke="{BLUE}" '
f'stroke-width="1.8"/>',
f'<text x="{W - 16}" y="{y_ppd - 7:.1f}" fill="{BLUE}" text-anchor="end">'
f'pivot daily (mic)</text>',
]
i = svg.index(">") + 1
svg = svg[:i] + "\n " + "\n ".join(inject) + svg[i:]
# marcajul crossing-ului: treapta verticală a pivotului mic, între ziua 3 și 4
xc = ch._cx(zi4a) - 7.5
y_de, y_la = ch._y(S.PPD[S.ZI4 - 1]) + off, ch._y(S.PPD[S.ZI4]) + off
inject += [
f'<circle cx="{xc:.1f}" cy="{(y_de + y_la) / 2:.1f}" r="{(y_de - y_la) / 2 + 4:.1f}" '
f'fill="none" stroke="{BLUE}" stroke-width="1.4" stroke-dasharray="3 2"/>',
f'<text x="{xc:.1f}" y="{y_de + 20:.1f}" fill="{BLUE}" text-anchor="middle" '
f'style="font-weight:bold">crossing</text>',
]
svg = S.injecteaza(svg, inject)
assert svg.count("\n\n") == 0, "linie goală în SVG rupe blocul din markdown"
OUT.write_text(svg)
print(f"scris {OUT.name}: {len(cds)} candele, entry {entry:.2f}, "
f"SL {sl:.2f} ({loss_pct:+.1f}%), TP {tp:.2f} "
f"({(tp/entry - 1) * 100:+.1f}%), crossing la bara {ENTRY}")
assert y_de > y_la, "crossing-ul nu urcă pe desen"
assert abs((ch._y(S.SL) - ch._y(S.ENTRY)) - (ch._y(S.ENTRY) - ch._y(S.TP1))) < 0.01, \
"1R în sus nu e desenat cât 1R în jos"
h = float(svg.split('viewBox="0 0 ')[1].split('"')[0].split()[1])
w = float(svg.split('viewBox="0 0 ')[1].split()[0])
S.scrie(OUT, svg, w, h)

View File

@@ -1,132 +1,143 @@
<svg viewBox="0 0 720 603" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif">
<polyline points="44.0,119.2 59.0,119.2 74.0,119.2 89.0,119.2 104.0,119.2 119.0,119.2 134.0,119.2 149.0,119.2 164.0,119.2 179.0,119.2 194.0,119.2 194.0,289.2 209.0,289.2 224.0,289.2 239.0,289.2 254.0,289.2 269.0,289.2 284.0,289.2 299.0,289.2 314.0,289.2 329.0,289.2 344.0,289.2 344.0,415.8 359.0,415.8 374.0,415.8 389.0,415.8 404.0,415.8 419.0,415.8 434.0,415.8 449.0,415.8 464.0,415.8 464.0,421.8 479.0,421.8 494.0,421.8 509.0,421.8 524.0,421.8 539.0,421.8 554.0,421.8 569.0,421.8 584.0,421.8 599.0,421.8" fill="none" stroke="#777" stroke-width="1.6"/>
<polyline points="44.0,127.7 59.0,127.7 74.0,127.7 89.0,127.7 104.0,127.7 119.0,127.7 119.0,153.2 134.0,153.2 149.0,153.2 164.0,153.2 179.0,153.2 194.0,153.2 194.0,306.2 209.0,306.2 224.0,306.2 239.0,306.2 254.0,306.2 254.0,357.2 269.0,357.2 284.0,357.2 299.0,357.2 314.0,357.2 314.0,432.0 329.0,432.0 344.0,432.0 359.0,432.0 359.0,426.0 374.0,426.0 389.0,426.0 389.0,421.8 404.0,421.8 419.0,421.8 419.0,413.3 434.0,413.3 449.0,413.3 464.0,413.3 464.0,404.8 479.0,404.8 494.0,404.8 509.0,404.8 524.0,404.8 524.0,398.0 539.0,398.0 554.0,398.0 569.0,398.0 584.0,398.0 599.0,398.0" fill="none" stroke="#1a5fb4" stroke-width="1.6"/>
<text x="712" y="392.0" fill="#1a5fb4" text-anchor="end">pivot weekly (mic)</text>
<text x="712" y="435.8" fill="#777" text-anchor="end">pivot monthly (mare)</text>
<text x="24" y="78" fill="#333" style="font-weight:bold">NVDA — weekly (pre-split 1:10)</text>
<line x1="24" y1="411.6" x2="706" y2="411.6" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30" y="405.6" fill="#188a3e">entry ~13.80 (după M+A)</text>
<line x1="24" y1="465.4" x2="706" y2="465.4" stroke="#c00" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30" y="459.4" fill="#c00">SL swing low absolut 10.63, −23%</text>
<line x1="24" y1="352.9" x2="706" y2="352.9" stroke="#1a5fb4" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30" y="346.9" fill="#1a5fb4">TP ~+25% (17.25), ~9 săpt.</text>
<line x1="44.0" y1="86.0" x2="44.0" y2="108.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="39.5" y="92.0" width="9" height="10.2" fill="#c00"/>
<line x1="59.0" y1="96.2" x2="59.0" y2="128.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="54.5" y="102.2" width="9" height="20.4" fill="#c00"/>
<line x1="74.0" y1="116.6" x2="74.0" y2="148.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="69.5" y="122.6" width="9" height="20.4" fill="#c00"/>
<line x1="89.0" y1="137.0" x2="89.0" y2="164.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="84.5" y="143.0" width="9" height="15.3" fill="#c00"/>
<line x1="104.0" y1="152.3" x2="104.0" y2="186.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="99.5" y="158.3" width="9" height="22.1" fill="#c00"/>
<line x1="119.0" y1="174.4" x2="119.0" y2="201.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="114.5" y="180.4" width="9" height="15.3" fill="#c00"/>
<line x1="134.0" y1="189.7" x2="134.0" y2="222.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="129.5" y="195.7" width="9" height="20.4" fill="#c00"/>
<line x1="149.0" y1="210.1" x2="149.0" y2="240.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="144.5" y="216.1" width="9" height="18.7" fill="#c00"/>
<line x1="164.0" y1="228.8" x2="164.0" y2="250.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="159.5" y="234.8" width="9" height="10.2" fill="#c00"/>
<line x1="179.0" y1="239.0" x2="179.0" y2="273.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="174.5" y="245.0" width="9" height="22.1" fill="#c00"/>
<line x1="194.0" y1="261.1" x2="194.0" y2="293.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="189.5" y="267.1" width="9" height="20.4" fill="#c00"/>
<line x1="209.0" y1="281.5" x2="209.0" y2="313.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="204.5" y="287.5" width="9" height="20.4" fill="#c00"/>
<line x1="224.0" y1="301.9" x2="224.0" y2="337.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="219.5" y="307.9" width="9" height="23.8" fill="#c00"/>
<line x1="239.0" y1="325.7" x2="239.0" y2="364.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="234.5" y="331.7" width="9" height="27.2" fill="#c00"/>
<line x1="254.0" y1="353.8" x2="254.0" y2="392.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="249.5" y="358.9" width="9" height="28.9" fill="#c00"/>
<line x1="269.0" y1="384.4" x2="269.0" y2="465.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="264.5" y="387.8" width="9" height="64.6" fill="#c00"/>
<line x1="284.0" y1="440.5" x2="284.0" y2="457.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="279.5" y="445.6" width="9" height="6.8" fill="#188a3e"/>
<line x1="299.0" y1="435.4" x2="299.0" y2="450.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="294.5" y="440.5" width="9" height="5.1" fill="#188a3e"/>
<line x1="314.0" y1="431.1" x2="314.0" y2="445.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="309.5" y="436.2" width="9" height="4.2" fill="#188a3e"/>
<line x1="329.0" y1="431.1" x2="329.0" y2="443.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="324.5" y="436.2" width="9" height="2.6" fill="#c00"/>
<line x1="344.0" y1="427.7" x2="344.0" y2="443.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="339.5" y="432.8" width="9" height="6.0" fill="#188a3e"/>
<line x1="359.0" y1="422.6" x2="359.0" y2="437.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="354.5" y="427.7" width="9" height="5.1" fill="#188a3e"/>
<line x1="374.0" y1="419.2" x2="374.0" y2="432.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="369.5" y="424.3" width="9" height="3.4" fill="#188a3e"/>
<line x1="389.0" y1="414.1" x2="389.0" y2="429.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="384.5" y="419.2" width="9" height="5.1" fill="#188a3e"/>
<line x1="404.0" y1="410.7" x2="404.0" y2="424.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="399.5" y="415.8" width="9" height="3.4" fill="#188a3e"/>
<line x1="419.0" y1="407.3" x2="419.0" y2="419.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="414.5" y="411.6" width="9" height="4.2" fill="#188a3e"/>
<line x1="434.0" y1="401.4" x2="434.0" y2="416.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="429.5" y="406.5" width="9" height="5.1" fill="#188a3e"/>
<line x1="449.0" y1="395.4" x2="449.0" y2="411.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="444.5" y="400.5" width="9" height="5.9" fill="#188a3e"/>
<line x1="464.0" y1="389.5" x2="464.0" y2="405.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="459.5" y="394.6" width="9" height="6.0" fill="#188a3e"/>
<line x1="479.0" y1="384.4" x2="479.0" y2="399.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="474.5" y="389.5" width="9" height="5.1" fill="#188a3e"/>
<line x1="494.0" y1="378.4" x2="494.0" y2="394.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="489.5" y="383.5" width="9" height="5.9" fill="#188a3e"/>
<line x1="509.0" y1="372.5" x2="509.0" y2="388.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="504.5" y="377.6" width="9" height="6.0" fill="#188a3e"/>
<line x1="524.0" y1="367.4" x2="524.0" y2="382.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="519.5" y="372.5" width="9" height="5.1" fill="#188a3e"/>
<line x1="539.0" y1="367.4" x2="539.0" y2="381.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="534.5" y="372.5" width="9" height="3.4" fill="#c00"/>
<line x1="554.0" y1="364.0" x2="554.0" y2="381.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="549.5" y="369.1" width="9" height="6.8" fill="#188a3e"/>
<line x1="569.0" y1="358.9" x2="569.0" y2="374.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="564.5" y="364.0" width="9" height="5.1" fill="#188a3e"/>
<line x1="584.0" y1="352.9" x2="584.0" y2="369.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="579.5" y="358.0" width="9" height="5.9" fill="#188a3e"/>
<line x1="599.0" y1="347.8" x2="599.0" y2="363.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="594.5" y="352.9" width="9" height="5.1" fill="#188a3e"/>
<line x1="24" y1="561.4" x2="706" y2="561.4" stroke="#888"/>
<rect x="39.5" y="531.1" width="9" height="30.3" fill="#c00" opacity="0.55"/>
<rect x="54.5" y="529.4" width="9" height="32.1" fill="#c00" opacity="0.55"/>
<rect x="69.5" y="532.3" width="9" height="29.2" fill="#c00" opacity="0.55"/>
<rect x="84.5" y="527.6" width="9" height="33.8" fill="#c00" opacity="0.55"/>
<rect x="99.5" y="529.9" width="9" height="31.5" fill="#c00" opacity="0.55"/>
<rect x="114.5" y="532.9" width="9" height="28.6" fill="#c00" opacity="0.55"/>
<rect x="129.5" y="528.8" width="9" height="32.7" fill="#c00" opacity="0.55"/>
<rect x="144.5" y="531.1" width="9" height="30.3" fill="#c00" opacity="0.55"/>
<rect x="159.5" y="526.4" width="9" height="35.0" fill="#c00" opacity="0.55"/>
<rect x="174.5" y="528.2" width="9" height="33.2" fill="#c00" opacity="0.55"/>
<rect x="189.5" y="524.7" width="9" height="36.8" fill="#c00" opacity="0.55"/>
<rect x="204.5" y="521.8" width="9" height="39.7" fill="#c00" opacity="0.55"/>
<rect x="219.5" y="519.4" width="9" height="42.0" fill="#c00" opacity="0.55"/>
<rect x="234.5" y="514.8" width="9" height="46.7" fill="#c00" opacity="0.55"/>
<rect x="249.5" y="508.9" width="9" height="52.5" fill="#c00" opacity="0.55"/>
<rect x="264.5" y="491.4" width="9" height="70.0" fill="#c00" opacity="0.55"/>
<rect x="279.5" y="503.1" width="9" height="58.3" fill="#188a3e" opacity="0.55"/>
<rect x="294.5" y="519.4" width="9" height="42.0" fill="#188a3e" opacity="0.55"/>
<rect x="309.5" y="526.4" width="9" height="35.0" fill="#188a3e" opacity="0.55"/>
<rect x="324.5" y="529.4" width="9" height="32.1" fill="#c00" opacity="0.55"/>
<rect x="339.5" y="527.6" width="9" height="33.8" fill="#188a3e" opacity="0.55"/>
<rect x="354.5" y="525.3" width="9" height="36.2" fill="#188a3e" opacity="0.55"/>
<rect x="369.5" y="522.9" width="9" height="38.5" fill="#188a3e" opacity="0.55"/>
<rect x="384.5" y="520.6" width="9" height="40.8" fill="#188a3e" opacity="0.55"/>
<rect x="399.5" y="515.9" width="9" height="45.5" fill="#188a3e" opacity="0.55"/>
<rect x="414.5" y="506.0" width="9" height="55.4" fill="#188a3e" opacity="0.55"/>
<rect x="429.5" y="510.1" width="9" height="51.3" fill="#188a3e" opacity="0.55"/>
<rect x="444.5" y="514.8" width="9" height="46.7" fill="#188a3e" opacity="0.55"/>
<rect x="459.5" y="518.3" width="9" height="43.2" fill="#188a3e" opacity="0.55"/>
<rect x="474.5" y="520.6" width="9" height="40.8" fill="#188a3e" opacity="0.55"/>
<rect x="489.5" y="521.8" width="9" height="39.7" fill="#188a3e" opacity="0.55"/>
<rect x="504.5" y="519.4" width="9" height="42.0" fill="#188a3e" opacity="0.55"/>
<rect x="519.5" y="517.1" width="9" height="44.3" fill="#188a3e" opacity="0.55"/>
<rect x="534.5" y="520.6" width="9" height="40.8" fill="#c00" opacity="0.55"/>
<rect x="549.5" y="518.3" width="9" height="43.2" fill="#188a3e" opacity="0.55"/>
<rect x="564.5" y="515.9" width="9" height="45.5" fill="#188a3e" opacity="0.55"/>
<rect x="579.5" y="512.4" width="9" height="49.0" fill="#188a3e" opacity="0.55"/>
<rect x="594.5" y="507.8" width="9" height="53.7" fill="#188a3e" opacity="0.55"/>
<text x="24" y="485.4" fill="#555">volum</text>
<text x="269.0" y="479.4" fill="#c00" text-anchor="middle" style="font-weight:bold">minim absolut 10.63</text>
<text x="419.0" y="397.3" fill="#1a5fb4" text-anchor="middle" style="font-weight:bold">M+A</text>
<text x="24" y="591" fill="#555">Bottom oct. 2022: entry ~13.80, −23%, ~+25% în ~9 săpt. Traseu și pivoți construiți (cursul nu dă valorile lor).</text>
<svg viewBox="0 0 752 579" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif">
<polyline points="52.0,392.6 67.0,392.6 82.0,392.6 97.0,392.6 112.0,392.6 127.0,392.6 142.0,392.6 157.0,392.6 157.0,406.2 172.0,406.2 187.0,406.2 202.0,406.2 217.0,406.2 232.0,406.2 247.0,406.2 262.0,406.2 262.0,392.6 277.0,392.6 292.0,392.6 307.0,392.6 322.0,392.6 337.0,392.6 352.0,392.6 367.0,392.6 367.0,325.8 382.0,325.8 397.0,325.8 412.0,325.8 427.0,325.8 442.0,325.8 457.0,325.8 472.0,325.8 472.0,204.8 487.0,204.8 502.0,204.8 517.0,204.8 532.0,204.8 547.0,204.8 562.0,204.8" fill="none" stroke="#1a5fb4" stroke-width="1.8"/>
<text x="704" y="197.8" fill="#1a5fb4" text-anchor="end">pivot daily (mic)</text>
<circle cx="359.5" cy="359.2" r="37.4" fill="none" stroke="#1a5fb4" stroke-width="1.4" stroke-dasharray="3 2"/>
<text x="359.5" y="412.6" fill="#1a5fb4" text-anchor="middle" style="font-weight:bold">crossing</text>
<text x="24" y="54" fill="#333" style="font-weight:bold">Exemplu construit — bare de 60 de minute, 5 ședințe</text>
<rect x="357.5" y="123.7" width="109.0" height="229.4" fill="#1a5fb4" fill-opacity="0.08" stroke="#1a5fb4" stroke-width="1"/>
<text x="357.5" y="53.0" fill="#1a5fb4" style="font-weight:bold">ziua a 4-a: pivotul mic e deja peste cel mare</text>
<line x1="24" y1="141.0" x2="738" y2="141.0" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="2 3"/>
<text x="30" y="135.0" fill="#188a3e">TP1 598.00 — poziția 1</text>
<line x1="24" y1="243.0" x2="738" y2="243.0" stroke="#333" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30" y="237.0" fill="#333">intrarea 592.00</text>
<line x1="24" y1="345.0" x2="738" y2="345.0" stroke="#c00" stroke-width="1.5" stroke-dasharray="6 3"/>
<text x="30" y="339.0" fill="#c00">stopul 586.00</text>
<line x1="24" y1="379.0" x2="738" y2="379.0" stroke="#777" stroke-width="1.5" stroke-dasharray="8 4"/>
<text x="724" y="373.0" fill="#777" text-anchor="end">pivot weekly (mare) 584.00</text>
<line x1="52.0" y1="355.2" x2="52.0" y2="379.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="47.5" y="362.0" width="9" height="13.6" fill="#c00"/>
<line x1="67.0" y1="371.4" x2="67.0" y2="393.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="62.5" y="375.6" width="9" height="13.6" fill="#c00"/>
<line x1="82.0" y1="376.5" x2="82.0" y2="393.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="77.5" y="380.8" width="9" height="8.5" fill="#188a3e"/>
<line x1="97.0" y1="376.5" x2="97.0" y2="407.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="92.5" y="380.8" width="9" height="22.1" fill="#c00"/>
<line x1="112.0" y1="398.6" x2="112.0" y2="420.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="107.5" y="402.8" width="9" height="13.6" fill="#c00"/>
<line x1="127.0" y1="405.4" x2="127.0" y2="420.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="122.5" y="409.6" width="9" height="6.8" fill="#188a3e"/>
<line x1="142.0" y1="405.4" x2="142.0" y2="436.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="137.5" y="409.6" width="9" height="17.0" fill="#c00"/>
<line x1="157.0" y1="422.4" x2="157.0" y2="447.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="152.5" y="426.6" width="9" height="10.2" fill="#c00"/>
<line x1="172.0" y1="419.0" x2="172.0" y2="441.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="167.5" y="423.2" width="9" height="13.6" fill="#188a3e"/>
<line x1="187.0" y1="419.0" x2="187.0" y2="436.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="182.5" y="423.2" width="9" height="8.5" fill="#c00"/>
<line x1="202.0" y1="403.7" x2="202.0" y2="436.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="197.5" y="408.0" width="9" height="23.8" fill="#188a3e"/>
<line x1="217.0" y1="390.1" x2="217.0" y2="412.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="212.5" y="394.3" width="9" height="13.6" fill="#188a3e"/>
<line x1="232.0" y1="378.2" x2="232.0" y2="398.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="227.5" y="382.5" width="9" height="11.9" fill="#188a3e"/>
<line x1="247.0" y1="362.0" x2="247.0" y2="386.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="242.5" y="368.8" width="9" height="13.6" fill="#188a3e"/>
<line x1="262.0" y1="356.1" x2="262.0" y2="375.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="257.5" y="360.3" width="9" height="8.5" fill="#188a3e"/>
<line x1="277.0" y1="356.1" x2="277.0" y2="371.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="272.5" y="360.3" width="9" height="6.8" fill="#c00"/>
<line x1="292.0" y1="347.6" x2="292.0" y2="371.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="287.5" y="351.8" width="9" height="15.3" fill="#188a3e"/>
<line x1="307.0" y1="334.0" x2="307.0" y2="356.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="302.5" y="338.2" width="9" height="13.6" fill="#188a3e"/>
<line x1="322.0" y1="320.4" x2="322.0" y2="342.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="317.5" y="324.6" width="9" height="13.6" fill="#188a3e"/>
<line x1="337.0" y1="310.2" x2="337.0" y2="328.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="332.5" y="314.5" width="9" height="10.2" fill="#188a3e"/>
<line x1="352.0" y1="297.5" x2="352.0" y2="318.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="347.5" y="304.2" width="9" height="10.2" fill="#188a3e"/>
<line x1="367.0" y1="299.2" x2="367.0" y2="334.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="362.5" y="304.2" width="9" height="25.5" fill="#c00"/>
<line x1="382.0" y1="324.7" x2="382.0" y2="345.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="377.5" y="329.8" width="9" height="10.2" fill="#c00"/>
<line x1="397.0" y1="326.4" x2="397.0" y2="343.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="392.5" y="331.5" width="9" height="8.5" fill="#188a3e"/>
<line x1="412.0" y1="236.2" x2="412.0" y2="336.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="407.5" y="243.0" width="9" height="88.4" fill="#188a3e"/>
<line x1="427.0" y1="213.3" x2="427.0" y2="249.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="422.5" y="219.2" width="9" height="23.8" fill="#188a3e"/>
<line x1="442.0" y1="170.8" x2="442.0" y2="226.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="437.5" y="176.8" width="9" height="42.5" fill="#188a3e"/>
<line x1="457.0" y1="131.7" x2="457.0" y2="183.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="452.5" y="137.6" width="9" height="39.1" fill="#188a3e"/>
<line x1="472.0" y1="107.9" x2="472.0" y2="143.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="467.5" y="113.8" width="9" height="23.8" fill="#188a3e"/>
<line x1="487.0" y1="80.7" x2="487.0" y2="119.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="482.5" y="86.6" width="9" height="27.2" fill="#188a3e"/>
<line x1="502.0" y1="80.7" x2="502.0" y2="106.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="497.5" y="86.6" width="9" height="13.6" fill="#c00"/>
<line x1="517.0" y1="62.0" x2="517.0" y2="106.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="512.5" y="68.0" width="9" height="32.3" fill="#188a3e"/>
<line x1="532.0" y1="62.0" x2="532.0" y2="94.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="527.5" y="68.0" width="9" height="20.4" fill="#c00"/>
<line x1="547.0" y1="82.4" x2="547.0" y2="116.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="542.5" y="88.3" width="9" height="22.1" fill="#c00"/>
<line x1="562.0" y1="104.5" x2="562.0" y2="131.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="557.5" y="110.5" width="9" height="15.3" fill="#c00"/>
<line x1="24" y1="537.0" x2="738" y2="537.0" stroke="#888"/>
<rect x="47.5" y="512.1" width="9" height="24.9" fill="#c00" opacity="0.55"/>
<rect x="62.5" y="515.4" width="9" height="21.7" fill="#c00" opacity="0.55"/>
<rect x="77.5" y="516.4" width="9" height="20.6" fill="#188a3e" opacity="0.55"/>
<rect x="92.5" y="514.3" width="9" height="22.8" fill="#c00" opacity="0.55"/>
<rect x="107.5" y="515.9" width="9" height="21.2" fill="#c00" opacity="0.55"/>
<rect x="122.5" y="517.5" width="9" height="19.5" fill="#188a3e" opacity="0.55"/>
<rect x="137.5" y="513.2" width="9" height="23.9" fill="#c00" opacity="0.55"/>
<rect x="152.5" y="505.6" width="9" height="31.5" fill="#c00" opacity="0.55"/>
<rect x="167.5" y="508.8" width="9" height="28.2" fill="#188a3e" opacity="0.55"/>
<rect x="182.5" y="513.2" width="9" height="23.9" fill="#c00" opacity="0.55"/>
<rect x="197.5" y="514.8" width="9" height="22.2" fill="#188a3e" opacity="0.55"/>
<rect x="212.5" y="516.4" width="9" height="20.6" fill="#188a3e" opacity="0.55"/>
<rect x="227.5" y="517.5" width="9" height="19.5" fill="#188a3e" opacity="0.55"/>
<rect x="242.5" y="515.4" width="9" height="21.7" fill="#188a3e" opacity="0.55"/>
<rect x="257.5" y="513.2" width="9" height="23.9" fill="#188a3e" opacity="0.55"/>
<rect x="272.5" y="516.4" width="9" height="20.6" fill="#c00" opacity="0.55"/>
<rect x="287.5" y="514.8" width="9" height="22.2" fill="#188a3e" opacity="0.55"/>
<rect x="302.5" y="512.6" width="9" height="24.4" fill="#188a3e" opacity="0.55"/>
<rect x="317.5" y="511.0" width="9" height="26.0" fill="#188a3e" opacity="0.55"/>
<rect x="332.5" y="513.2" width="9" height="23.9" fill="#188a3e" opacity="0.55"/>
<rect x="347.5" y="508.8" width="9" height="28.2" fill="#188a3e" opacity="0.55"/>
<rect x="362.5" y="509.9" width="9" height="27.1" fill="#c00" opacity="0.55"/>
<rect x="377.5" y="512.1" width="9" height="24.9" fill="#c00" opacity="0.55"/>
<rect x="392.5" y="514.3" width="9" height="22.8" fill="#188a3e" opacity="0.55"/>
<rect x="407.5" y="473.0" width="9" height="64.0" fill="#188a3e" opacity="0.55"/>
<rect x="422.5" y="490.4" width="9" height="46.6" fill="#188a3e" opacity="0.55"/>
<rect x="437.5" y="494.7" width="9" height="42.3" fill="#188a3e" opacity="0.55"/>
<rect x="452.5" y="492.6" width="9" height="44.5" fill="#188a3e" opacity="0.55"/>
<rect x="467.5" y="502.3" width="9" height="34.7" fill="#188a3e" opacity="0.55"/>
<rect x="482.5" y="505.6" width="9" height="31.5" fill="#188a3e" opacity="0.55"/>
<rect x="497.5" y="512.1" width="9" height="24.9" fill="#c00" opacity="0.55"/>
<rect x="512.5" y="503.4" width="9" height="33.6" fill="#188a3e" opacity="0.55"/>
<rect x="527.5" y="513.2" width="9" height="23.9" fill="#c00" opacity="0.55"/>
<rect x="542.5" y="506.7" width="9" height="30.4" fill="#c00" opacity="0.55"/>
<rect x="557.5" y="511.0" width="9" height="26.0" fill="#c00" opacity="0.55"/>
<text x="24" y="467.0" fill="#555">volum</text>
<line x1="294.0" y1="200.2" x2="404.3" y2="230.2" stroke="#188a3e" stroke-width="1.8"/>
<polygon points="412.0,232.2 403.2,234.0 405.3,226.3" fill="#188a3e"/>
<text x="294.0" y="167.2" fill="#188a3e" text-anchor="middle" style="font-weight:bold">aici intri: 592.00</text>
<text x="294.0" y="181.2" fill="#188a3e" text-anchor="middle" style="font-weight:bold">prima bară care ÎNCHIDE</text>
<text x="294.0" y="195.2" fill="#188a3e" text-anchor="middle" style="font-weight:bold">peste pivotul mic</text>
<line x1="508.0" y1="379.0" x2="389.8" y2="350.9" stroke="#c00" stroke-width="1.8"/>
<polygon points="382.0,349.0 390.7,347.0 388.9,354.8" fill="#c00"/>
<text x="508.0" y="393.0" fill="#c00" text-anchor="middle" style="font-weight:bold">stopul: 586.00</text>
<text x="508.0" y="407.0" fill="#c00" text-anchor="middle" style="font-weight:bold">minimul ultimelor 4 bare —</text>
<text x="508.0" y="421.0" fill="#c00" text-anchor="middle" style="font-weight:bold">sub el, cumpărătorii nu mai au controlul</text>
<line x1="573.5" y1="101.0" x2="473.0" y2="138.3" stroke="#188a3e" stroke-width="1.8"/>
<polygon points="465.5,141.0 471.6,134.5 474.4,142.0" fill="#188a3e"/>
<text x="577.5" y="98.0" fill="#188a3e" text-anchor="start" style="font-weight:bold">poziția 1 iese la 598.00:</text>
<text x="577.5" y="112.0" fill="#188a3e" text-anchor="start" style="font-weight:bold">exact cât ai riscat (1:1)</text>
<line x1="585.5" y1="154.5" x2="560.0" y2="117.1" stroke="#b06000" stroke-width="1.8"/>
<polygon points="555.5,110.5 563.3,114.8 556.7,119.3" fill="#b06000"/>
<text x="589.5" y="151.5" fill="#b06000" text-anchor="start" style="font-weight:bold">poziția 2 iese la 599.80,</text>
<text x="589.5" y="165.5" fill="#b06000" text-anchor="start" style="font-weight:bold">prima închidere sub trail</text>
<text x="24" y="567" fill="#555">Crossing: pivotul mic urcă de la 583.20 la 587.13, peste cel mare (584.00) — de-abia de acolo cauți trigger-ul.</text>
</svg>

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -186,7 +186,7 @@ LEGENDA = [
"Legendă: ce separă cele două sunt nivelurile independente dedesubte "
"(suport quarterly + double bottom + neckline),",
"nu un filtru pus în scaner. Panoul din dreapta e exemplu construit, nu date reale.",
"Surse A+: 09_QA/01_2026-08-25.md:389-394, 485-490, 501-507.",
"Cifrele A+ sunt din material; trimiterile stau în fișa de surse a capitolului.",
]
wrapper = (

View File

@@ -218,4 +218,4 @@
<text x="24" y="416.0" fill="#555">volum</text>
<text x="149.0" y="201.8" fill="#188a3e" text-anchor="middle" style="font-weight:bold">crossing (mijloc)</text>
<text x="24" y="516" fill="#555">exemplu construit, nu date reale — SL nu stă pe niciun pivot</text>
</g><text x="580" y="650" fill="#555" text-anchor="middle">Legendă: ce separă cele două sunt nivelurile independente dedesubte (suport quarterly + double bottom + neckline),</text><text x="580" y="668" fill="#555" text-anchor="middle">nu un filtru pus în scaner. Panoul din dreapta e exemplu construit, nu date reale.</text><text x="580" y="686" fill="#555" text-anchor="middle">Surse A+: 09_QA/01_2026-08-25.md:389-394, 485-490, 501-507.</text></svg>
</g><text x="580" y="650" fill="#555" text-anchor="middle">Legendă: ce separă cele două sunt nivelurile independente dedesubte (suport quarterly + double bottom + neckline),</text><text x="580" y="668" fill="#555" text-anchor="middle">nu un filtru pus în scaner. Panoul din dreapta e exemplu construit, nu date reale.</text><text x="580" y="686" fill="#555" text-anchor="middle">Cifrele A+ sunt din material; trimiterile stau în fișa de surse a capitolului.</text></svg>

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

142
gen/strategii/mp2_bottom.py Normal file
View File

@@ -0,0 +1,142 @@
"""MP² la un bottom major — NVDA (strategii/02_mp2.md, Nivelul 3).
Excepția de la regula stopului: la un bottom/top major stopul nu se
măsoară pe 4 candele, ci la swing low-ul absolut al mișcării.
„NVDA — weekly (pre-split 1:10)": downtrend masiv → bază/bottom oct. 2022 →
crossing-ul pivotului weekly (mic) peste cel monthly (mare) → candela de
trigger care închide peste pivotul mic (M+A) → intrare 13.80 → SL la swing
low-ul absolut 10.63 (−23 %) → urcare spre TP 17.25 (+25 %, ~9 săptămâni).
Cifrele (13.80 / 10.63 / 17.25 / −23 % / +25 %) sunt din
`summaries/04_MODUL_3/04_strategia_2_mp_patrat.md:341-357,435`.
Traseul de preț și cele două linii de pivot sunt schematice: cursul nu dă
valorile pivoților, doar faptul că micul trece deasupra marelui la crossing
(`...:326-335`).
Rulează:
python3 gen/strategii/mp2_bottom.py
Scrie lângă el `mp2_bottom.svg`.
"""
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 / "mp2_bottom.svg"
GRAY, RED, GREEN, BLUE = "#777", "#c00", "#188a3e", "#1a5fb4"
# ------------------------------------------------------------------ seria (38 bare)
# 16 bare de downtrend 32.00 -> 11.40 (minimul absolut 10.63 e fitilul barei 15),
# 10 bare de bază/recuperare 11.80 -> 13.80 (bara 25 = intrarea, după M+A),
# 12 bare de urcare 14.10 -> 17.25 (ținta). open-ul = close-ul precedentului.
DOWN = [32.00, 30.80, 29.60, 28.70, 27.40, 26.50, 25.30, 24.20, 23.60,
22.30, 21.10, 19.90, 18.50, 16.90, 15.20, 11.40] # 0-15
BASE = [11.80, 12.10, 12.35, 12.20, 12.55, 12.85, 13.05, 13.35, 13.55,
13.80] # 16-25
UP = [14.10, 14.45, 14.80, 15.10, 15.45, 15.80, 16.10, 15.90, 16.30,
16.60, 16.95, 17.25] # 26-37
CLOSES = DOWN + BASE + UP
assert len(CLOSES) == 38, len(CLOSES)
CAPIT, ENTRY, LAST = 15, 25, 37
# fitile (sus, jos) per bară; bara 15 are fitilul de jos până la minimul absolut
WICKS = ([(0.35, 0.35)] * 14
+ [(0.30, 0.30)] # 14
+ [(0.20, 0.77)] # 15: low = 11.40 - 0.77 = 10.63
+ [(0.30, 0.30)] * 9 # 16-24
+ [(0.25, 0.20)] # 25: candela de intrare
+ [(0.30, 0.30)] * 12) # 26-37
assert len(WICKS) == len(CLOSES)
VOLS = ([52, 55, 50, 58, 54, 49, 56, 52, 60, 57, 63, 68, 72, 80, 90, 120] # 0-15
+ [100, 72, 60, 55, 58, 62, 66, 70, 78, 95] # 16-25
+ [88, 80, 74, 70, 68, 72, 76, 70, 74, 78, 84, 92]) # 26-37
assert len(VOLS) == len(CLOSES)
cds = from_closes(CLOSES, wicks=WICKS, vols=VOLS, start=32.60)
# ------------------------------------------------- liniile de pivot (trepte)
# Stepped, schematice (cursul nu dă valorile): monthly „mare" se recalculează
# rar, weekly „mic" mai des. Crossing: micul trece deasupra marelui exact pe
# candela de intrare.
PMARE = [31.00] * 10 + [21.00] * 10 + [13.55] * 8 + [13.20] * 10 # monthly
PMIC = ([30.50] * 5 + [29.00] * 5 + [20.00] * 4 + [17.00] * 4
+ [12.60] * 3 + [12.95] * 2 + [13.20] * 2 + [13.70] * 3
+ [14.20] * 4 + [14.60] * 6) # weekly
assert len(PMARE) == len(PMIC) == len(CLOSES)
# ---------------------------------------------------------- assert-urile din spec
entry = cds[ENTRY].c
sl, tp = 10.63, cds[LAST].c
assert abs(entry - 13.80) < 0.05 # close-ul intrării == 13.80
assert abs(sl - 10.63) < 0.05 and sl < entry # SL = swing low absolut, sub entry
assert abs(tp - 17.25) < 0.10 and tp > entry # TP = 17.25, peste entry
# spec: `abs((entry/sl - 1)*100 - 23)`; formula din spec e inversată (dă +29.8,
# nu −23). Pierderea corectă din entry până la SL e (sl/entry - 1), deci o scriu așa:
loss_pct = (sl / entry - 1) * 100
assert abs(loss_pct + 23) < 1.5, loss_pct # SL ≈ −23 %
assert abs((tp / entry - 1) * 100 - 25) < 1.5 # TP ≈ +25 %
assert abs(min(c.l for c in cds) - 10.63) < 0.01 # minimul absolut al seriei = SL
assert min(c.l for c in cds[-5:-1]) > 10.63 # stopul de 4 bare ar fi mult mai sus
# crossing-ul pivoților, înainte/după candela de intrare
assert all(PMIC[i] < PMARE[i] for i in range(ENTRY - 4, ENTRY)), "mic < mare înainte de intrare"
assert all(PMIC[i] > PMARE[i] for i in range(ENTRY, ENTRY + 4)), "mic > mare după intrare"
assert cds[ENTRY].c > PMIC[ENTRY], "candela de trigger nu închide peste pivotul mic"
assert abs(cds[CAPIT].l - sl) < 1e-9, "fitilul barei 15 nu atinge exact SL-ul"
levels = [
Level(13.80, "entry ~13.80 (după M+A)", GREEN, label_at="left"),
Level(sl, "SL swing low absolut 10.63, −23%", RED, label_at="left"),
Level(tp, "TP ~+25% (17.25), ~9 săpt.", BLUE, label_at="left"),
]
marks = [
Mark(CAPIT, f"minim absolut {sl:.2f}", RED, "below", dy=-6),
Mark(ENTRY, "M+A", BLUE, "above"),
]
ch = Chart(candles=cds, levels=levels, marks=marks,
scale=17.0, gap=15, body_w=9, left=44, width=720, top=64, vol_h=70,
vol_label="volum", title="NVDA — weekly (pre-split 1:10)",
caption="Bottom oct. 2022: entry ~13.80, −23%, ~+25% în ~9 săpt. "
"Traseu și pivoți construiți (cursul nu dă valorile lor).")
svg = ch.render()
def step_points(vals: list[float]) -> str:
"""Polilinie în trepte: orizontal pe fiecare palier, vertical la schimbare."""
pts: list[tuple[float, float]] = []
for i, v in enumerate(vals):
x, y = ch._cx(i), ch._y(v)
if i == 0:
pts.append((x, y))
elif v != vals[i - 1]:
pts.append((x, ch._y(vals[i - 1]))) # orizontal până la bara nouă
pts.append((x, y)) # salt vertical la nivelul nou
else:
pts.append((x, y))
return " ".join(f"{x:.1f},{y:.1f}" for x, y in pts)
# injectate imediat după tag-ul de deschidere => desenate în spatele candelelor
inject = [
f'<polyline points="{step_points(PMARE)}" fill="none" stroke="{GRAY}" stroke-width="1.6"/>',
f'<polyline points="{step_points(PMIC)}" fill="none" stroke="{BLUE}" stroke-width="1.6"/>',
f'<text x="712" y="{ch._y(PMIC[-1]) - 6:.1f}" fill="{BLUE}" text-anchor="end">'
f'pivot weekly (mic)</text>',
f'<text x="712" y="{ch._y(PMARE[-1]) + 14:.1f}" fill="{GRAY}" text-anchor="end">'
f'pivot monthly (mare)</text>',
]
i = svg.index(">") + 1
svg = svg[:i] + "\n " + "\n ".join(inject) + svg[i:]
assert svg.count("\n\n") == 0, "linie goală în SVG rupe blocul din markdown"
OUT.write_text(svg)
print(f"scris {OUT.name}: {len(cds)} candele, entry {entry:.2f}, "
f"SL {sl:.2f} ({loss_pct:+.1f}%), TP {tp:.2f} "
f"({(tp/entry - 1) * 100:+.1f}%), crossing la bara {ENTRY}")

View File

@@ -0,0 +1,132 @@
<svg viewBox="0 0 720 603" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif">
<polyline points="44.0,97.2 59.0,97.2 74.0,97.2 89.0,97.2 104.0,97.2 119.0,97.2 134.0,97.2 149.0,97.2 164.0,97.2 179.0,97.2 194.0,97.2 194.0,267.2 209.0,267.2 224.0,267.2 239.0,267.2 254.0,267.2 269.0,267.2 284.0,267.2 299.0,267.2 314.0,267.2 329.0,267.2 344.0,267.2 344.0,393.8 359.0,393.8 374.0,393.8 389.0,393.8 404.0,393.8 419.0,393.8 434.0,393.8 449.0,393.8 464.0,393.8 464.0,399.8 479.0,399.8 494.0,399.8 509.0,399.8 524.0,399.8 539.0,399.8 554.0,399.8 569.0,399.8 584.0,399.8 599.0,399.8" fill="none" stroke="#777" stroke-width="1.6"/>
<polyline points="44.0,105.7 59.0,105.7 74.0,105.7 89.0,105.7 104.0,105.7 119.0,105.7 119.0,131.2 134.0,131.2 149.0,131.2 164.0,131.2 179.0,131.2 194.0,131.2 194.0,284.2 209.0,284.2 224.0,284.2 239.0,284.2 254.0,284.2 254.0,335.2 269.0,335.2 284.0,335.2 299.0,335.2 314.0,335.2 314.0,410.0 329.0,410.0 344.0,410.0 359.0,410.0 359.0,404.0 374.0,404.0 389.0,404.0 389.0,399.8 404.0,399.8 419.0,399.8 419.0,391.3 434.0,391.3 449.0,391.3 464.0,391.3 464.0,382.8 479.0,382.8 494.0,382.8 509.0,382.8 524.0,382.8 524.0,376.0 539.0,376.0 554.0,376.0 569.0,376.0 584.0,376.0 599.0,376.0" fill="none" stroke="#1a5fb4" stroke-width="1.6"/>
<text x="712" y="370.0" fill="#1a5fb4" text-anchor="end">pivot weekly (mic)</text>
<text x="712" y="413.8" fill="#777" text-anchor="end">pivot monthly (mare)</text>
<text x="24" y="78" fill="#333" style="font-weight:bold">NVDA — weekly (pre-split 1:10)</text>
<line x1="24" y1="411.6" x2="706" y2="411.6" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30" y="405.6" fill="#188a3e">entry ~13.80 (după M+A)</text>
<line x1="24" y1="465.4" x2="706" y2="465.4" stroke="#c00" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30" y="459.4" fill="#c00">SL swing low absolut 10.63, −23%</text>
<line x1="24" y1="352.9" x2="706" y2="352.9" stroke="#1a5fb4" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30" y="346.9" fill="#1a5fb4">TP ~+25% (17.25), ~9 săpt.</text>
<line x1="44.0" y1="86.0" x2="44.0" y2="108.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="39.5" y="92.0" width="9" height="10.2" fill="#c00"/>
<line x1="59.0" y1="96.2" x2="59.0" y2="128.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="54.5" y="102.2" width="9" height="20.4" fill="#c00"/>
<line x1="74.0" y1="116.6" x2="74.0" y2="148.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="69.5" y="122.6" width="9" height="20.4" fill="#c00"/>
<line x1="89.0" y1="137.0" x2="89.0" y2="164.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="84.5" y="143.0" width="9" height="15.3" fill="#c00"/>
<line x1="104.0" y1="152.3" x2="104.0" y2="186.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="99.5" y="158.3" width="9" height="22.1" fill="#c00"/>
<line x1="119.0" y1="174.4" x2="119.0" y2="201.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="114.5" y="180.4" width="9" height="15.3" fill="#c00"/>
<line x1="134.0" y1="189.7" x2="134.0" y2="222.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="129.5" y="195.7" width="9" height="20.4" fill="#c00"/>
<line x1="149.0" y1="210.1" x2="149.0" y2="240.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="144.5" y="216.1" width="9" height="18.7" fill="#c00"/>
<line x1="164.0" y1="228.8" x2="164.0" y2="250.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="159.5" y="234.8" width="9" height="10.2" fill="#c00"/>
<line x1="179.0" y1="239.0" x2="179.0" y2="273.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="174.5" y="245.0" width="9" height="22.1" fill="#c00"/>
<line x1="194.0" y1="261.1" x2="194.0" y2="293.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="189.5" y="267.1" width="9" height="20.4" fill="#c00"/>
<line x1="209.0" y1="281.5" x2="209.0" y2="313.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="204.5" y="287.5" width="9" height="20.4" fill="#c00"/>
<line x1="224.0" y1="301.9" x2="224.0" y2="337.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="219.5" y="307.9" width="9" height="23.8" fill="#c00"/>
<line x1="239.0" y1="325.7" x2="239.0" y2="364.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="234.5" y="331.7" width="9" height="27.2" fill="#c00"/>
<line x1="254.0" y1="353.8" x2="254.0" y2="392.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="249.5" y="358.9" width="9" height="28.9" fill="#c00"/>
<line x1="269.0" y1="384.4" x2="269.0" y2="465.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="264.5" y="387.8" width="9" height="64.6" fill="#c00"/>
<line x1="284.0" y1="440.5" x2="284.0" y2="457.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="279.5" y="445.6" width="9" height="6.8" fill="#188a3e"/>
<line x1="299.0" y1="435.4" x2="299.0" y2="450.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="294.5" y="440.5" width="9" height="5.1" fill="#188a3e"/>
<line x1="314.0" y1="431.1" x2="314.0" y2="445.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="309.5" y="436.2" width="9" height="4.2" fill="#188a3e"/>
<line x1="329.0" y1="431.1" x2="329.0" y2="443.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="324.5" y="436.2" width="9" height="2.6" fill="#c00"/>
<line x1="344.0" y1="427.7" x2="344.0" y2="443.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="339.5" y="432.8" width="9" height="6.0" fill="#188a3e"/>
<line x1="359.0" y1="422.6" x2="359.0" y2="437.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="354.5" y="427.7" width="9" height="5.1" fill="#188a3e"/>
<line x1="374.0" y1="419.2" x2="374.0" y2="432.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="369.5" y="424.3" width="9" height="3.4" fill="#188a3e"/>
<line x1="389.0" y1="414.1" x2="389.0" y2="429.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="384.5" y="419.2" width="9" height="5.1" fill="#188a3e"/>
<line x1="404.0" y1="410.7" x2="404.0" y2="424.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="399.5" y="415.8" width="9" height="3.4" fill="#188a3e"/>
<line x1="419.0" y1="407.3" x2="419.0" y2="419.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="414.5" y="411.6" width="9" height="4.2" fill="#188a3e"/>
<line x1="434.0" y1="401.4" x2="434.0" y2="416.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="429.5" y="406.5" width="9" height="5.1" fill="#188a3e"/>
<line x1="449.0" y1="395.4" x2="449.0" y2="411.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="444.5" y="400.5" width="9" height="5.9" fill="#188a3e"/>
<line x1="464.0" y1="389.5" x2="464.0" y2="405.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="459.5" y="394.6" width="9" height="6.0" fill="#188a3e"/>
<line x1="479.0" y1="384.4" x2="479.0" y2="399.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="474.5" y="389.5" width="9" height="5.1" fill="#188a3e"/>
<line x1="494.0" y1="378.4" x2="494.0" y2="394.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="489.5" y="383.5" width="9" height="5.9" fill="#188a3e"/>
<line x1="509.0" y1="372.5" x2="509.0" y2="388.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="504.5" y="377.6" width="9" height="6.0" fill="#188a3e"/>
<line x1="524.0" y1="367.4" x2="524.0" y2="382.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="519.5" y="372.5" width="9" height="5.1" fill="#188a3e"/>
<line x1="539.0" y1="367.4" x2="539.0" y2="381.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="534.5" y="372.5" width="9" height="3.4" fill="#c00"/>
<line x1="554.0" y1="364.0" x2="554.0" y2="381.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="549.5" y="369.1" width="9" height="6.8" fill="#188a3e"/>
<line x1="569.0" y1="358.9" x2="569.0" y2="374.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="564.5" y="364.0" width="9" height="5.1" fill="#188a3e"/>
<line x1="584.0" y1="352.9" x2="584.0" y2="369.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="579.5" y="358.0" width="9" height="5.9" fill="#188a3e"/>
<line x1="599.0" y1="347.8" x2="599.0" y2="363.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="594.5" y="352.9" width="9" height="5.1" fill="#188a3e"/>
<line x1="24" y1="561.4" x2="706" y2="561.4" stroke="#888"/>
<rect x="39.5" y="531.1" width="9" height="30.3" fill="#c00" opacity="0.55"/>
<rect x="54.5" y="529.4" width="9" height="32.1" fill="#c00" opacity="0.55"/>
<rect x="69.5" y="532.3" width="9" height="29.2" fill="#c00" opacity="0.55"/>
<rect x="84.5" y="527.6" width="9" height="33.8" fill="#c00" opacity="0.55"/>
<rect x="99.5" y="529.9" width="9" height="31.5" fill="#c00" opacity="0.55"/>
<rect x="114.5" y="532.9" width="9" height="28.6" fill="#c00" opacity="0.55"/>
<rect x="129.5" y="528.8" width="9" height="32.7" fill="#c00" opacity="0.55"/>
<rect x="144.5" y="531.1" width="9" height="30.3" fill="#c00" opacity="0.55"/>
<rect x="159.5" y="526.4" width="9" height="35.0" fill="#c00" opacity="0.55"/>
<rect x="174.5" y="528.2" width="9" height="33.2" fill="#c00" opacity="0.55"/>
<rect x="189.5" y="524.7" width="9" height="36.8" fill="#c00" opacity="0.55"/>
<rect x="204.5" y="521.8" width="9" height="39.7" fill="#c00" opacity="0.55"/>
<rect x="219.5" y="519.4" width="9" height="42.0" fill="#c00" opacity="0.55"/>
<rect x="234.5" y="514.8" width="9" height="46.7" fill="#c00" opacity="0.55"/>
<rect x="249.5" y="508.9" width="9" height="52.5" fill="#c00" opacity="0.55"/>
<rect x="264.5" y="491.4" width="9" height="70.0" fill="#c00" opacity="0.55"/>
<rect x="279.5" y="503.1" width="9" height="58.3" fill="#188a3e" opacity="0.55"/>
<rect x="294.5" y="519.4" width="9" height="42.0" fill="#188a3e" opacity="0.55"/>
<rect x="309.5" y="526.4" width="9" height="35.0" fill="#188a3e" opacity="0.55"/>
<rect x="324.5" y="529.4" width="9" height="32.1" fill="#c00" opacity="0.55"/>
<rect x="339.5" y="527.6" width="9" height="33.8" fill="#188a3e" opacity="0.55"/>
<rect x="354.5" y="525.3" width="9" height="36.2" fill="#188a3e" opacity="0.55"/>
<rect x="369.5" y="522.9" width="9" height="38.5" fill="#188a3e" opacity="0.55"/>
<rect x="384.5" y="520.6" width="9" height="40.8" fill="#188a3e" opacity="0.55"/>
<rect x="399.5" y="515.9" width="9" height="45.5" fill="#188a3e" opacity="0.55"/>
<rect x="414.5" y="506.0" width="9" height="55.4" fill="#188a3e" opacity="0.55"/>
<rect x="429.5" y="510.1" width="9" height="51.3" fill="#188a3e" opacity="0.55"/>
<rect x="444.5" y="514.8" width="9" height="46.7" fill="#188a3e" opacity="0.55"/>
<rect x="459.5" y="518.3" width="9" height="43.2" fill="#188a3e" opacity="0.55"/>
<rect x="474.5" y="520.6" width="9" height="40.8" fill="#188a3e" opacity="0.55"/>
<rect x="489.5" y="521.8" width="9" height="39.7" fill="#188a3e" opacity="0.55"/>
<rect x="504.5" y="519.4" width="9" height="42.0" fill="#188a3e" opacity="0.55"/>
<rect x="519.5" y="517.1" width="9" height="44.3" fill="#188a3e" opacity="0.55"/>
<rect x="534.5" y="520.6" width="9" height="40.8" fill="#c00" opacity="0.55"/>
<rect x="549.5" y="518.3" width="9" height="43.2" fill="#188a3e" opacity="0.55"/>
<rect x="564.5" y="515.9" width="9" height="45.5" fill="#188a3e" opacity="0.55"/>
<rect x="579.5" y="512.4" width="9" height="49.0" fill="#188a3e" opacity="0.55"/>
<rect x="594.5" y="507.8" width="9" height="53.7" fill="#188a3e" opacity="0.55"/>
<text x="24" y="485.4" fill="#555">volum</text>
<text x="269.0" y="479.4" fill="#c00" text-anchor="middle" style="font-weight:bold">minim absolut 10.63</text>
<text x="419.0" y="397.3" fill="#1a5fb4" text-anchor="middle" style="font-weight:bold">M+A</text>
<text x="24" y="591" fill="#555">Bottom oct. 2022: entry ~13.80, −23%, ~+25% în ~9 săpt. Traseu și pivoți construiți (cursul nu dă valorile lor).</text>
</svg>

After

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -1,13 +1,13 @@
<svg viewBox="0 0 480 688" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif">
<g transform="translate(0,0)">
<polyline points="44.0,182.3 59.0,182.3 74.0,182.3 89.0,182.3 104.0,182.3 119.0,182.3 134.0,182.3 149.0,182.3 164.0,182.3 179.0,182.3 194.0,182.3 194.0,134.8 209.0,134.8 224.0,134.8 239.0,134.8 254.0,134.8 269.0,134.8 284.0,134.8 299.0,134.8 314.0,134.8 329.0,134.8 344.0,134.8 359.0,134.8" fill="none" stroke="#b06000" stroke-width="1.8"/>
<text x="470" y="128.8" fill="#b06000" text-anchor="end" style="font-weight:bold">pivot daily (cel MIC)</text>
<polyline points="44.0,160.3 59.0,160.3 74.0,160.3 89.0,160.3 104.0,160.3 119.0,160.3 134.0,160.3 149.0,160.3 164.0,160.3 179.0,160.3 194.0,160.3 194.0,112.8 209.0,112.8 224.0,112.8 239.0,112.8 254.0,112.8 269.0,112.8 284.0,112.8 299.0,112.8 314.0,112.8 329.0,112.8 344.0,112.8 359.0,112.8" fill="none" stroke="#b06000" stroke-width="1.8"/>
<text x="470" y="106.8" fill="#b06000" text-anchor="end" style="font-weight:bold">pivot daily (cel MIC)</text>
<text x="24" y="48" fill="#333" style="font-weight:bold">DA — crossing (+2)</text>
<line x1="24" y1="153.9" x2="466" y2="153.9" stroke="#1a5fb4" stroke-width="1.5" stroke-dasharray=""/>
<text x="452" y="147.9" fill="#1a5fb4" text-anchor="end">pivot weekly (cel MARE) 62.00</text>
<circle cx="194.0" cy="158.6" r="13" fill="none" stroke="#188a3e" stroke-width="2"/>
<text x="210.0" y="200.3" fill="#188a3e" style="font-weight:bold">crossing: 61.70 → 62.20</text>
<text x="213.0" y="85.0" fill="#188a3e" text-anchor="end" style="font-weight:bold">intrare: trigger</text>
<circle cx="194.0" cy="136.6" r="13" fill="none" stroke="#188a3e" stroke-width="2"/>
<text x="210.0" y="178.3" fill="#188a3e" style="font-weight:bold">crossing: 61.70 → 62.20</text>
<text x="213.0" y="63.0" fill="#188a3e" text-anchor="end" style="font-weight:bold">intrare: trigger</text>
<line x1="44.0" y1="201.4" x2="44.0" y2="229.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="39.5" y="209.0" width="9" height="11.4" fill="#c00"/>
<line x1="59.0" y1="212.8" x2="59.0" y2="244.1" stroke="#1a1a1a" stroke-width="1.2"/>
@@ -54,8 +54,8 @@
<rect x="354.5" y="63.6" width="9" height="4.8" fill="#188a3e"/>
</g>
<g transform="translate(0,314)">
<polyline points="44.0,139.6 59.0,139.6 74.0,139.6 89.0,139.6 104.0,139.6 119.0,139.6 134.0,139.6 149.0,139.6 164.0,139.6 179.0,139.6 179.0,149.1 194.0,149.1 209.0,149.1 224.0,149.1 239.0,149.1 254.0,149.1 269.0,149.1 284.0,149.1 299.0,149.1 314.0,149.1 329.0,149.1 344.0,149.1 359.0,149.1" fill="none" stroke="#b06000" stroke-width="1.8"/>
<text x="470" y="143.1" fill="#b06000" text-anchor="end" style="font-weight:bold">pivot daily (cel MIC)</text>
<polyline points="44.0,117.6 59.0,117.6 74.0,117.6 89.0,117.6 104.0,117.6 119.0,117.6 134.0,117.6 149.0,117.6 164.0,117.6 179.0,117.6 179.0,127.1 194.0,127.1 209.0,127.1 224.0,127.1 239.0,127.1 254.0,127.1 269.0,127.1 284.0,127.1 299.0,127.1 314.0,127.1 329.0,127.1 344.0,127.1 359.0,127.1" fill="none" stroke="#b06000" stroke-width="1.8"/>
<text x="470" y="121.1" fill="#b06000" text-anchor="end" style="font-weight:bold">pivot daily (cel MIC)</text>
<text x="24" y="48" fill="#333" style="font-weight:bold">NU — continuare/buy the dip (+1)</text>
<line x1="24" y1="168.1" x2="466" y2="168.1" stroke="#1a5fb4" stroke-width="1.5" stroke-dasharray=""/>
<text x="452" y="162.1" fill="#1a5fb4" text-anchor="end">pivot weekly (cel MARE) 62.00</text>

Before

Width:  |  Height:  |  Size: 9.4 KiB

After

Width:  |  Height:  |  Size: 9.4 KiB

View File

@@ -0,0 +1,70 @@
"""MP² — ieșirea în două poziții (Pasul 6 din `02_mp2.md`).
Aceeași serie, de la bara dinaintea trigger-ului încolo. Poziția 1 iese la
TP1 (1:1). Poziția 2 nu are țintă fixă: merge pe bull trail — low-ul
fiecărei bare care face un maxim nou — și iese la prima ÎNCHIDERE sub linie.
Între timp, când prețul a făcut 60 % din drumul spre TP1, stopul amândurora
urcă la break-even, adică la prețul de intrare.
Rulare: python3 gen/strategii/mp2_iesire.py
"""
import re
import sys
from pathlib import Path
sys.path.insert(0, "/workspace/atm-curs-dl")
sys.path.insert(0, str(Path(__file__).parent))
from svg_candles import Arrow, Chart, Level # noqa: E402
import mp2_serie as S # noqa: E402
OUT = Path(__file__).with_suffix(".svg")
RED, BLUE, GRAY, GREEN, ORANGE = "#c00", "#1a5fb4", "#777", "#188a3e", "#b06000"
W, A = 720, 21
cds = S.CDS[A:]
# linia de trail contează pentru poziția 2, adică de la TP1 încolo
trail = [v if i + A >= S.I_TP1 else None for i, v in enumerate(S.TRAIL[A:])]
i_tp1, i_be, i_out, i_tr = S.I_TP1 - A, S.I_BE - A, S.IESIRE - A, S.TRIGGER - A
R_OUT = round((S.IES_PRET - S.ENTRY) / S.R, 2)
assert trail[i_out] is not None and cds[i_out].c < trail[i_out]
assert cds[i_be].h >= S.BE and cds[i_be - 1].h < S.BE, "BE atins în altă bară"
assert S.IES_PRET > S.TP1 > S.BE > S.ENTRY
ch = Chart(
candles=cds,
levels=[Level(S.TP1, f"TP1 {S.TP1:.2f} = intrarea + 1R", GREEN, "2 3", "left"),
Level(S.BE, f"{S.BE:.2f} = 60 % din drum", ORANGE, "1 3", "left"),
Level(S.ENTRY, f"intrarea {S.ENTRY:.2f}", "#333", "4 3", "left"),
Level(S.SL, f"stopul inițial {S.SL:.2f}", RED, "6 3", "right")],
arrows=[
Arrow(i_tp1, f"poziția 1 (jumătate) iese la {S.TP1:.2f}\nexact cât riscai: 1:1, "
f"fără discuție",
where="above", price=S.TP1, color=GREEN, dx=-110, dy=-8),
Arrow(i_out, f"poziția 2 iese la {S.IES_PRET:.2f}\nprima ÎNCHIDERE sub linia de trail "
f"({trail[i_out]:.2f}),\nnu primul fitil care o atinge = +{R_OUT:.2f}R",
where="below", color=ORANGE, dx=-74, dy=34),
],
scale=17.0, gap=32, body_w=15, left=58, width=W, top=40,
title="Pasul 6 — o jumătate la țintă fixă, cealaltă pe trail",
caption="Linia portocalie = bull trail: low-ul ultimei bare cu maxim nou. "
f"Rezultat: +1R pe o jumătate, +{R_OUT:.2f}R pe cealaltă.")
svg = ch.render()
off = S.offset(svg, ch)
inject = [
f'<polyline points="{S.trepte(ch, trail, off)}" fill="none" stroke="{ORANGE}" '
f'stroke-width="1.8"/>',
]
# bara la care stopul urcă la break-even
x = ch._cx(i_be)
inject.append(f'<line x1="{x:.1f}" y1="{ch._y(S.BE) + off:.1f}" x2="{x:.1f}" '
f'y2="{ch._y(S.ENTRY) + off:.1f}" stroke="{ORANGE}" stroke-width="1.4" '
f'stroke-dasharray="3 3"/>')
inject.append(f'<text x="{x + 6:.1f}" y="{(ch._y(S.BE) + ch._y(S.ENTRY)) / 2 + off:.1f}" '
f'fill="{ORANGE}" style="font-weight:bold">stopul urcă la break-even</text>')
svg = S.injecteaza(svg, inject)
h = float(re.search(r'viewBox="0 0 [\d.]+ ([\d.]+)"', svg).group(1))
w = float(re.search(r'viewBox="0 0 ([\d.]+)', svg).group(1))
S.scrie(OUT, svg, w, h)

View File

@@ -0,0 +1,52 @@
<svg viewBox="0 0 720 387" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif">
<polyline points="250.0,183.5 282.0,183.5 282.0,143.5 314.0,143.5 314.0,119.8 346.0,119.8 346.0,106.2 378.0,106.2 410.0,106.2 410.0,94.2 442.0,94.2 474.0,94.2" fill="none" stroke="#b06000" stroke-width="1.8"/>
<line x1="218.0" y1="181.8" x2="218.0" y2="243.0" stroke="#b06000" stroke-width="1.4" stroke-dasharray="3 3"/>
<text x="224.0" y="212.4" fill="#b06000" style="font-weight:bold">stopul urcă la break-even</text>
<text x="24" y="54" fill="#333" style="font-weight:bold">Pasul 6 — o jumătate la țintă fixă, cealaltă pe trail</text>
<line x1="24" y1="141.0" x2="706" y2="141.0" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="2 3"/>
<text x="30" y="135.0" fill="#188a3e">TP1 598.00 = intrarea + 1R</text>
<line x1="24" y1="181.8" x2="706" y2="181.8" stroke="#b06000" stroke-width="1.5" stroke-dasharray="1 3"/>
<text x="30" y="175.8" fill="#b06000">595.60 = 60 % din drum</text>
<line x1="24" y1="243.0" x2="706" y2="243.0" stroke="#333" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="30" y="237.0" fill="#333">intrarea 592.00</text>
<line x1="24" y1="345.0" x2="706" y2="345.0" stroke="#c00" stroke-width="1.5" stroke-dasharray="6 3"/>
<text x="692" y="339.0" fill="#c00" text-anchor="end">stopul inițial 586.00</text>
<line x1="58.0" y1="299.2" x2="58.0" y2="334.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="50.5" y="304.2" width="15" height="25.5" fill="#c00"/>
<line x1="90.0" y1="324.7" x2="90.0" y2="345.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="82.5" y="329.8" width="15" height="10.2" fill="#c00"/>
<line x1="122.0" y1="326.4" x2="122.0" y2="343.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="114.5" y="331.5" width="15" height="8.5" fill="#188a3e"/>
<line x1="154.0" y1="236.2" x2="154.0" y2="336.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="146.5" y="243.0" width="15" height="88.4" fill="#188a3e"/>
<line x1="186.0" y1="213.3" x2="186.0" y2="249.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="178.5" y="219.2" width="15" height="23.8" fill="#188a3e"/>
<line x1="218.0" y1="170.8" x2="218.0" y2="226.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="210.5" y="176.8" width="15" height="42.5" fill="#188a3e"/>
<line x1="250.0" y1="131.7" x2="250.0" y2="183.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="242.5" y="137.6" width="15" height="39.1" fill="#188a3e"/>
<line x1="282.0" y1="107.9" x2="282.0" y2="143.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="274.5" y="113.8" width="15" height="23.8" fill="#188a3e"/>
<line x1="314.0" y1="80.7" x2="314.0" y2="119.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="306.5" y="86.6" width="15" height="27.2" fill="#188a3e"/>
<line x1="346.0" y1="80.7" x2="346.0" y2="106.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="338.5" y="86.6" width="15" height="13.6" fill="#c00"/>
<line x1="378.0" y1="62.0" x2="378.0" y2="106.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="370.5" y="68.0" width="15" height="32.3" fill="#188a3e"/>
<line x1="410.0" y1="62.0" x2="410.0" y2="94.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="402.5" y="68.0" width="15" height="20.4" fill="#c00"/>
<line x1="442.0" y1="82.4" x2="442.0" y2="116.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="434.5" y="88.3" width="15" height="22.1" fill="#c00"/>
<line x1="474.0" y1="104.5" x2="474.0" y2="131.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="466.5" y="110.5" width="15" height="15.3" fill="#c00"/>
<line x1="140.0" y1="103.0" x2="242.4" y2="134.7" stroke="#188a3e" stroke-width="1.8"/>
<polygon points="250.0,137.0 241.2,138.5 243.5,130.9" fill="#188a3e"/>
<text x="140.0" y="84.0" fill="#188a3e" text-anchor="middle" style="font-weight:bold">poziția 1 (jumătate) iese la 598.00</text>
<text x="140.0" y="98.0" fill="#188a3e" text-anchor="middle" style="font-weight:bold">exact cât riscai: 1:1, fără discuție</text>
<line x1="368.0" y1="268.0" x2="438.4" y2="127.6" stroke="#b06000" stroke-width="1.8"/>
<polygon points="442.0,120.4 442.0,129.3 434.8,125.8" fill="#b06000"/>
<text x="368.0" y="282.0" fill="#b06000" text-anchor="middle" style="font-weight:bold">poziția 2 iese la 599.80</text>
<text x="368.0" y="296.0" fill="#b06000" text-anchor="middle" style="font-weight:bold">prima ÎNCHIDERE sub linia de trail (600.75),</text>
<text x="368.0" y="310.0" fill="#b06000" text-anchor="middle" style="font-weight:bold">nu primul fitil care o atinge = +1.30R</text>
<text x="24" y="375" fill="#555">Linia portocalie = bull trail: low-ul ultimei bare cu maxim nou. Rezultat: +1R pe o jumătate, +1.30R pe cealaltă.</text>
</svg>

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

@@ -0,0 +1,302 @@
#!/usr/bin/env python3
"""MP² — perechea de timeframe-uri, cu lupă (Pasul 1 din `02_mp2.md`).
Stânga: graficul daily, unde trăiesc cei doi pivoți și unde se vede
crossing-ul. Dreapta: graficul de 60 de minute, unde intri.
Graficul din dreapta NU e o serie care vine după cel din stânga: e
**descompunerea reală** a ultimelor două candele daily. O ședință = 7 bare
de 60 de minute (9:30-16:00 înseamnă 6 ore și jumătate, deci ultima bară a
zilei e de 30 de minute), cu același open, același close, același maxim și
același minim — verificat bară cu bară prin assert. Sursa de adevăr e seria
fină din `mp2_serie.py`; candelele daily se calculează din ea prin agregare.
Caseta punctată de pe panoul mare arată exact ce bucată e mărită; ghidajele
îi leagă colțurile de cadrul mic; cele două linii de pivot sunt trasate pe
ambele panouri, cu același număr de ambele părți, iar conectorul subțire
leagă cele două înălțimi ale aceluiași preț. Nu se pot alinia: scările au
pante diferite, e o lupă, nu o eroare.
Rulare: python3 gen/strategii/mp2_perechi_tf.py
"""
import sys
from pathlib import Path
sys.path.insert(0, "/workspace/atm-curs-dl")
sys.path.insert(0, str(Path(__file__).parent))
import mp2_serie as S # noqa: E402
OUT = Path(__file__).with_suffix(".svg")
W, PLOT_H = 720, 190
GREEN, RED, GRAY, INK, BLUE, ORANGE = "#188a3e", "#c00", "#888", "#333", "#1a5fb4", "#b06000"
LINK = "#aaa"
BX0, BGAP = 96, 22 # panoul daily
SX0, SGAP = 374, 15 # panoul de 60 min
BODY_W = 9
FRAME_L = SX0 - 9
COL_X = 586
MIDX = FRAME_L - 20 # granița stânga/dreapta pentru verificări
PAD = 0.06 # aer sus/jos pe panoul mic
TOP = 86
# --- zilele dinaintea ferestrei fine, ca daily (open = close precedent) -------
DOWN_C = [634.00, 626.00, 629.00, 618.00, 610.00, 612.00, 598.00, 585.00]
DOWN_W = 2.5
ZI_FINA = 2 # câte ședințe sunt desfăcute în panoul mic
def daily_din_closes(closes, start, w):
out, o = [], start
for c in closes:
out.append((o, max(o, c) + w, min(o, c) - w, c))
o = c
return out
A_FIN, B_FIN = (S.ZI4 + 1 - ZI_FINA) * S.BARE_ZI, (S.ZI4 + 1) * S.BARE_ZI
zile = S.zilnice(S.CDS)
fine = [(c.o, c.h, c.l, c.c) for c in S.CDS[A_FIN:B_FIN]]
zoom = [(z.o, z.h, z.l, z.c) for z in zile[S.ZI4 + 1 - ZI_FINA:S.ZI4 + 1]]
base = (daily_din_closes(DOWN_C, 640.00, DOWN_W)
+ [(z.o, z.h, z.l, z.c) for z in zile[:S.ZI4 + 1 - ZI_FINA]])
big = base + zoom
PPD_ZI = [None] * len(DOWN_C) + S.PPD[:S.ZI4 + 1] # pivotul mic, pe candele daily
PPD_FIN = S.PPD_BARA[A_FIN:B_FIN]
N_BASE = len(base)
# --- ce afirmă desenul, verificat pe serii ------------------------------------
for nume, bars in (("daily", big), ("60 min", fine)):
for i, (o, h, l, c) in enumerate(bars):
assert h >= max(o, c) and l <= min(o, c), f"{nume}[{i}] h/l incoerent"
if i:
assert abs(o - bars[i - 1][3]) < 1e-9, f"{nume}[{i}] open != close precedent"
assert len(fine) == S.BARE_ZI * ZI_FINA
# 1. descompunerea e reală: fiecare candelă daily mărită = 7 bare de 60 min
for j, (o, h, l, c) in enumerate(zoom):
part = fine[j * S.BARE_ZI:(j + 1) * S.BARE_ZI]
assert (o, c) == (part[0][0], part[-1][3])
assert h == max(b[1] for b in part) and l == min(b[2] for b in part)
# 2. lupa se leagă de restul graficului mare
assert abs(fine[0][0] - base[-1][3]) < 1e-9, "open-ul primei bare fine != close-ul ultimei daily"
# 3. trigger-ul cade în a doua candelă daily mărită, nu în prima
I_TRIG = S.TRIGGER - A_FIN
assert I_TRIG // S.BARE_ZI == 1, "trigger-ul nu cade în ultima candelă daily"
assert PPD_FIN[I_TRIG] == S.PPD[S.ZI4] > S.PPW > PPD_FIN[0], "crossing-ul nu e în fereastră"
# 4. trade-ul pe TF-ul mic
ENTRY, SL, R, TP1 = S.ENTRY, S.SL, S.R, S.TP1
assert SL == min(b[2] for b in fine[I_TRIG - S.BARE_STOP + 1:I_TRIG + 1])
PCT = R / ENTRY * 100
# 5. același setup, dacă ai fi intrat pe daily: alt trigger, alt stop
B_ENTRY = big[-1][3] # close-ul candelei daily de trigger
B_SL = min(b[2] for b in big[-S.BARE_STOP:]) # low-ul ultimelor 4 candele daily
B_R = round(B_ENTRY - B_SL, 2)
B_PCT = B_R / B_ENTRY * 100
assert B_SL == S.SWING_LOW == 580.00 and B_R == 18.20, (B_SL, B_R)
RAPORT = B_PCT / PCT
assert 2.9 <= RAPORT <= 3.1, f"raportul stopurilor e {RAPORT:.2f}"
# 6. cadrul mic cuprinde și pivotul mare, ca nivelul comun să aibă unde sta
ZLO, ZHI = min(b[2] for b in fine), max(b[1] for b in fine)
assert ZLO == min(b[2] for b in zoom) and ZHI == max(b[1] for b in zoom)
assert S.PPW < ZLO, "pivotul mare e în interiorul barelor mici; verifică scara"
lo_, hi_ = min(ZLO, S.PPW), ZHI
pad = PAD * (hi_ - lo_)
LO, HI = lo_ - pad, hi_ + pad
bmax = max(b[1] for b in big)
bmin = min(min(b[2] for b in big), B_SL, LO)
bs, ss = PLOT_H / (bmax - bmin), PLOT_H / (HI - LO)
assert ss / bs > 2.5, f"lupa mărește de doar {ss / bs:.1f} ori"
def yb(p):
return TOP + (bmax - p) * bs
def ys(p):
return TOP + (HI - p) * ss
# --- desen --------------------------------------------------------------------
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) * (5.7 if size >= 12 else size * 0.5)
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 pânză: {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="{";".join(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}" stroke="{color}" '
f'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 ""
mk = 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}{mk}/>')
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}" height="{y1 - y0:.1f}" '
f'fill="{color}" fill-opacity="{fill_op}" 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))
out.append(f'<rect x="{cx - BODY_W / 2:.1f}" y="{top_:.1f}" width="{BODY_W}" '
f'height="{max(yf(min(o, c)) - top_, 1.6):.1f}" '
f'fill="{GREEN if c >= o else RED}"/>')
def trepte(vals, x0, gap, yf):
pts = []
for i, v in enumerate(vals):
if v is None:
continue
x, y = x0 + i * gap, yf(v)
if pts and vals[i - 1] is not None and v != vals[i - 1]:
pts.append((x, yf(vals[i - 1])))
pts.append((x, y))
return " ".join(f"{x:.1f},{y:.1f}" for x, y in pts)
def bracket(x, ya, yb_, color, label, side="right", below=False):
tip = x + 5 if side == "right" else x - 5
out.append(f'<path d="M{tip:.1f},{ya:.1f} H{x:.1f} V{yb_:.1f} H{tip:.1f}" fill="none" '
f'stroke="{color}" stroke-width="1.6"/>')
if below:
text((x + tip) / 2, max(ya, yb_) + 14, label, fill=color, anchor="middle", bold=True, size=11)
else:
text(tip + 4, (ya + yb_) / 2 + 4, label, fill=color, bold=True, size=11)
def stack(items, x_line):
y_prev = None
for y, lines, fill in sorted(items, key=lambda t: t[0]):
y_lab = y if y_prev is None or y >= y_prev + 15 else y_prev + 15
out.append(f'<path d="M{x_line + 2:.1f},{y - 4:.1f} H{x_line + 7:.1f} '
f'L{COL_X - 4:.1f},{y_lab - 4:.1f}" fill="none" stroke="{fill}" '
f'stroke-width="0.8" stroke-opacity="0.8"/>')
for j, s in enumerate(lines):
text(COL_X, y_lab + j * 13, s, fill=fill, size=10)
y_prev = y_lab + (len(lines) - 1) * 13
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, "Pasul 1 — perechea de timeframe-uri: pivoții stau pe daily, intrarea se face pe 60 min",
bold=True, size=13)
text(20, 40, "Graficul din dreapta e aceeași bucată de piață, mărită: fiecare candelă daily din "
"caseta punctată", fill="#555", size=11)
text(20, 54, f"e desfăcută în {S.BARE_ZI} bare de 60 de minute (ședința are 6 ore și jumătate, "
f"deci ultima bară a zilei e de 30 min).", fill="#555", size=11)
text(20, TOP - 8, "daily: direcția", fill="#555", size=11)
text(FRAME_L, TOP - 8, f"60 min: ultimele {ZI_FINA} candele daily, desfăcute", fill="#555", size=11)
# ---- panoul daily ------------------------------------------------------------
lx0, lx1 = BX0 + N_BASE * BGAP - 9, BX0 + (len(big) - 1) * BGAP + 10
ly0, ly1 = yb(HI), yb(LO)
rect(lx0, ly0, lx1, ly1, BLUE, fill_op=0.06, dash="4 3")
hline(BX0 - 18, lx1, yb(S.PPW), GRAY, "8 4")
out.append(f'<polyline points="{trepte(PPD_ZI, BX0, BGAP, yb)}" fill="none" stroke="{BLUE}" '
f'stroke-width="1.8"/>')
candles(big, BX0, BGAP, yb)
text(BX0 - 8, yb(S.PPW) + 14, f"pivot weekly (mare) {S.PPW:.2f}", fill="#666", size=11)
text(BX0 + 2 * BGAP, yb(bmin) + 16, "pivot daily (mic), în trepte", fill=BLUE, size=11)
# stopul, dacă ai fi măsurat pe daily
bracket(34, yb(B_ENTRY), yb(B_SL), RED, f"stop {B_PCT:.2f} %".replace(".", ","), below=True)
# ---- 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 ----------------------------------------------
# Aceeași linie de pivot weekly cade la înălțimi diferite: scările au pante
# diferite. Conectorul le leagă; „același preț" e scris o singură dată, în cot.
ycb, ycs = yb(S.PPW), ys(S.PPW)
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}" fill="none" '
f'stroke="{LINK}" stroke-width="1.0" stroke-dasharray="3 3"/>')
text(mid + 4, (ycb + ycs) / 2 + 4, "același preț", fill="#999", size=10)
# ---- panoul de 60 min --------------------------------------------------------
frame_r = SX0 + (len(fine) - 1) * SGAP + 9
rect(FRAME_L, TOP, frame_r, TOP + PLOT_H, BLUE, fill_op=0.03)
y_e, y_sl, y_tp = ys(ENTRY), ys(SL), ys(TP1)
assert abs((y_sl - y_e) - (y_e - y_tp)) < 1e-6, "1R în sus nu e desenat cât 1R în jos"
assert TOP + PLOT_H - ys(S.PPW) > 6, "linia pivotului mare e lipită de marginea cadrului"
# stopul e minimul ULTIMELOR 4 bare, nu al întregii ferestre: ziua dinainte
# coboară mai jos, iar acele bare nu intră la socoteală
assert y_sl < ys(ZLO), "stopul de 4 bare ar trebui să stea peste minimul ferestrei"
# zona verde peste bara de trigger
sx0, sx1 = SX0 + I_TRIG * SGAP - 9, SX0 + I_TRIG * SGAP + 9
rect(sx0, y_e - 6, sx1, ys(ZLO) + 4, GREEN)
line((sx0 + sx1) / 2, TOP + PLOT_H, (sx0 + sx1) / 2, TOP + PLOT_H + 26, GREEN, width=1)
text((sx0 + sx1) / 2, TOP + PLOT_H + 38, "închide peste pivotul mic: aici intri", fill=GREEN,
anchor="middle", bold=True, size=11)
hline(FRAME_L, frame_r, ys(S.PPW), GRAY, "8 4")
out.append(f'<polyline points="{trepte(PPD_FIN, SX0, SGAP, ys)}" fill="none" stroke="{BLUE}" '
f'stroke-width="1.8"/>')
hline(FRAME_L, frame_r, y_e, GREEN, "6 3")
hline(FRAME_L, frame_r, y_sl, RED, "6 3")
hline(FRAME_L, frame_r, y_tp, GREEN, "2 3")
candles(fine, SX0, SGAP, ys)
stack([(y_tp + 4, [f"TP1 {TP1:.2f}"], GREEN),
(y_e + 4, [f"intrare {ENTRY:.2f}"], GREEN),
(y_sl + 4, [f"stop {SL:.2f}", f"minimul ultimelor", f"{S.BARE_STOP} bare de 60 min"], RED),
(ys(S.PPW) + 4, [f"pivot weekly", f"(mare) {S.PPW:.2f}"], "#666")], frame_r)
kx = SX0 + (I_TRIG + 1) * SGAP + BODY_W / 2 + 1
bracket(kx, y_e, y_sl, RED, f"stop {PCT:.2f} %".replace(".", ","))
# ---- de ce merită lupa -------------------------------------------------------
ya = TOP + PLOT_H + 62
line(34, ya, kx, ya, RED, width=1.6, marker="pt")
text((34 + kx) / 2, ya + 17, f"același setup, stop de {RAPORT:.1f} ori mai mic".replace(".", ","),
fill=RED, anchor="middle", bold=True, size=11)
text((34 + kx) / 2, ya + 31, f"→ de {RAPORT:.1f} ori mai multe acțiuni la același risc în bani"
.replace(".", ","), fill=RED, anchor="middle", bold=True, size=11)
text(20, ya + 52, f"Pe daily ai fi intrat la close-ul zilei ({B_ENTRY:.2f}) cu stopul sub "
f"minimul ultimelor {S.BARE_STOP} zile ({B_SL:.2f}).", fill="#555", size=11)
text(20, ya + 66, "Pe 60 de minute vezi unde s-a oprit coborârea, deci ai de unde măsura un stop "
"mult mai strâns.", fill="#555", size=11)
# --- fiecare preț stă pe panoul lui, cu excepția nivelului comun --------------
COMUN = f"{S.PPW:.2f}"
MARE = {"B_ENTRY": B_ENTRY, "B_SL": B_SL}
MIC = {"ENTRY": ENTRY, "SL": SL, "TP1": TP1}
for x0, _x1, _y, s in LABELS:
pe_mic = x0 >= MIDX
for k, v in (MARE if pe_mic else MIC).items():
assert f"{v:.2f}" not in s, f"eticheta {s!r} poartă prețul {k} al celuilalt panou"
st = [s for x0, _1, _2, s in LABELS if COMUN in s and x0 < MIDX]
dr = [s for x0, _1, _2, s in LABELS if COMUN in s and x0 >= MIDX]
assert st and dr, f"nivelul comun {COMUN} nu apare pe ambele panouri ({st} / {dr})"
for k, v in MIC.items():
assert any(f"{v:.2f}" in s and x0 >= MIDX for x0, _1, _2, s in LABELS), f"{k} lipsește de pe mic"
H = ya + 76
for a in range(len(LABELS)):
assert 0 < LABELS[a][2] < H, f"etichetă în afara pânzei: {LABELS[a][3]!r}"
for b in range(a + 1, len(LABELS)):
xa0, xa1, ya_, sa = LABELS[a]
xb0, xb1, yb_, sb = LABELS[b]
assert not (abs(ya_ - yb_) < 13 and xa0 < xb1 - 4 and xb0 < xa1 - 4), \
f"etichete suprapuse: {sa!r} / {sb!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>")
S.scrie(OUT, svg, W, H)
print(f"lupă x{ss / bs:.1f} | daily: entry {B_ENTRY:.2f} SL {B_SL:.2f} = {B_PCT:.2f} % | "
f"60 min: entry {ENTRY:.2f} SL {SL:.2f} = {PCT:.2f} % | raport {RAPORT:.2f}")

View File

@@ -0,0 +1,98 @@
<svg viewBox="0 0 720 414" 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">Pasul 1 — perechea de timeframe-uri: pivoții stau pe daily, intrarea se face pe 60 min</text>
<text x="20.0" y="40.0" fill="#555" style="font-size:11px">Graficul din dreapta e aceeași bucată de piață, mărită: fiecare candelă daily din caseta punctată</text>
<text x="20.0" y="54.0" fill="#555" style="font-size:11px">e desfăcută în 7 bare de 60 de minute (ședința are 6 ore și jumătate, deci ultima bară a zilei e de 30 min).</text>
<text x="20.0" y="78.0" fill="#555" style="font-size:11px">daily: direcția</text>
<text x="365.0" y="78.0" fill="#555" style="font-size:11px">60 min: ultimele 2 candele daily, desfăcute</text>
<rect x="307.0" y="217.0" width="41.0" height="49.5" fill="#1a5fb4" fill-opacity="0.06" stroke="#1a5fb4" stroke-width="1.2" stroke-dasharray="4 3"/>
<line x1="78.0" y1="263.8" x2="348.0" y2="263.8" stroke="#888" stroke-width="1.5" stroke-dasharray="8 4"/>
<polyline points="272.0,266.3 294.0,266.3 294.0,268.7 316.0,268.7 316.0,266.3 338.0,266.3 338.0,254.3" fill="none" stroke="#1a5fb4" stroke-width="1.8"/>
<line x1="96.0" y1="86.0" x2="96.0" y2="119.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="91.5" y="93.6" width="9" height="18.2" fill="#c00"/>
<line x1="118.0" y1="104.2" x2="118.0" y2="143.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="113.5" y="111.8" width="9" height="24.3" fill="#c00"/>
<line x1="140.0" y1="119.4" x2="140.0" y2="143.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="135.5" y="127.0" width="9" height="9.1" fill="#188a3e"/>
<line x1="162.0" y1="119.4" x2="162.0" y2="168.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="157.5" y="127.0" width="9" height="33.4" fill="#c00"/>
<line x1="184.0" y1="152.9" x2="184.0" y2="192.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="179.5" y="160.5" width="9" height="24.3" fill="#c00"/>
<line x1="206.0" y1="171.1" x2="206.0" y2="192.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="201.5" y="178.7" width="9" height="6.1" fill="#188a3e"/>
<line x1="228.0" y1="171.1" x2="228.0" y2="228.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="223.5" y="178.7" width="9" height="42.6" fill="#c00"/>
<line x1="250.0" y1="213.7" x2="250.0" y2="268.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="245.5" y="221.3" width="9" height="39.5" fill="#c00"/>
<line x1="272.0" y1="259.6" x2="272.0" y2="274.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="267.5" y="260.8" width="9" height="11.6" fill="#c00"/>
<line x1="294.0" y1="260.8" x2="294.0" y2="276.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="289.5" y="262.0" width="9" height="10.3" fill="#188a3e"/>
<line x1="316.0" y1="249.2" x2="316.0" y2="263.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="311.5" y="250.5" width="9" height="11.6" fill="#188a3e"/>
<line x1="338.0" y1="219.6" x2="338.0" y2="257.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="333.5" y="220.7" width="9" height="29.8" fill="#188a3e"/>
<text x="88.0" y="277.8" fill="#666" style="font-size:11px">pivot weekly (mare) 584.00</text>
<text x="140.0" y="292.0" fill="#1a5fb4" style="font-size:11px">pivot daily (mic), în trepte</text>
<path d="M39.0,220.7 H34.0 V276.0 H39.0" fill="none" stroke="#c00" stroke-width="1.6"/>
<text x="36.5" y="290.0" fill="#c00" text-anchor="middle" style="font-size:11px;font-weight:bold">stop 3,04 %</text>
<line x1="348.0" y1="217.0" x2="365.0" y2="86.0" stroke="#1a5fb4" stroke-width="1.1" stroke-dasharray="5 3"/>
<line x1="348.0" y1="266.5" x2="365.0" y2="276.0" stroke="#1a5fb4" stroke-width="1.1" stroke-dasharray="5 3"/>
<path d="M348.0,263.8 H356.5 V265.8 H365.0" fill="none" stroke="#aaa" stroke-width="1.0" stroke-dasharray="3 3"/>
<text x="360.5" y="268.8" fill="#999" style="font-size:10px">același preț</text>
<rect x="365.0" y="86.0" width="213.0" height="190.0" fill="#1a5fb4" fill-opacity="0.03" stroke="#1a5fb4" stroke-width="1.2"/>
<rect x="515.0" y="166.5" width="18.0" height="100.9" fill="#188a3e" fill-opacity="0.1" stroke="#188a3e" stroke-width="1.2"/>
<line x1="524.0" y1="276.0" x2="524.0" y2="302.0" stroke="#188a3e" stroke-width="1"/>
<text x="524.0" y="314.0" fill="#188a3e" text-anchor="middle" style="font-size:11px;font-weight:bold">închide peste pivotul mic: aici intri</text>
<line x1="365.0" y1="265.8" x2="578.0" y2="265.8" stroke="#888" stroke-width="1.5" stroke-dasharray="8 4"/>
<polyline points="374.0,275.1 389.0,275.1 404.0,275.1 419.0,275.1 434.0,275.1 449.0,275.1 464.0,275.1 479.0,275.1 479.0,229.3 494.0,229.3 509.0,229.3 524.0,229.3 539.0,229.3 554.0,229.3 569.0,229.3" fill="none" stroke="#1a5fb4" stroke-width="1.8"/>
<line x1="365.0" y1="172.5" x2="578.0" y2="172.5" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="6 3"/>
<line x1="365.0" y1="242.5" x2="578.0" y2="242.5" stroke="#c00" stroke-width="1.5" stroke-dasharray="6 3"/>
<line x1="365.0" y1="102.6" x2="578.0" y2="102.6" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="2 3"/>
<line x1="374.0" y1="250.1" x2="374.0" y2="263.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="369.5" y="253.0" width="9" height="5.8" fill="#188a3e"/>
<line x1="389.0" y1="250.1" x2="389.0" y2="260.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="384.5" y="253.0" width="9" height="4.7" fill="#c00"/>
<line x1="404.0" y1="244.3" x2="404.0" y2="260.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="399.5" y="247.2" width="9" height="10.5" fill="#188a3e"/>
<line x1="419.0" y1="234.9" x2="419.0" y2="250.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="414.5" y="237.8" width="9" height="9.3" fill="#188a3e"/>
<line x1="434.0" y1="225.6" x2="434.0" y2="240.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="429.5" y="228.5" width="9" height="9.3" fill="#188a3e"/>
<line x1="449.0" y1="218.6" x2="449.0" y2="231.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="444.5" y="221.5" width="9" height="7.0" fill="#188a3e"/>
<line x1="464.0" y1="209.9" x2="464.0" y2="224.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="459.5" y="214.5" width="9" height="7.0" fill="#188a3e"/>
<line x1="479.0" y1="211.0" x2="479.0" y2="235.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="474.5" y="214.5" width="9" height="17.5" fill="#c00"/>
<line x1="494.0" y1="228.5" x2="494.0" y2="242.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="489.5" y="232.0" width="9" height="7.0" fill="#c00"/>
<line x1="509.0" y1="229.7" x2="509.0" y2="241.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="504.5" y="233.2" width="9" height="5.8" fill="#188a3e"/>
<line x1="524.0" y1="167.9" x2="524.0" y2="236.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="519.5" y="172.5" width="9" height="60.6" fill="#188a3e"/>
<line x1="539.0" y1="152.1" x2="539.0" y2="177.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="534.5" y="156.2" width="9" height="16.3" fill="#188a3e"/>
<line x1="554.0" y1="123.0" x2="554.0" y2="160.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="549.5" y="127.1" width="9" height="29.1" fill="#188a3e"/>
<line x1="569.0" y1="96.2" x2="569.0" y2="131.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="564.5" y="100.3" width="9" height="26.8" fill="#188a3e"/>
<path d="M580.0,102.6 H585.0 L582.0,102.6" fill="none" stroke="#188a3e" stroke-width="0.8" stroke-opacity="0.8"/>
<text x="586.0" y="106.6" fill="#188a3e" style="font-size:10px">TP1 598.00</text>
<path d="M580.0,172.5 H585.0 L582.0,172.5" fill="none" stroke="#188a3e" stroke-width="0.8" stroke-opacity="0.8"/>
<text x="586.0" y="176.5" fill="#188a3e" style="font-size:10px">intrare 592.00</text>
<path d="M580.0,242.5 H585.0 L582.0,242.5" fill="none" stroke="#c00" stroke-width="0.8" stroke-opacity="0.8"/>
<text x="586.0" y="246.5" fill="#c00" style="font-size:10px">stop 586.00</text>
<text x="586.0" y="259.5" fill="#c00" style="font-size:10px">minimul ultimelor</text>
<text x="586.0" y="272.5" fill="#c00" style="font-size:10px">4 bare de 60 min</text>
<path d="M580.0,265.8 H585.0 L582.0,283.5" fill="none" stroke="#666" stroke-width="0.8" stroke-opacity="0.8"/>
<text x="586.0" y="287.5" fill="#666" style="font-size:10px">pivot weekly</text>
<text x="586.0" y="300.5" fill="#666" style="font-size:10px">(mare) 584.00</text>
<path d="M549.5,172.5 H544.5 V242.5 H549.5" fill="none" stroke="#c00" stroke-width="1.6"/>
<text x="553.5" y="211.5" fill="#c00" style="font-size:11px;font-weight:bold">stop 1,01 %</text>
<line x1="34.0" y1="338.0" x2="544.5" y2="338.0" stroke="#c00" stroke-width="1.6" marker-end="url(#pt)"/>
<text x="289.2" y="355.0" fill="#c00" text-anchor="middle" style="font-size:11px;font-weight:bold">același setup, stop de 3,0 ori mai mic</text>
<text x="289.2" y="369.0" fill="#c00" text-anchor="middle" style="font-size:11px;font-weight:bold">→ de 3,0 ori mai multe acțiuni la același risc în bani</text>
<text x="20.0" y="390.0" fill="#555" style="font-size:11px">Pe daily ai fi intrat la close-ul zilei (598.20) cu stopul sub minimul ultimelor 4 zile (580.00).</text>
<text x="20.0" y="404.0" fill="#555" style="font-size:11px">Pe 60 de minute vezi unde s-a oprit coborârea, deci ai de unde măsura un stop mult mai strâns.</text>
</svg>

After

Width:  |  Height:  |  Size: 9.3 KiB

View File

@@ -0,0 +1,79 @@
"""MP² — cei doi pivoți și condiția M (Pasul 2 din `02_mp2.md`).
Aceeași serie ca tot capitolul. Aici nu e niciun trade: doar cele două linii
de pivot și granița dintre „nu ai voie long" și „ai voie să cauți trigger".
Dedesubt, aritmetica: pivotul mic al zilei 4 iese din OHLC-ul zilei 3, cu
formula cursului. Cifrele nu sunt scrise de mână — ies din serie.
Rulare: python3 gen/strategii/mp2_pivoti.py
"""
import re
import sys
from pathlib import Path
sys.path.insert(0, "/workspace/atm-curs-dl")
sys.path.insert(0, str(Path(__file__).parent))
from svg_candles import Chart, Level, Zone # noqa: E402
import mp2_serie as S # noqa: E402
OUT = Path(__file__).with_suffix(".svg")
RED, BLUE, GRAY, GREEN = "#c00", "#1a5fb4", "#777", "#188a3e"
W = 720
zi = S.zilnice(S.CDS)
z3 = zi[S.ZI4 - 1] # ziua 3, cea din care iese pivotul zilei 4
assert S.pp(z3.h, z3.l, z3.c) == S.PPD[S.ZI4]
assert S.pp(*S.PPW_OHLC) == S.PPW
hot = S.ZI4 * S.BARE_ZI # prima bară a zilei 4
ch = Chart(
candles=S.CDS,
levels=[Level(S.PPW, f"pivot weekly (mare) {S.PPW:.2f} — nu se mișcă toată săptămâna",
GRAY, "8 4", "right")],
zones=[Zone(0, hot - 1, "pivotul mic e SUB cel mare: M neîndeplinit, nu cauți long", RED),
Zone(hot, len(S.CDS) - 1, "pivotul mic e PESTE cel mare: M îndeplinit", GREEN)],
scale=15.0, gap=15, body_w=9, left=52, width=W, top=40,
title="Pasul 2 — cei doi pivoți: unde stă cel mic față de cel mare")
svg = ch.render()
off = S.offset(svg, ch)
inject = [
f'<polyline points="{S.trepte(ch, S.PPD_BARA, off)}" fill="none" stroke="{BLUE}" '
f'stroke-width="1.8"/>',
]
# doar cele două valori care contează: ultima de sub pivotul mare și prima de peste
for d, dy_, b in ((S.ZI4 - 1, 14, 3), (S.ZI4, -7, 6)):
inject.append(
f'<text x="{ch._cx(d * S.BARE_ZI + b):.1f}" y="{ch._y(S.PPD[d]) + off + dy_:.1f}" '
f'fill="{BLUE}" text-anchor="middle" style="font-weight:bold">{S.PPD[d]:.2f}</text>')
svg = S.injecteaza(svg, inject)
# --- aritmetica, sub grafic ---------------------------------------------------
h = float(re.search(r'viewBox="0 0 [\d.]+ ([\d.]+)"', svg).group(1))
linii = [
("Linia albastră în trepte e pivotul daily (mic), recalculat în fiecare ședință; "
"linia gri e pivotul weekly (mare).", "#333"),
("Pivotul mare, al săptămânii încheiate: PP = (High + Low + Close) / 3 = "
f"({S.PPW_OHLC[0]:.2f} + {S.PPW_OHLC[1]:.2f} + {S.PPW_OHLC[2]:.2f}) / 3 = "
f"{S.PPW:.2f}", GRAY),
("Pivotul mic al zilei a 4-a, din ziua a 3-a încheiată: "
f"({z3.h:.2f} + {z3.l:.2f} + {z3.c:.2f}) / 3 = {S.PPD[S.ZI4]:.2f}", BLUE),
(f"{S.PPD[S.ZI4]:.2f} este peste {S.PPW:.2f}, iar în ziua a 3-a era "
f"{S.PPD[S.ZI4 - 1]:.2f}, adică dedesubt: M îndeplinit, printr-un crossing proaspăt.",
GREEN),
]
blocs = [f'<text x="24" y="{h + 6 + 19 * i:.1f}" fill="{c}"'
f'{" style=\'font-weight:bold\'" if i == 3 else ""}>{t}</text>'
for i, (t, c) in enumerate(linii)]
H = h + 6 + 19 * len(linii)
svg = svg.replace(f'viewBox="0 0 {W} {h:.0f}"', f'viewBox="0 0 {W} {H:.0f}"', 1)
if f'viewBox="0 0 {W} {H:.0f}"' not in svg: # lățimea a fost lărgită
vb = re.search(r'viewBox="0 0 ([\d.]+) ([\d.]+)"', svg)
svg = svg.replace(vb.group(0), f'viewBox="0 0 {vb.group(1)} {H:.0f}"', 1)
svg = svg.replace("</svg>", " " + "\n ".join(blocs) + "\n</svg>")
w = float(re.search(r'viewBox="0 0 ([\d.]+)', svg).group(1))
assert max(len(t) for t, _ in linii) * 5.7 + 24 < w, "linia de aritmetică iese din pânză"
S.scrie(OUT, svg, w, H)

View File

@@ -0,0 +1,86 @@
<svg viewBox="0 0 720 524" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif">
<polyline points="52.0,353.7 67.0,353.7 82.0,353.7 97.0,353.7 112.0,353.7 127.0,353.7 142.0,353.7 157.0,353.7 157.0,365.7 172.0,365.7 187.0,365.7 202.0,365.7 217.0,365.7 232.0,365.7 247.0,365.7 262.0,365.7 262.0,353.7 277.0,353.7 292.0,353.7 307.0,353.7 322.0,353.7 337.0,353.7 352.0,353.7 367.0,353.7 367.0,294.8 382.0,294.8 397.0,294.8 412.0,294.8 427.0,294.8 442.0,294.8 457.0,294.8 472.0,294.8 472.0,187.9 487.0,187.9 502.0,187.9 517.0,187.9 532.0,187.9 547.0,187.9 562.0,187.9" fill="none" stroke="#1a5fb4" stroke-width="1.8"/>
<text x="307.0" y="367.7" fill="#1a5fb4" text-anchor="middle" style="font-weight:bold">583.20</text>
<text x="457.0" y="287.8" fill="#1a5fb4" text-anchor="middle" style="font-weight:bold">587.13</text>
<text x="24" y="54" fill="#333" style="font-weight:bold">Pasul 2 — cei doi pivoți: unde stă cel mic față de cel mare</text>
<rect x="42.5" y="261.8" width="319.0" height="148.0" fill="#c00" fill-opacity="0.08" stroke="#c00" stroke-width="1"/>
<text x="42.5" y="256.8" fill="#c00" style="font-weight:bold">pivotul mic e SUB cel mare: M neîndeplinit, nu cauți long</text>
<rect x="357.5" y="54.0" width="214.0" height="265.7" fill="#188a3e" fill-opacity="0.08" stroke="#188a3e" stroke-width="1"/>
<text x="357.5" y="49.0" fill="#188a3e" style="font-weight:bold">pivotul mic e PESTE cel mare: M îndeplinit</text>
<line x1="24" y1="341.7" x2="706" y2="341.7" stroke="#777" stroke-width="1.5" stroke-dasharray="8 4"/>
<text x="692" y="335.7" fill="#777" text-anchor="end">pivot weekly (mare) 584.00 — nu se mișcă toată săptămâna</text>
<line x1="52.0" y1="320.8" x2="52.0" y2="342.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="47.5" y="326.7" width="9" height="12.0" fill="#c00"/>
<line x1="67.0" y1="335.0" x2="67.0" y2="354.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="62.5" y="338.7" width="9" height="12.0" fill="#c00"/>
<line x1="82.0" y1="339.5" x2="82.0" y2="354.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="77.5" y="343.2" width="9" height="7.5" fill="#188a3e"/>
<line x1="97.0" y1="339.5" x2="97.0" y2="366.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="92.5" y="343.2" width="9" height="19.5" fill="#c00"/>
<line x1="112.0" y1="359.0" x2="112.0" y2="378.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="107.5" y="362.7" width="9" height="12.0" fill="#c00"/>
<line x1="127.0" y1="365.0" x2="127.0" y2="378.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="122.5" y="368.7" width="9" height="6.0" fill="#188a3e"/>
<line x1="142.0" y1="365.0" x2="142.0" y2="392.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="137.5" y="368.7" width="9" height="15.0" fill="#c00"/>
<line x1="157.0" y1="380.0" x2="157.0" y2="401.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="152.5" y="383.7" width="9" height="9.0" fill="#c00"/>
<line x1="172.0" y1="377.0" x2="172.0" y2="396.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="167.5" y="380.8" width="9" height="12.0" fill="#188a3e"/>
<line x1="187.0" y1="377.0" x2="187.0" y2="392.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="182.5" y="380.8" width="9" height="7.5" fill="#c00"/>
<line x1="202.0" y1="363.5" x2="202.0" y2="392.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="197.5" y="367.3" width="9" height="21.0" fill="#188a3e"/>
<line x1="217.0" y1="351.5" x2="217.0" y2="371.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="212.5" y="355.2" width="9" height="12.0" fill="#188a3e"/>
<line x1="232.0" y1="341.0" x2="232.0" y2="359.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="227.5" y="344.8" width="9" height="10.5" fill="#188a3e"/>
<line x1="247.0" y1="326.7" x2="247.0" y2="348.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="242.5" y="332.7" width="9" height="12.0" fill="#188a3e"/>
<line x1="262.0" y1="321.5" x2="262.0" y2="338.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="257.5" y="325.2" width="9" height="7.5" fill="#188a3e"/>
<line x1="277.0" y1="321.5" x2="277.0" y2="335.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="272.5" y="325.2" width="9" height="6.0" fill="#c00"/>
<line x1="292.0" y1="314.0" x2="292.0" y2="335.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="287.5" y="317.7" width="9" height="13.5" fill="#188a3e"/>
<line x1="307.0" y1="302.0" x2="307.0" y2="321.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="302.5" y="305.8" width="9" height="12.0" fill="#188a3e"/>
<line x1="322.0" y1="290.0" x2="322.0" y2="309.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="317.5" y="293.7" width="9" height="12.0" fill="#188a3e"/>
<line x1="337.0" y1="281.0" x2="337.0" y2="297.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="332.5" y="284.8" width="9" height="9.0" fill="#188a3e"/>
<line x1="352.0" y1="269.8" x2="352.0" y2="288.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="347.5" y="275.8" width="9" height="9.0" fill="#188a3e"/>
<line x1="367.0" y1="271.3" x2="367.0" y2="302.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="362.5" y="275.8" width="9" height="22.5" fill="#c00"/>
<line x1="382.0" y1="293.8" x2="382.0" y2="311.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="377.5" y="298.2" width="9" height="9.0" fill="#c00"/>
<line x1="397.0" y1="295.3" x2="397.0" y2="310.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="392.5" y="299.8" width="9" height="7.5" fill="#188a3e"/>
<line x1="412.0" y1="215.8" x2="412.0" y2="304.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="407.5" y="221.7" width="9" height="78.0" fill="#188a3e"/>
<line x1="427.0" y1="195.5" x2="427.0" y2="227.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="422.5" y="200.8" width="9" height="21.0" fill="#188a3e"/>
<line x1="442.0" y1="158.0" x2="442.0" y2="206.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="437.5" y="163.2" width="9" height="37.5" fill="#188a3e"/>
<line x1="457.0" y1="123.5" x2="457.0" y2="169.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="452.5" y="128.7" width="9" height="34.5" fill="#188a3e"/>
<line x1="472.0" y1="102.5" x2="472.0" y2="134.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="467.5" y="107.7" width="9" height="21.0" fill="#188a3e"/>
<line x1="487.0" y1="78.5" x2="487.0" y2="113.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="482.5" y="83.7" width="9" height="24.0" fill="#188a3e"/>
<line x1="502.0" y1="78.5" x2="502.0" y2="101.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="497.5" y="83.7" width="9" height="12.0" fill="#c00"/>
<line x1="517.0" y1="62.0" x2="517.0" y2="101.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="512.5" y="67.3" width="9" height="28.5" fill="#188a3e"/>
<line x1="532.0" y1="62.0" x2="532.0" y2="90.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="527.5" y="67.3" width="9" height="18.0" fill="#c00"/>
<line x1="547.0" y1="80.0" x2="547.0" y2="110.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="542.5" y="85.2" width="9" height="19.5" fill="#c00"/>
<line x1="562.0" y1="99.5" x2="562.0" y2="123.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="557.5" y="104.8" width="9" height="13.5" fill="#c00"/>
<text x="24" y="448.0" fill="#333">Linia albastră în trepte e pivotul daily (mic), recalculat în fiecare ședință; linia gri e pivotul weekly (mare).</text>
<text x="24" y="467.0" fill="#777">Pivotul mare, al săptămânii încheiate: PP = (High + Low + Close) / 3 = (588.00 + 580.00 + 584.00) / 3 = 584.00</text>
<text x="24" y="486.0" fill="#1a5fb4">Pivotul mic al zilei a 4-a, din ziua a 3-a încheiată: (588.80 + 584.20 + 588.40) / 3 = 587.13</text>
<text x="24" y="505.0" fill="#188a3e" style='font-weight:bold'>587.13 este peste 584.00, iar în ziua a 3-a era 583.20, adică dedesubt: M îndeplinit, printr-un crossing proaspăt.</text>
</svg>

After

Width:  |  Height:  |  Size: 7.7 KiB

View File

@@ -195,14 +195,11 @@ def build():
13, "400", GRAY))
p.append(txt(W / 2, 358, "nu sunt date reale de piață.", 13, "400", GRAY))
p.append(txt(W / 2, 386,
"crossing = PPD trece deasupra PPW; dacă rămâne deasupra — "
"continuare (09_QA/16:35-43).", 13, "400", BLACK))
"crossing = PPD trece deasupra PPW; dacă rămâne deasupra, "
"e continuare, nu crossing.", 13, "400", BLACK))
p.append(txt(W / 2, 408,
"Surse formule: 03_MODUL_2/02_zone_cerere_oferta_support_"
"resistance.md:42-50", 13, "400", GRAY))
p.append(txt(W / 2, 426,
"Calcul Excel 1-la-1, MP² = comparația a doi pivoți: "
"09_QA/09_2025-12-09.md:1176-1180.", 13, "400", GRAY))
"Formula pivotului e cea predată în Modul 2; autorul a confirmat "
"că se calculează 1 la 1 în Excel.", 13, "400", GRAY))
p.append('</g></svg>')
return "\n".join(p) + "\n"
@@ -299,7 +296,7 @@ def verify(svg):
"22.13", "21.23", "22.47", "20.67",
"PPD 21.57 > PPW 21.37", "CROSSING BULL (long)",
"exemplu construit", "nu sunt date reale de piață",
"09_QA/16:35-43", "09_QA/09_2025-12-09.md:1176-1180",
"e continuare, nu crossing", "se calculează 1 la 1 în Excel",
):
assert cheie in plain, f"lipsește din desen: {cheie!r}"

View File

@@ -75,7 +75,6 @@
<text x="350.0" y="296.0" font-size="16" font-weight="700" fill="#000000" text-anchor="middle">PPD 21.57 &gt; PPW 21.37 → CROSSING BULL (long)</text>
<text x="350.0" y="340.0" font-size="13" font-weight="400" fill="#777777" text-anchor="middle">Cifrele sunt un exemplu construit, cu valori rotunde, pe TLV —</text>
<text x="350.0" y="358.0" font-size="13" font-weight="400" fill="#777777" text-anchor="middle">nu sunt date reale de piață.</text>
<text x="350.0" y="386.0" font-size="13" font-weight="400" fill="#000000" text-anchor="middle">crossing = PPD trece deasupra PPW; dacă rămâne deasupra — continuare (09_QA/16:35-43).</text>
<text x="350.0" y="408.0" font-size="13" font-weight="400" fill="#777777" text-anchor="middle">Surse formule: 03_MODUL_2/02_zone_cerere_oferta_support_resistance.md:42-50</text>
<text x="350.0" y="426.0" font-size="13" font-weight="400" fill="#777777" text-anchor="middle">Calcul Excel 1-la-1, MP² = comparația a doi pivoți: 09_QA/09_2025-12-09.md:1176-1180.</text>
<text x="350.0" y="386.0" font-size="13" font-weight="400" fill="#000000" text-anchor="middle">crossing = PPD trece deasupra PPW; dacă rămâne deasupra, e continuare, nu crossing.</text>
<text x="350.0" y="408.0" font-size="13" font-weight="400" fill="#777777" text-anchor="middle">Formula pivotului e cea predată în Modul 2; autorul a confirmat că se calculează 1 la 1 în Excel.</text>
</g></svg>

Before

Width:  |  Height:  |  Size: 8.6 KiB

After

Width:  |  Height:  |  Size: 8.4 KiB

268
gen/strategii/mp2_serie.py Normal file
View File

@@ -0,0 +1,268 @@
"""Seria comună a capitolului `17_STRATEGII/02_mp2.md` — un singur trade.
Toate diagramele din Nivelul 1 și Nivelul 2 ale capitolului desenează ACELAȘI
trade, din aceeași serie. Așa nu se poate întâmpla ca două diagrame să
folosească două reguli de stop diferite, fiecare etichetată corect local.
Ce e din material și ce e construit
-----------------------------------
Din material (rezumatul Q&A, exemplul ilustrativ al mecanicii celor două
poziții): intrare 592.00, SL 586.00, 1R = 6.00, TP1 598.00, mutarea SL-ului
la break-even la 60 % din drum, mărimea totală multiplu de 2.
Construit de mine: traseul barelor de 60 de minute care produce exact
cifrele alea, și pivoții — care NU sunt scriși de mână, ci calculați din
serie cu formula cursului, PP = (High + Low + Close) / 3 al perioadei
încheiate. Fără ticker: e un exemplu construit, nu date reale de piață.
Structura: 5 zile × 7 bare de 60 de minute (ședința 9:30-16:00 are 6 ore și
jumătate, deci ultima bară a zilei e de 30 de minute).
ziua 1 bare 0-6 coborâre
ziua 2 bare 7-13 minimul și întoarcerea
ziua 3 bare 14-20 ziua verde care ridică pivotul zilnic peste cel weekly
ziua 4 bare 21-27 crossing-ul e pe tablă: dip, trigger la 592.00, TP1
ziua 5 bare 28-34 poziția 2 pe trail, ieșire la 599.80
Rulat direct, verifică toate afirmațiile capitolului:
python3 gen/strategii/mp2_serie.py
"""
import re
import sys
sys.path.insert(0, "/workspace/atm-curs-dl")
from svg_candles import Candle, from_closes # noqa: E402
BARE_ZI = 7 # bare de 60 min într-o ședință
ZILE = 5
# pivotul săptămânal (MARE): al săptămânii încheiate, H 588.00 / L 580.00 /
# C 584.00. E un dat din afara ferestrei desenate — săptămâna trecută nu
# încape pe grafic — deci îl declar aici, cu OHLC-ul din care iese.
PPW_OHLC = (588.00, 580.00, 584.00)
# pivotul zilnic al PRIMEI zile: al ședinței de vineri, dinaintea ferestrei.
PPD0_OHLC = (586.00, 581.00, 582.60)
START = 585.00 # open-ul primei bare
CLOSES = [
# ziua 1 — coborâre
584.20, 583.40, 583.90, 582.60, 581.80, 582.20, 581.20,
# ziua 2 — minimul (580.00) și întoarcerea
580.60, 581.40, 580.90, 582.30, 583.10, 583.80, 584.60,
# ziua 3 — ziua verde; închiderile ei sunt peste pivotul zilnic, dar
# pivotul zilnic e încă sub cel weekly, deci NU e trigger
585.10, 584.70, 585.60, 586.40, 587.20, 587.80, 588.40,
# ziua 4 — dip sub pivotul zilnic nou, apoi trigger-ul
586.90, 586.30, 586.80, 592.00, 593.40, 595.90, 598.20,
# ziua 5 — poziția 2 pe trail
599.60, 601.20, 600.40, 602.30, 601.10, 599.80, 598.90,
]
W = [(0.25, 0.25)] * 35 # fitile (sus, jos); excepțiile fixează extremele zilei
W[0] = (0.40, 0.25) # H zi 1 = 585.40
W[6] = (0.25, 0.60) # L zi 1 = 580.60
W[7] = (0.25, 0.60) # L zi 2 = 580.00
W[13] = (0.40, 0.25) # H zi 2 = 585.00
W[14] = (0.25, 0.40) # L zi 3 = 584.20
W[20] = (0.40, 0.25) # H zi 3 = 588.80
W[21] = (0.30, 0.30)
W[22] = (0.30, 0.30) # L = 586.00 — minimul celor 4 bare de la trigger
W[23] = (0.30, 0.20)
W[24] = (0.40, 0.30) # bara de trigger
W[25] = (0.35, 0.40)
W[26] = (0.35, 0.40)
W[27] = (0.35, 0.40)
for i in range(28, 35):
W[i] = (0.35, 0.35)
VOLS = [46, 40, 38, 42, 39, 36, 44,
58, 52, 44, 41, 38, 36, 40,
44, 38, 41, 45, 48, 44, 52,
50, 46, 42, 118, 86, 78, 82,
64, 58, 46, 62, 44, 56, 48]
ZI3, ZI4 = 2, 3 # indexul zilei verzi și al zilei de trigger
TRIGGER = 24 # bara de trigger (ziua 4, a 4-a oră)
PREA_DEVREME = 16 # închidere peste pivotul mic cu M neîndeplinit
NU_INCHIDE = 22 # trece peste pivot în timpul barei, dar nu închide
BARE_STOP = 4 # stopul: extrema ultimelor 4 bare, de la trigger
PRAG_BE = 0.60 # la 60 % din drumul spre TP1, SL-ul merge la BE
PRAG_90 = 0.90
def pp(h, l, c):
"""Pivotul clasic al unei perioade încheiate (formula cursului)."""
return round((h + l + c) / 3, 2)
def serie(closes=None, wicks=None, start=None):
return from_closes(closes or CLOSES, wicks=wicks or W, vols=VOLS,
start=START if start is None else start)
def zilnice(cds):
"""Agregă barele de 60 min în candele zilnice: 7 bare = o ședință."""
out = []
for d in range(ZILE):
p = cds[d * BARE_ZI:(d + 1) * BARE_ZI]
out.append(Candle(p[0].o, max(c.h for c in p), min(c.l for c in p), p[-1].c))
return out
def pivoti(cds, ppw_ohlc=PPW_OHLC, ppd0_ohlc=PPD0_OHLC):
"""(PPW, PPD pe zi, PPD pe bară). PPD al zilei N = pivotul zilei N-1."""
zi = zilnice(cds)
ppw = pp(*ppw_ohlc)
ppd = [pp(*ppd0_ohlc)] + [pp(z.h, z.l, z.c) for z in zi[:-1]]
return ppw, ppd, [ppd[i // BARE_ZI] for i in range(len(cds))]
def trail(cds, de_la):
"""Bull trail: low-ul fiecărei bare care face un maxim nou, de la `de_la`.
Întoarce (linia pe bară, indexul barei de ieșire) — ieșirea e prima
închidere sub linie, nu primul fitil sub ea.
"""
linie, nivel, hmax, iesire = [], None, cds[de_la].h, None
for i, c in enumerate(cds):
if i >= de_la:
if c.h >= hmax:
hmax, nivel = c.h, c.l
if iesire is None and nivel is not None and i > de_la and c.c < nivel:
iesire = i
linie.append(nivel)
return linie, iesire
def oglinda(a=246.40, f=0.2):
"""Aceeași structură, întoarsă: p' = a - f*p. Transformarea e afină, deci
agregarea zilnică și pivoții se păstrează; short-ul nu e „e invers", are
desenul lui complet. Cu f = 0.2 toate prețurile rămân exacte la 2 zecimale."""
m = lambda p: round(a - f * p, 2) # noqa: E731
cds = [Candle(m(c.o), m(c.l), m(c.h), m(c.c), vol=c.vol) for c in serie()]
ppw = m(pp(*PPW_OHLC))
zi = zilnice(cds)
ppd = [m(pp(*PPD0_OHLC))] + [pp(z.l, z.h, z.c) for z in zi[:-1]]
return cds, ppw, ppd, [ppd[i // BARE_ZI] for i in range(len(cds))]
# ---------------------------------------------------------------- cifrele
CDS = serie()
PPW, PPD, PPD_BARA = pivoti(CDS)
ENTRY = CDS[TRIGGER].c
SL = min(c.l for c in CDS[TRIGGER - BARE_STOP + 1:TRIGGER + 1])
R = round(ENTRY - SL, 2)
TP1 = round(ENTRY + R, 2)
BE = round(ENTRY + PRAG_BE * R, 2)
P90 = round(ENTRY + PRAG_90 * R, 2)
SWING_LOW = min(c.l for c in CDS) # varianta de bottom major
TRAIL, IESIRE = trail(CDS, TRIGGER)
IES_PRET = CDS[IESIRE].c
I_TP1 = next(i for i in range(TRIGGER + 1, len(CDS)) if CDS[i].h >= TP1)
I_BE = next(i for i in range(TRIGGER + 1, len(CDS)) if CDS[i].h >= BE)
# mărimea poziției: regula de risc a cursului (0,5 % pe prop), contul e al meu
CONT, RISC_PCT = 50_000, 0.005
BUCATI = int(CONT * RISC_PCT / R) // 2 * 2 # multiplu de 2: două ordine egale
RISC_REAL = round(BUCATI * R, 2)
def _verifica():
for i, c in enumerate(CDS):
assert c.l <= min(c.o, c.c) and c.h >= max(c.o, c.c), f"bara {i}: h/l nu cuprind o/c"
if i:
assert abs(c.o - CDS[i - 1].c) < 1e-9, f"bara {i}: open != close precedent"
assert len(CDS) == BARE_ZI * ZILE == 35
# 1. cifrele din material ies din serie, nu sunt scrise de mână
assert (ENTRY, SL, R, TP1) == (592.00, 586.00, 6.00, 598.00), (ENTRY, SL, R, TP1)
assert BE == 595.60 and P90 == 597.40
# 2. M: pivotul mic e sub cel mare până în ziua 4, și peste din ziua 4
assert all(PPD[d] < PPW for d in range(ZI4)), PPD
assert PPD[ZI4] > PPW, (PPD[ZI4], PPW)
assert PPD[ZI4] - PPW > 2.5, "crossing-ul e prea strâns ca să se vadă pe desen"
# 3. crossing PROASPĂT, nu continuare: în ziua dinainte era de partea cealaltă
assert PPD[ZI4 - 1] < PPW < PPD[ZI4]
assert PPD[ZI4 + 1] > PPW, "ziua 5 e continuare (+1), nu crossing"
# 4. trigger-ul: PRIMA închidere peste pivotul mic din ziua în care M e îndeplinit
zi4 = range(ZI4 * BARE_ZI, (ZI4 + 1) * BARE_ZI)
assert TRIGGER == next(i for i in zi4 if CDS[i].c > PPD_BARA[i]), "nu e prima închidere"
assert CDS[TRIGGER].c > CDS[TRIGGER].o, "bara de trigger nu e verde"
# 5. NU — prea devreme: închidere peste pivotul mic cu M neîndeplinit
assert CDS[PREA_DEVREME].c > PPD_BARA[PREA_DEVREME] > 0
assert PPD_BARA[PREA_DEVREME] < PPW, "în ziua 3 M ar fi îndeplinit"
assert CDS[PREA_DEVREME].c > CDS[PREA_DEVREME].o, "bara „prea devreme” nu e verde"
# 6. NU — trece peste pivot în timpul barei, dar nu închide peste
assert CDS[NU_INCHIDE].h > PPD_BARA[NU_INCHIDE] > CDS[NU_INCHIDE].c
# 7. stopul: minimul celor 4 bare, și e minimul lor strict
assert SL == CDS[22].l and SL < min(CDS[i].l for i in (21, 23, 24))
assert SWING_LOW < SL, "varianta de bottom major ar coincide cu stopul de 4 bare"
assert round(SL - SWING_LOW, 2) == 6.00, round(SL - SWING_LOW, 2)
# 8. ieșirile, în ordine: BE, TP1, apoi trail-ul
assert I_BE == 26 and I_TP1 == 27 and IESIRE == 33, (I_BE, I_TP1, IESIRE)
assert CDS[IESIRE].c < TRAIL[IESIRE] and all(
CDS[i].c >= TRAIL[i] for i in range(TRIGGER + 1, IESIRE)), "ieșire greșită pe trail"
assert round((IES_PRET - ENTRY) / R, 2) == 1.30, (IES_PRET - ENTRY) / R
# 9. mărimea poziției
assert BUCATI == 40 and RISC_REAL == 240.00 and RISC_REAL <= CONT * RISC_PCT
# 10. oglinda păstrează structura
o_cds, o_ppw, o_ppd, _ = oglinda()
assert all(o_ppd[d] > o_ppw for d in range(ZI4)) and o_ppd[ZI4] < o_ppw
o_entry = o_cds[TRIGGER].c
o_sl = max(c.h for c in o_cds[TRIGGER - BARE_STOP + 1:TRIGGER + 1])
assert (o_entry, o_sl) == (128.00, 129.20), (o_entry, o_sl)
assert round(o_sl - o_entry, 2) == 1.20
_verifica()
# -------------------------------------------------- ajutoare pentru desen
def offset(svg, ch):
"""Câți px a coborât `render()` graficul față de ce întoarce acum ch._y().
`render()` mută `top` ca să facă loc titlului/săgeților și îl restaurează
la final, deci ch._y() de după randare e deplasat. Citim deplasarea din
prima linie de Level desenată, ca ce injectăm pe urmă să cadă exact peste
candele (bug real: liniile de pivot cu 22 px mai sus decât candelele).
"""
y = float(re.search(r'<line x1="24" y1="([\d.]+)"', svg).group(1))
return y - ch._y(ch.levels[0].price)
def trepte(ch, valori, off):
"""Polilinie în trepte pentru un pivot care se recalculează periodic."""
pts = []
for i, v in enumerate(valori):
if v is None:
continue
x, y = ch._cx(i), ch._y(v) + off
if pts and v != valori[i - 1]:
pts.append((x, ch._y(valori[i - 1]) + off))
pts.append((x, y))
return " ".join(f"{x:.1f},{y:.1f}" for x, y in pts)
def injecteaza(svg, bucati):
"""Pune `bucati` imediat după tag-ul de deschidere: desenate în spate."""
i = svg.index(">") + 1
return svg[:i] + "\n " + "\n ".join(bucati) + svg[i:]
def scrie(out, svg, w, h):
assert "\n\n" not in svg, "linie goală în SVG rupe blocul din markdown"
assert ".md:" not in svg, "trimitere fișier:linie în SVG"
for x, y in re.findall(r'<text x="([-\d.]+)" y="([-\d.]+)"', svg):
assert -1 <= float(x) <= w + 1 and 0 <= float(y) <= h + 1, f"text în afara pânzei ({x}, {y})"
out.write_text(svg, encoding="utf-8")
print(f"scris {out.name} ({w}x{h:.0f})")
if __name__ == "__main__":
print(f"PPW (mare) = {PPW:.2f} PPD (mic), pe zile = {PPD}")
print(f"crossing în ziua {ZI4 + 1}: {PPD[ZI4 - 1]:.2f} -> {PPD[ZI4]:.2f}, peste {PPW:.2f}")
print(f"trigger bara {TRIGGER}: close {ENTRY:.2f} peste pivotul mic {PPD[ZI4]:.2f}")
print(f"SL {SL:.2f} (minimul barelor {TRIGGER - 3}-{TRIGGER}), 1R = {R:.2f} "
f"({R / ENTRY * 100:.2f} %), TP1 {TP1:.2f} la bara {I_TP1}")
print(f"BE {BE:.2f} la bara {I_BE}; trail: ieșire la bara {IESIRE}, "
f"{IES_PRET:.2f} = {(IES_PRET - ENTRY) / R:.2f}R")
print(f"swing low absolut {SWING_LOW:.2f} (varianta de bottom major)")
print(f"mărime: {BUCATI} bucăți (2 x {BUCATI // 2}), risc real {RISC_REAL:.2f} $")
print("toate verificările trec")

View File

@@ -0,0 +1,87 @@
"""MP² pe short — aceeași procedură, întoarsă (oglinda din `02_mp2.md`).
Alt simbol, altă scară de preț (în jur de 128 $, nu 590 $): structura e
aceeași serie, întoarsă cu p' = 246.40 − 0.2·p. Transformarea e afină și
descrescătoare, deci agregarea zilnică, pivoții și linia de trail se
păstrează exact — bull trail-ul devine bear trail fără să recalculez nimic.
Ce se schimbă față de long:
M pivotul mic e SUB cel mare, nu peste;
crossing pivotul mic coboară prin cel mare;
trigger prima bară care ÎNCHIDE sub pivotul mic;
stopul cel mai SUS high din ultimele 4 bare;
ținta la aceeași distanță, în jos.
Rulare: python3 gen/strategii/mp2_short.py
"""
import re
import sys
from pathlib import Path
sys.path.insert(0, "/workspace/atm-curs-dl")
sys.path.insert(0, str(Path(__file__).parent))
from svg_candles import Arrow, Chart, Level, Zone # noqa: E402
import mp2_serie as S # noqa: E402
OUT = Path(__file__).with_suffix(".svg")
A, F = 246.40, 0.2
RED, BLUE, GRAY, GREEN, ORANGE = "#c00", "#1a5fb4", "#777", "#188a3e", "#b06000"
W = 720
def m(p):
return round(A - F * p, 2)
cds, ppw, ppd, ppd_bara = S.oglinda(A, F)
entry = cds[S.TRIGGER].c
sl = max(c.h for c in cds[S.TRIGGER - S.BARE_STOP + 1:S.TRIGGER + 1])
r = round(sl - entry, 2)
tp1 = round(entry - r, 2)
trail = [None if v is None or i < S.I_TP1 else m(v) for i, v in enumerate(S.TRAIL)]
ies = cds[S.IESIRE].c
zi4a = S.ZI4 * S.BARE_ZI
# tot ce scriu pe desen iese din serie
assert (entry, sl, tp1, r) == (128.00, 129.20, 126.80, 1.20), (entry, sl, tp1, r)
assert all(ppd[d] > ppw for d in range(S.ZI4)) and ppd[S.ZI4] < ppw, ppd
assert cds[S.TRIGGER].c < ppd_bara[S.TRIGGER] and cds[S.TRIGGER].c < cds[S.TRIGGER].o
assert S.TRIGGER == next(i for i in range(zi4a, zi4a + S.BARE_ZI)
if cds[i].c < ppd_bara[i]), "nu e prima închidere sub pivotul mic"
assert cds[S.IESIRE].c > trail[S.IESIRE] and min(c.l for c in cds[S.TRIGGER:S.I_TP1 + 1]) <= tp1
assert round((entry - ies) / r, 2) == 1.30
ch = Chart(
candles=cds,
levels=[Level(ppw, f"pivot weekly (mare) {ppw:.2f}", GRAY, "8 4", "right"),
Level(sl, f"stopul {sl:.2f}", RED, "6 3", "right"),
Level(entry, f"intrarea (short) {entry:.2f}", "#333", "4 3", "right"),
Level(tp1, f"TP1 {tp1:.2f} = intrarea − 1R", GREEN, "2 3", "left")],
zones=[Zone(zi4a, len(cds) - 1, "pivotul mic e deja SUB cel mare", BLUE)],
arrows=[
Arrow(S.TRIGGER, f"aici intri short: {entry:.2f}\nprima bară care ÎNCHIDE "
f"sub pivotul mic",
where="below", color=RED, dx=-108, dy=26),
Arrow(S.I_TP1, f"poziția 1 iese la {tp1:.2f} (1:1)", where="right", price=tp1,
color=GREEN, dx=78, dy=30),
Arrow(S.IESIRE, f"poziția 2 iese la {ies:.2f},\nprima închidere peste trail",
where="right", color=ORANGE, dy=-34),
],
scale=55.0, gap=15, body_w=9, left=52, width=W, top=40,
title="Oglinda — Sell / short: alt simbol, altă scară, aceleași reguli",
caption="Albastru în trepte = pivotul daily (mic); portocaliu = bear trail, "
"high-ul ultimei bare cu minim nou.")
svg = ch.render()
off = S.offset(svg, ch)
svg = S.injecteaza(svg, [
f'<polyline points="{S.trepte(ch, ppd_bara, off)}" fill="none" stroke="{BLUE}" '
f'stroke-width="1.8"/>',
f'<polyline points="{S.trepte(ch, trail, off)}" fill="none" stroke="{ORANGE}" '
f'stroke-width="1.8"/>',
f'<text x="{ch._cx(zi4a + 6):.1f}" y="{ch._y(ppd[S.ZI4]) + off + 15:.1f}" fill="{BLUE}" '
f'text-anchor="middle" style="font-weight:bold">{ppd[S.ZI4]:.2f}: crossing bear</text>',
])
h = float(re.search(r'viewBox="0 0 [\d.]+ ([\d.]+)"', svg).group(1))
w = float(re.search(r'viewBox="0 0 ([\d.]+)', svg).group(1))
S.scrie(OUT, svg, w, h)

View File

@@ -0,0 +1,98 @@
<svg viewBox="0 0 771 367" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif">
<polyline points="52.0,97.2 67.0,97.2 82.0,97.2 97.0,97.2 112.0,97.2 127.0,97.2 142.0,97.2 157.0,97.2 157.0,88.4 172.0,88.4 187.0,88.4 202.0,88.4 217.0,88.4 232.0,88.4 247.0,88.4 262.0,88.4 262.0,97.2 277.0,97.2 292.0,97.2 307.0,97.2 322.0,97.2 337.0,97.2 352.0,97.2 367.0,97.2 367.0,140.6 382.0,140.6 397.0,140.6 412.0,140.6 427.0,140.6 442.0,140.6 457.0,140.6 472.0,140.6 472.0,218.7 487.0,218.7 502.0,218.7 517.0,218.7 532.0,218.7 547.0,218.7 562.0,218.7" fill="none" stroke="#1a5fb4" stroke-width="1.8"/>
<polyline points="457.0,232.5 472.0,232.5 472.0,258.3 487.0,258.3 487.0,273.7 502.0,273.7 502.0,282.5 517.0,282.5 532.0,282.5 532.0,290.2 547.0,290.2 562.0,290.2" fill="none" stroke="#b06000" stroke-width="1.8"/>
<text x="457.0" y="155.6" fill="#1a5fb4" text-anchor="middle" style="font-weight:bold">128.97: crossing bear</text>
<text x="24" y="54" fill="#333" style="font-weight:bold">Oglinda — Sell / short: alt simbol, altă scară, aceleași reguli</text>
<rect x="357.5" y="120.0" width="214.0" height="199.1" fill="#1a5fb4" fill-opacity="0.08" stroke="#1a5fb4" stroke-width="1"/>
<text x="357.5" y="115.0" fill="#1a5fb4" style="font-weight:bold">pivotul mic e deja SUB cel mare</text>
<line x1="24" y1="106.0" x2="757" y2="106.0" stroke="#777" stroke-width="1.5" stroke-dasharray="8 4"/>
<text x="743" y="100.0" fill="#777" text-anchor="end">pivot weekly (mare) 129.60</text>
<line x1="24" y1="128.0" x2="757" y2="128.0" stroke="#c00" stroke-width="1.5" stroke-dasharray="6 3"/>
<text x="743" y="122.0" fill="#c00" text-anchor="end">stopul 129.20</text>
<line x1="24" y1="194.0" x2="757" y2="194.0" stroke="#333" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="743" y="188.0" fill="#333" text-anchor="end">intrarea (short) 128.00</text>
<line x1="24" y1="260.0" x2="757" y2="260.0" stroke="#188a3e" stroke-width="1.5" stroke-dasharray="2 3"/>
<text x="30" y="254.0" fill="#188a3e">TP1 126.80 = intrarea − 1R</text>
<line x1="52.0" y1="105.4" x2="52.0" y2="121.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="47.5" y="108.2" width="9" height="8.8" fill="#188a3e"/>
<line x1="67.0" y1="96.6" x2="67.0" y2="111.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="62.5" y="99.4" width="9" height="8.8" fill="#188a3e"/>
<line x1="82.0" y1="96.6" x2="82.0" y2="107.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="77.5" y="99.4" width="9" height="5.5" fill="#c00"/>
<line x1="97.0" y1="87.8" x2="97.0" y2="107.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="92.5" y="90.6" width="9" height="14.3" fill="#188a3e"/>
<line x1="112.0" y1="79.1" x2="112.0" y2="93.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="107.5" y="81.8" width="9" height="8.8" fill="#188a3e"/>
<line x1="127.0" y1="79.1" x2="127.0" y2="89.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="122.5" y="81.8" width="9" height="4.4" fill="#c00"/>
<line x1="142.0" y1="68.6" x2="142.0" y2="89.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="137.5" y="75.2" width="9" height="11.0" fill="#188a3e"/>
<line x1="157.0" y1="62.0" x2="157.0" y2="77.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="152.5" y="68.6" width="9" height="6.6" fill="#188a3e"/>
<line x1="172.0" y1="65.8" x2="172.0" y2="80.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="167.5" y="68.6" width="9" height="8.8" fill="#c00"/>
<line x1="187.0" y1="69.1" x2="187.0" y2="80.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="182.5" y="71.9" width="9" height="5.5" fill="#188a3e"/>
<line x1="202.0" y1="69.1" x2="202.0" y2="90.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="197.5" y="71.9" width="9" height="15.4" fill="#c00"/>
<line x1="217.0" y1="84.5" x2="217.0" y2="98.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="212.5" y="87.3" width="9" height="8.8" fill="#c00"/>
<line x1="232.0" y1="93.3" x2="232.0" y2="106.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="227.5" y="96.1" width="9" height="7.7" fill="#c00"/>
<line x1="247.0" y1="101.1" x2="247.0" y2="117.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="242.5" y="103.8" width="9" height="8.8" fill="#c00"/>
<line x1="262.0" y1="108.2" x2="262.0" y2="120.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="257.5" y="112.6" width="9" height="5.5" fill="#c00"/>
<line x1="277.0" y1="111.0" x2="277.0" y2="120.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="272.5" y="113.7" width="9" height="4.4" fill="#188a3e"/>
<line x1="292.0" y1="111.0" x2="292.0" y2="126.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="287.5" y="113.7" width="9" height="9.9" fill="#c00"/>
<line x1="307.0" y1="120.8" x2="307.0" y2="135.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="302.5" y="123.6" width="9" height="8.8" fill="#c00"/>
<line x1="322.0" y1="129.7" x2="322.0" y2="144.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="317.5" y="132.4" width="9" height="8.8" fill="#c00"/>
<line x1="337.0" y1="138.5" x2="337.0" y2="150.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="332.5" y="141.2" width="9" height="6.6" fill="#c00"/>
<line x1="352.0" y1="145.1" x2="352.0" y2="158.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="347.5" y="147.8" width="9" height="6.6" fill="#c00"/>
<line x1="367.0" y1="134.6" x2="367.0" y2="157.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="362.5" y="137.9" width="9" height="16.5" fill="#188a3e"/>
<line x1="382.0" y1="128.0" x2="382.0" y2="141.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="377.5" y="131.3" width="9" height="6.6" fill="#188a3e"/>
<line x1="397.0" y1="129.1" x2="397.0" y2="140.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="392.5" y="131.3" width="9" height="5.5" fill="#c00"/>
<line x1="412.0" y1="133.5" x2="412.0" y2="198.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="407.5" y="136.8" width="9" height="57.2" fill="#c00"/>
<line x1="427.0" y1="189.6" x2="427.0" y2="213.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="422.5" y="194.0" width="9" height="15.4" fill="#c00"/>
<line x1="442.0" y1="205.0" x2="442.0" y2="240.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="437.5" y="209.4" width="9" height="27.5" fill="#c00"/>
<line x1="457.0" y1="232.5" x2="457.0" y2="266.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="452.5" y="236.9" width="9" height="25.3" fill="#c00"/>
<line x1="472.0" y1="258.4" x2="472.0" y2="281.5" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="467.5" y="262.2" width="9" height="15.4" fill="#c00"/>
<line x1="487.0" y1="273.8" x2="487.0" y2="299.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="482.5" y="277.6" width="9" height="17.6" fill="#c00"/>
<line x1="502.0" y1="282.6" x2="502.0" y2="299.1" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="497.5" y="286.4" width="9" height="8.8" fill="#188a3e"/>
<line x1="517.0" y1="282.6" x2="517.0" y2="311.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="512.5" y="286.4" width="9" height="20.9" fill="#c00"/>
<line x1="532.0" y1="290.3" x2="532.0" y2="311.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="527.5" y="294.1" width="9" height="13.2" fill="#188a3e"/>
<line x1="547.0" y1="276.0" x2="547.0" y2="298.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="542.5" y="279.8" width="9" height="14.3" fill="#188a3e"/>
<line x1="562.0" y1="266.1" x2="562.0" y2="283.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="557.5" y="269.9" width="9" height="9.9" fill="#188a3e"/>
<line x1="304.0" y1="254.4" x2="404.8" y2="205.9" stroke="#c00" stroke-width="1.8"/>
<polygon points="412.0,202.4 406.5,209.5 403.1,202.3" fill="#c00"/>
<text x="304.0" y="268.4" fill="#c00" text-anchor="middle" style="font-weight:bold">aici intri short: 128.00</text>
<text x="304.0" y="282.4" fill="#c00" text-anchor="middle" style="font-weight:bold">prima bară care ÎNCHIDE sub pivotul mic</text>
<line x1="573.5" y1="290.0" x2="473.2" y2="262.1" stroke="#188a3e" stroke-width="1.8"/>
<polygon points="465.5,260.0 474.3,258.3 472.1,266.0" fill="#188a3e"/>
<text x="577.5" y="294.0" fill="#188a3e" text-anchor="start" style="font-weight:bold">poziția 1 iese la 126.80 (1:1)</text>
<line x1="585.5" y1="245.8" x2="560.8" y2="273.8" stroke="#b06000" stroke-width="1.8"/>
<polygon points="555.5,279.8 557.8,271.2 563.8,276.4" fill="#b06000"/>
<text x="589.5" y="242.8" fill="#b06000" text-anchor="start" style="font-weight:bold">poziția 2 iese la 126.44,</text>
<text x="589.5" y="256.8" fill="#b06000" text-anchor="start" style="font-weight:bold">prima închidere peste trail</text>
<text x="24" y="355" fill="#555">Albastru în trepte = pivotul daily (mic); portocaliu = bear trail, high-ul ultimei bare cu minim nou.</text>
</svg>

After

Width:  |  Height:  |  Size: 8.6 KiB

74
gen/strategii/mp2_stop.py Normal file
View File

@@ -0,0 +1,74 @@
"""MP² — stopul și mărimea poziției (Pasul 5 din `02_mp2.md`).
Aceeași serie. Numeri 4 bare înapoi, începând cu bara de trigger, iei cea
mai joasă dintre ele și acolo stă stopul. Pe desen mai apare și varianta de
la bottom major: swing low-ul absolut al mișcării, mult mai jos — regula
alternativă a cursului, nu o a doua regulă pentru trade-ul obișnuit.
Rulare: python3 gen/strategii/mp2_stop.py
"""
import re
import sys
from pathlib import Path
sys.path.insert(0, "/workspace/atm-curs-dl")
sys.path.insert(0, str(Path(__file__).parent))
from svg_candles import Arrow, Chart, Level, Zone # noqa: E402
import mp2_serie as S # noqa: E402
OUT = Path(__file__).with_suffix(".svg")
RED, BLUE, GRAY, GREEN, ORANGE = "#c00", "#1a5fb4", "#777", "#188a3e", "#b06000"
W, B = 720, 30
cds = S.CDS[:B + 1]
i_low = min(range(len(cds)), key=lambda i: cds[i].l)
R_MARE = round(S.ENTRY - S.SWING_LOW, 2)
assert i_low == 7 and cds[i_low].l == S.SWING_LOW
assert S.SL == min(c.l for c in cds[S.TRIGGER - 3:S.TRIGGER + 1])
assert R_MARE == 12.00 and R_MARE == 2 * S.R
ch = Chart(
candles=cds,
levels=[Level(S.ENTRY, f"intrarea {S.ENTRY:.2f}", "#333", "4 3", "right"),
Level(S.SL, f"stopul din regulă {S.SL:.2f} — 1R = {S.R:.2f}", RED, "6 3", "left"),
Level(S.SWING_LOW, f"swing low absolut {S.SWING_LOW:.2f}", ORANGE, "2 4", "right")],
zones=[Zone(S.TRIGGER - S.BARE_STOP + 1, S.TRIGGER,
f"cele {S.BARE_STOP} bare pe care le numeri", BLUE)],
arrows=[
Arrow(22, f"cea mai joasă dintre cele {S.BARE_STOP}: {S.SL:.2f}\nacolo pui stopul, "
f"nu mai jos și nu mai aproape",
where="below", price=S.SL, color=RED, dx=-120, dy=6),
Arrow(i_low, f"minimul întregii mișcări: {S.SWING_LOW:.2f}\nasta folosești DOAR la un "
f"bottom major,\ncând retesturile dese te-ar scoate degeaba — 1R devine {R_MARE:.2f}",
where="below", price=S.SWING_LOW, color=ORANGE, dx=180, dy=48),
Arrow(S.TRIGGER, f"bara de trigger: {S.ENTRY:.2f}\nde aici numeri înapoi",
where="above", color=GREEN, dx=-96, dy=-4),
],
scale=14.0, gap=20, body_w=11, left=56, width=W, top=40,
title="Pasul 5 — numeri 4 bare înapoi de la trigger și iei cea mai joasă")
svg = ch.render()
off = S.offset(svg, ch)
y_num = ch._y(S.SL) + off + 20
nums = [f'<text x="{ch._cx(S.TRIGGER - k):.1f}" y="{y_num:.1f}" fill="{BLUE}" '
f'text-anchor="middle" style="font-weight:bold">{k + 1}</text>' for k in range(S.BARE_STOP)]
svg = S.injecteaza(svg, nums)
h = float(re.search(r'viewBox="0 0 [\d.]+ ([\d.]+)"', svg).group(1))
w = float(re.search(r'viewBox="0 0 ([\d.]+)', svg).group(1))
linii = [
("Mărimea poziției: riscul în bani se împarte la distanța până la stop.", "#333"),
(f"Cont {S.CONT:,.0f} $".replace(",", ".") +
f" × {S.RISC_PCT * 100:.1f} % = {S.CONT * S.RISC_PCT:.0f} $ de risc; "
f"{S.CONT * S.RISC_PCT:.0f} / {S.R:.2f} = {S.CONT * S.RISC_PCT / S.R:.1f} bucăți → "
f"{S.BUCATI} bucăți, adică două ordine de câte {S.BUCATI // 2}.", BLUE),
(f"Risc real: {S.BUCATI} × {S.R:.2f} = {S.RISC_REAL:.0f} $, adică "
f"{S.RISC_REAL / S.CONT * 100:.2f} % din cont — sub pragul de "
f"{S.RISC_PCT * 100:.1f} %.", GREEN),
]
blocs = [f'<text x="24" y="{h + 6 + 19 * i:.1f}" fill="{c}">{t}</text>' for i, (t, c) in enumerate(linii)]
H = h + 6 + 19 * len(linii)
svg = re.sub(r'viewBox="0 0 ([\d.]+) [\d.]+"', rf'viewBox="0 0 \1 {H:.0f}"', svg, count=1)
svg = svg.replace("</svg>", " " + "\n ".join(blocs) + "\n</svg>")
assert max(len(t) for t, _ in linii) * 5.7 + 24 < w, "linia de calcul iese din pânză"
S.scrie(OUT, svg, w, H)

View File

@@ -0,0 +1,93 @@
<svg viewBox="0 0 720 582" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif">
<text x="536.0" y="299.7" fill="#1a5fb4" text-anchor="middle" style="font-weight:bold">1</text>
<text x="516.0" y="299.7" fill="#1a5fb4" text-anchor="middle" style="font-weight:bold">2</text>
<text x="496.0" y="299.7" fill="#1a5fb4" text-anchor="middle" style="font-weight:bold">3</text>
<text x="476.0" y="299.7" fill="#1a5fb4" text-anchor="middle" style="font-weight:bold">4</text>
<text x="24" y="54" fill="#333" style="font-weight:bold">Pasul 5 — numeri 4 bare înapoi de la trigger și iei cea mai joasă</text>
<rect x="465.5" y="182.1" width="81.0" height="105.6" fill="#1a5fb4" fill-opacity="0.08" stroke="#1a5fb4" stroke-width="1"/>
<text x="465.5" y="53.0" fill="#1a5fb4" style="font-weight:bold">cele 4 bare pe care le numeri</text>
<line x1="24" y1="195.7" x2="706" y2="195.7" stroke="#333" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="692" y="189.7" fill="#333" text-anchor="end">intrarea 592.00</text>
<line x1="24" y1="279.7" x2="706" y2="279.7" stroke="#c00" stroke-width="1.5" stroke-dasharray="6 3"/>
<text x="30" y="273.7" fill="#c00">stopul din regulă 586.00 — 1R = 6.00</text>
<line x1="24" y1="363.7" x2="706" y2="363.7" stroke="#b06000" stroke-width="1.5" stroke-dasharray="2 4"/>
<text x="692" y="357.7" fill="#b06000" text-anchor="end">swing low absolut 580.00</text>
<line x1="56.0" y1="288.1" x2="56.0" y2="308.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="50.5" y="293.7" width="11" height="11.2" fill="#c00"/>
<line x1="76.0" y1="301.4" x2="76.0" y2="319.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="70.5" y="304.9" width="11" height="11.2" fill="#c00"/>
<line x1="96.0" y1="305.6" x2="96.0" y2="319.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="90.5" y="309.1" width="11" height="7.0" fill="#188a3e"/>
<line x1="116.0" y1="305.6" x2="116.0" y2="330.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="110.5" y="309.1" width="11" height="18.2" fill="#c00"/>
<line x1="136.0" y1="323.8" x2="136.0" y2="342.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="130.5" y="327.3" width="11" height="11.2" fill="#c00"/>
<line x1="156.0" y1="329.4" x2="156.0" y2="342.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="150.5" y="332.9" width="11" height="5.6" fill="#188a3e"/>
<line x1="176.0" y1="329.4" x2="176.0" y2="355.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="170.5" y="332.9" width="11" height="14.0" fill="#c00"/>
<line x1="196.0" y1="343.4" x2="196.0" y2="363.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="190.5" y="346.9" width="11" height="8.4" fill="#c00"/>
<line x1="216.0" y1="340.6" x2="216.0" y2="358.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="210.5" y="344.1" width="11" height="11.2" fill="#188a3e"/>
<line x1="236.0" y1="340.6" x2="236.0" y2="354.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="230.5" y="344.1" width="11" height="7.0" fill="#c00"/>
<line x1="256.0" y1="328.0" x2="256.0" y2="354.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="250.5" y="331.5" width="11" height="19.6" fill="#188a3e"/>
<line x1="276.0" y1="316.8" x2="276.0" y2="335.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="270.5" y="320.3" width="11" height="11.2" fill="#188a3e"/>
<line x1="296.0" y1="307.0" x2="296.0" y2="323.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="290.5" y="310.5" width="11" height="9.8" fill="#188a3e"/>
<line x1="316.0" y1="293.7" x2="316.0" y2="314.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="310.5" y="299.3" width="11" height="11.2" fill="#188a3e"/>
<line x1="336.0" y1="288.8" x2="336.0" y2="304.9" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="330.5" y="292.3" width="11" height="7.0" fill="#188a3e"/>
<line x1="356.0" y1="288.8" x2="356.0" y2="301.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="350.5" y="292.3" width="11" height="5.6" fill="#c00"/>
<line x1="376.0" y1="281.8" x2="376.0" y2="301.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="370.5" y="285.3" width="11" height="12.6" fill="#188a3e"/>
<line x1="396.0" y1="270.6" x2="396.0" y2="288.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="390.5" y="274.1" width="11" height="11.2" fill="#188a3e"/>
<line x1="416.0" y1="259.4" x2="416.0" y2="277.6" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="410.5" y="262.9" width="11" height="11.2" fill="#188a3e"/>
<line x1="436.0" y1="251.0" x2="436.0" y2="266.4" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="430.5" y="254.5" width="11" height="8.4" fill="#188a3e"/>
<line x1="456.0" y1="240.5" x2="456.0" y2="258.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="450.5" y="246.1" width="11" height="8.4" fill="#188a3e"/>
<line x1="476.0" y1="241.9" x2="476.0" y2="271.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="470.5" y="246.1" width="11" height="21.0" fill="#c00"/>
<line x1="496.0" y1="262.9" x2="496.0" y2="279.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="490.5" y="267.1" width="11" height="8.4" fill="#c00"/>
<line x1="516.0" y1="264.3" x2="516.0" y2="278.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="510.5" y="268.5" width="11" height="7.0" fill="#188a3e"/>
<line x1="536.0" y1="190.1" x2="536.0" y2="272.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="530.5" y="195.7" width="11" height="72.8" fill="#188a3e"/>
<line x1="556.0" y1="171.2" x2="556.0" y2="201.3" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="550.5" y="176.1" width="11" height="19.6" fill="#188a3e"/>
<line x1="576.0" y1="136.2" x2="576.0" y2="181.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="570.5" y="141.1" width="11" height="35.0" fill="#188a3e"/>
<line x1="596.0" y1="104.0" x2="596.0" y2="146.7" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="590.5" y="108.9" width="11" height="32.2" fill="#188a3e"/>
<line x1="616.0" y1="84.4" x2="616.0" y2="113.8" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="610.5" y="89.3" width="11" height="19.6" fill="#188a3e"/>
<line x1="636.0" y1="62.0" x2="636.0" y2="94.2" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="630.5" y="66.9" width="11" height="22.4" fill="#188a3e"/>
<line x1="656.0" y1="62.0" x2="656.0" y2="83.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="650.5" y="66.9" width="11" height="11.2" fill="#c00"/>
<line x1="376.0" y1="368.6" x2="489.5" y2="288.3" stroke="#c00" stroke-width="1.8"/>
<polygon points="496.0,283.7 491.8,291.6 487.2,285.1" fill="#c00"/>
<text x="376.0" y="382.6" fill="#c00" text-anchor="middle" style="font-weight:bold">cea mai joasă dintre cele 4: 586.00</text>
<text x="376.0" y="396.6" fill="#c00" text-anchor="middle" style="font-weight:bold">acolo pui stopul, nu mai jos și nu mai aproape</text>
<line x1="376.0" y1="441.7" x2="203.4" y2="370.7" stroke="#b06000" stroke-width="1.8"/>
<polygon points="196.0,367.7 204.9,367.0 201.9,374.4" fill="#b06000"/>
<text x="376.0" y="455.7" fill="#b06000" text-anchor="middle" style="font-weight:bold">minimul întregii mișcări: 580.00</text>
<text x="376.0" y="469.7" fill="#b06000" text-anchor="middle" style="font-weight:bold">asta folosești DOAR la un bottom major,</text>
<text x="376.0" y="483.7" fill="#b06000" text-anchor="middle" style="font-weight:bold">când retesturile dese te-ar scoate degeaba — 1R devine 12.00</text>
<line x1="440.0" y1="156.1" x2="528.4" y2="183.7" stroke="#188a3e" stroke-width="1.8"/>
<polygon points="536.0,186.1 527.2,187.5 529.6,179.9" fill="#188a3e"/>
<text x="440.0" y="137.1" fill="#188a3e" text-anchor="middle" style="font-weight:bold">bara de trigger: 592.00</text>
<text x="440.0" y="151.1" fill="#188a3e" text-anchor="middle" style="font-weight:bold">de aici numeri înapoi</text>
<text x="24" y="525.0" fill="#333">Mărimea poziției: riscul în bani se împarte la distanța până la stop.</text>
<text x="24" y="544.0" fill="#1a5fb4">Cont 50.000 $ × 0.5 % = 250 $ de risc; 250 / 6.00 = 41.7 bucăți → 40 bucăți, adică două ordine de câte 20.</text>
<text x="24" y="563.0" fill="#188a3e">Risc real: 40 × 6.00 = 240 $, adică 0.48 % din cont — sub pragul de 0.5 %.</text>
</svg>

After

Width:  |  Height:  |  Size: 8.0 KiB

View File

@@ -0,0 +1,67 @@
"""MP² — trigger valid și trigger fals (Pasul 4 din `02_mp2.md`).
Lupa pe ultimele două ședințe ale seriei comune: trei bare care seamănă și
care nu înseamnă același lucru.
NU — prea devreme: închidere verde peste pivotul mic, dar pivotul mic e
încă sub cel mare (M neîndeplinit).
NU — n-a închis: bara trece peste pivotul mic în timpul ei, dar se
închide sub el. Contează închiderea, nu atingerea.
DA: prima închidere peste pivotul mic după ce pivotul mic
a trecut peste cel mare.
Rulare: python3 gen/strategii/mp2_trigger.py
"""
import sys
from pathlib import Path
sys.path.insert(0, "/workspace/atm-curs-dl")
sys.path.insert(0, str(Path(__file__).parent))
from svg_candles import Arrow, Chart, Level # noqa: E402
import mp2_serie as S # noqa: E402
OUT = Path(__file__).with_suffix(".svg")
RED, BLUE, GRAY, GREEN, ORANGE = "#c00", "#1a5fb4", "#777", "#188a3e", "#b06000"
W, A, B = 720, 14, 27 # fereastra desenată: barele A..B
cds = S.CDS[A:B + 1]
ppd = S.PPD_BARA[A:B + 1]
d_devreme, d_nu, d_da = S.PREA_DEVREME - A, S.NU_INCHIDE - A, S.TRIGGER - A
# ce afirmă fiecare etichetă, verificat pe serie
assert cds[d_devreme].c > ppd[d_devreme] and ppd[d_devreme] < S.PPW
assert cds[d_nu].h > ppd[d_nu] > cds[d_nu].c and ppd[d_nu] > S.PPW
assert cds[d_da].c > ppd[d_da] > S.PPW
assert all(cds[i].c <= ppd[i] for i in range(d_nu - 1, d_da)), "ar fi existat un trigger mai devreme"
ch = Chart(
candles=cds,
levels=[Level(S.PPW, f"pivot weekly (mare) {S.PPW:.2f}", GRAY, "8 4", "right")],
arrows=[
Arrow(d_devreme, "NU — prea devreme\nînchide peste pivotul mic, dar pivotul\n"
f"mic ({ppd[d_devreme]:.2f}) e încă SUB cel mare ({S.PPW:.2f})",
where="below", color=RED, dx=8, dy=48),
Arrow(d_nu, "NU — n-a închis peste\n"
f"urcă peste {ppd[d_nu]:.2f} în timpul barei,\n"
f"dar se închide la {cds[d_nu].c:.2f}, sub el",
where="below", color=ORANGE, dx=150, dy=110),
Arrow(d_da, f"DA — trigger\nprima ÎNCHIDERE ({cds[d_da].c:.2f}) peste pivotul\n"
f"mic {ppd[d_da]:.2f}, cu pivotul mic peste cel mare",
where="above", color=GREEN, dx=-118, dy=-6),
],
scale=20.0, gap=32, body_w=15, left=58, width=W, top=40,
title="Pasul 4 — aceeași linie de pivot, trei bare, un singur trigger",
caption="Contează închiderea barei, nu cât de sus a urcat în timpul ei.")
svg = ch.render()
off = S.offset(svg, ch)
svg = S.injecteaza(svg, [
f'<polyline points="{S.trepte(ch, ppd, off)}" fill="none" stroke="{BLUE}" stroke-width="1.8"/>',
f'<text x="{ch._cx(d_da + 2):.1f}" y="{ch._y(ppd[-1]) + off + 15:.1f}" fill="{BLUE}" '
f'text-anchor="middle" style="font-weight:bold">pivot daily (mic) {ppd[-1]:.2f}</text>',
f'<text x="{ch._cx(1):.1f}" y="{ch._y(ppd[0]) + off + 15:.1f}" fill="{BLUE}" '
f'style="font-weight:bold">pivot daily (mic) {ppd[0]:.2f}</text>',
])
w = float(svg.split('viewBox="0 0 ')[1].split()[0])
h = float(svg.split('viewBox="0 0 ')[1].split('"')[0].split()[1])
S.scrie(OUT, svg, w, h)

View File

@@ -0,0 +1,52 @@
<svg viewBox="0 0 723 546" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:auto;font:12px sans-serif">
<polyline points="58.0,369.0 90.0,369.0 122.0,369.0 154.0,369.0 186.0,369.0 218.0,369.0 250.0,369.0 282.0,369.0 282.0,290.4 314.0,290.4 346.0,290.4 378.0,290.4 410.0,290.4 442.0,290.4 474.0,290.4" fill="none" stroke="#1a5fb4" stroke-width="1.8"/>
<text x="442.0" y="305.4" fill="#1a5fb4" text-anchor="middle" style="font-weight:bold">pivot daily (mic) 587.13</text>
<text x="90.0" y="384.0" fill="#1a5fb4" style="font-weight:bold">pivot daily (mic) 583.20</text>
<text x="24" y="54" fill="#333" style="font-weight:bold">Pasul 4 — aceeași linie de pivot, trei bare, un singur trigger</text>
<line x1="24" y1="353.0" x2="709" y2="353.0" stroke="#777" stroke-width="1.5" stroke-dasharray="8 4"/>
<text x="695" y="347.0" fill="#777" text-anchor="end">pivot weekly (mare) 584.00</text>
<line x1="61.1" y1="326.0" x2="61.1" y2="349.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="53.6" y="331.0" width="15" height="10.0" fill="#188a3e"/>
<line x1="93.1" y1="326.0" x2="93.1" y2="344.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="85.6" y="331.0" width="15" height="8.0" fill="#c00"/>
<line x1="125.1" y1="316.0" x2="125.1" y2="344.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="117.6" y="321.0" width="15" height="18.0" fill="#188a3e"/>
<line x1="157.1" y1="300.0" x2="157.1" y2="326.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="149.6" y="305.0" width="15" height="16.0" fill="#188a3e"/>
<line x1="189.1" y1="284.0" x2="189.1" y2="310.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="181.6" y="289.0" width="15" height="16.0" fill="#188a3e"/>
<line x1="221.1" y1="272.0" x2="221.1" y2="294.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="213.6" y="277.0" width="15" height="12.0" fill="#188a3e"/>
<line x1="253.1" y1="257.0" x2="253.1" y2="282.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="245.6" y="265.0" width="15" height="12.0" fill="#188a3e"/>
<line x1="285.1" y1="259.0" x2="285.1" y2="301.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="277.6" y="265.0" width="15" height="30.0" fill="#c00"/>
<line x1="317.1" y1="289.0" x2="317.1" y2="313.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="309.6" y="295.0" width="15" height="12.0" fill="#c00"/>
<line x1="349.1" y1="291.0" x2="349.1" y2="311.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="341.6" y="297.0" width="15" height="10.0" fill="#188a3e"/>
<line x1="381.1" y1="185.0" x2="381.1" y2="303.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="373.6" y="193.0" width="15" height="104.0" fill="#188a3e"/>
<line x1="413.1" y1="158.0" x2="413.1" y2="201.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="405.6" y="165.0" width="15" height="28.0" fill="#188a3e"/>
<line x1="445.1" y1="108.0" x2="445.1" y2="173.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="437.6" y="115.0" width="15" height="50.0" fill="#188a3e"/>
<line x1="477.1" y1="62.0" x2="477.1" y2="123.0" stroke="#1a1a1a" stroke-width="1.2"/>
<rect x="469.6" y="69.0" width="15" height="46.0" fill="#188a3e"/>
<line x1="133.1" y1="422.0" x2="126.0" y2="356.0" stroke="#c00" stroke-width="1.8"/>
<polygon points="125.1,348.0 129.9,355.5 122.0,356.4" fill="#c00"/>
<text x="133.1" y="436.0" fill="#c00" text-anchor="middle" style="font-weight:bold">NU — prea devreme</text>
<text x="133.1" y="450.0" fill="#c00" text-anchor="middle" style="font-weight:bold">închide peste pivotul mic, dar pivotul</text>
<text x="133.1" y="464.0" fill="#c00" text-anchor="middle" style="font-weight:bold">mic (583.20) e încă SUB cel mare (584.00)</text>
<line x1="467.1" y1="453.0" x2="323.0" y2="322.4" stroke="#b06000" stroke-width="1.8"/>
<polygon points="317.1,317.0 325.7,319.4 320.3,325.3" fill="#b06000"/>
<text x="467.1" y="467.0" fill="#b06000" text-anchor="middle" style="font-weight:bold">NU — n-a închis peste</text>
<text x="467.1" y="481.0" fill="#b06000" text-anchor="middle" style="font-weight:bold">urcă peste 587.13 în timpul barei,</text>
<text x="467.1" y="495.0" fill="#b06000" text-anchor="middle" style="font-weight:bold">dar se închide la 586.30, sub el</text>
<line x1="263.1" y1="149.0" x2="373.4" y2="178.9" stroke="#188a3e" stroke-width="1.8"/>
<polygon points="381.1,181.0 372.3,182.8 374.4,175.0" fill="#188a3e"/>
<text x="263.1" y="116.0" fill="#188a3e" text-anchor="middle" style="font-weight:bold">DA — trigger</text>
<text x="263.1" y="130.0" fill="#188a3e" text-anchor="middle" style="font-weight:bold">prima ÎNCHIDERE (592.00) peste pivotul</text>
<text x="263.1" y="144.0" fill="#188a3e" text-anchor="middle" style="font-weight:bold">mic 587.13, cu pivotul mic peste cel mare</text>
<text x="24" y="534" fill="#555">Contează închiderea barei, nu cât de sus a urcat în timpul ei.</text>
</svg>

After

Width:  |  Height:  |  Size: 4.8 KiB

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,77 @@
# Surse — 2. MP² (pivoți dubli)
Trimiterile la material pentru [`02_mp2.md`](../02_mp2.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**. Diagramele de la Nivelul 1 și Nivelul 2
sunt un exemplu construit, fără ticker: traseul e desenat ca cifrele din
material (intrare 592.00, stop 586.00, 1R = 6.00, TP1 598.00) să iasă din
serie, iar pivoții se calculează din ea. Exemplele cu ticker (SPY, NVDA) au
cifrele din curs.
**Prescurtări:**
`mp2` = [`04_strategia_2_mp_patrat.md`](../../04_MODUL_3/04_strategia_2_mp_patrat.md)
(fișierul principal al strategiei) ·
`m2d` = [`14_strategia_1_m2d.md`](../../03_MODUL_2/14_strategia_1_m2d.md)
(bull/bear trail, money management) ·
`zone` = [`02_zone_cerere_oferta_support_resistance.md`](../../03_MODUL_2/02_zone_cerere_oferta_support_resistance.md)
(formula pivotului) ·
`bim` = [`10_buysell_momentum_trigger.md`](../../03_MODUL_2/10_buysell_momentum_trigger.md)
(indicatorul de buy/sell momentum) ·
`mbt10` = [`02_mbt10.md`](../../08_ANALIZA_ZILNICA/02_mbt10.md) (MP4-1) ·
`selectia` = [`11_selectia_simbolului.md`](../../08_ANALIZA_ZILNICA/11_selectia_simbolului.md)
(scaner, ReVol) ·
fișierele datate sunt sesiuni Q&A din [`../../09_QA/`](../../09_QA/).
**Nivelul 1** — `mp2`: 4-14, 24-31, 35-36, 49-53 · `01_2026-08-25`: 15-19,
50-56 · `16_2025-10-07`: 35-43 · `06_2026-04-28`: 14-21.
**Pasul 1 (perechea de TF, lichiditatea)** — `mp2`: 24-31 ·
`09_2025-12-09`: 19-48, 436-448 · `10_2025-12-02`: 759, 761-762, 793 ·
`18_2025-09-23`: 78 · `selectia`: 18-20.
**Pasul 2 (cei doi pivoți, M)** — `mp2`: 35-36 · `zone`: 42-54 ·
`01_2026-08-25`: 15-19, 45-48 · `09_2025-12-09`: 1177-1180.
**Pasul 3 (crossing, nu buy the dip)** — `mp2`: 11-14 · `09_2025-12-09`:
56-67, 85-98, 107-129, 151-155 · `10_2025-12-02`: 719-730 ·
`16_2025-10-07`: 15-43 · `06_2026-04-28`: 14-16 · `25_2025-07-08`: 167-178.
**Pasul 4 (trigger)** — `mp2`: 38-40, 97-103, 288-296, 327-337 · `bim`:
4-9, 29-30 · `10_2025-12-02`: 750-753 · `26_2025-06-11`: 841 ·
`01_2026-08-25`: 272-275.
**Pasul 5 (stopul, mărimea)** — `mp2`: 42-48, 52-54, 105-116, 180-188,
293-294, 626-627 · `m2d`: 57-58, 66-68, 150-154 · `01_2026-08-25`: 381-394,
492 · `23_2025-07-29`: 563-564, 1666-1667 · `24_2025-07-15`: 463-466.
**Pasul 6 (ieșirea)** — `mp2`: 49-53, 278-286, 317-325 · `m2d`: 150-159 ·
`01_2026-08-25`: 60-73, 75-146, 148-151 · `14_2025-10-21`: 264-280 ·
`09_2025-12-09`: 993-1006.
**Oglinda (short)** — `mp2`: 288-296 · `01_2026-08-25`: 15-19, 45-48.
**A+ și ce dă edge** — `mp2`: 11-14, 622-625, 630-633 · `09_2025-12-09`:
85-98, 180-206 · `10_2025-12-02`: 728-730 · `16_2025-10-07`: 15-43, 83-106,
161-172 · `01_2026-08-25`: 272-275, 372-394, 501-507 · `23_2025-07-29`:
1666-1668 · `06_2026-04-28`: 14-21 · `selectia`: 756-770.
**Exemplul SPY** — `01_2026-08-25`: 372-394, 485-494, 501-507.
**Bottom major (NVDA)** — `mp2`: 180-188, 326-335, 341-357, 435, 626-627 ·
`23_2025-07-29`: 1666-1668.
**Transfer (prop, BVB)** — `mp2`: 26, 30-31, 630-633 · `09_2025-12-09`:
436-448, 1177-1186 · `10_2025-12-02`: 793 · `18_2025-09-23`: 78 ·
`26_2025-06-11`: 214-222 · `zone`: 42-54 · `selectia`: 5-9.
**Contradicțiile** — (1) `mp2`: 52-53 · `01_2026-08-25`: 62-63, 148-151 ·
`09_2025-12-09`: 993-1006; (2) `mp2`: 49 · `23_2025-07-29`: 563-566;
(3) `mp2`: 278-286; (4) `10_2025-12-02`: 728-730 · `09_2025-12-09`: 85-98;
(5) `mbt10`: 225-241.
**Legături** — `m2d`: 64-66, 150-159 · `23_2025-07-29`: 552-560 ·
`09_2025-12-09`: 1181-1186.