atmi: diagramele refacute, cinci noi, si fisa de surse
Noi: pivoti (PPQ/SQ calculati din trimestrul precedent, cu formula pe desen), perechi_tf (weekly -> daily ca descompunere reala, cu caseta, ghidaje si PPQ pe ambele panouri), trigger (BIM apoi verde, fata de verde inainte de BIM — cutitul in cadere), risc (ce inseamna "fara stop": 24 de bare sub apa, -20 % pe pozitie), reinvestire (ciclul banilor pe trei cicluri). aplus devine corectie: diagrama arata un prag de corectie, nu un setup A+, si numele vechi trimitea la altceva. Trei bug-uri reale: exemplul era etichetat weekly cu 20 de bare, dar textul spunea "un an mai tarziu" — trecut pe monthly cu assert pe numarul de luni; ansamblul avea o trimitere fisier:linie desenata in SVG; si benzile PPQ/SQ erau inversate ca sens, cu SQ fix pe intrare. PPQ 95.80 si SQ 90.80 sunt completare proprie — cursul spune explicit ca nu da valorile; derivate cu formula standard, cu assert. Textul capitolului e neatins — agentul a atins pragul de context. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ThN7ixZrowca8aTGrK1MUJ
This commit is contained in:
100
gen/strategii/atmi_risc.py
Normal file
100
gen/strategii/atmi_risc.py
Normal file
@@ -0,0 +1,100 @@
|
||||
"""ATMI — Pasul 5: ce înseamnă „fără stop-loss", desenat.
|
||||
|
||||
Același trade ca în restul capitolului (intrare 96.00, țintă +10 % = 105.60),
|
||||
dar arătând drumul, nu doar capetele: între intrare și țintă poziția trece
|
||||
printr-un drawdown — pierdere flotantă — de 20 % pe poziție, fără ca nimic
|
||||
să te scoată din ea. Cifra de 20-30 % pe poziție fără levier e a cursului
|
||||
(COVID 2020, 2018); traseul barelor e construit de mine.
|
||||
|
||||
Coloana din dreapta traduce aceeași cădere de 20 % a indicelui în pierdere
|
||||
pe poziție, pe trei variante de instrument — calculul e în cod.
|
||||
|
||||
Rulează: python3 gen/strategii/atmi_risc.py
|
||||
"""
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
sys.path.insert(0, "/workspace/atm-curs-dl")
|
||||
from svg_candles import Chart, Level, Mark, from_closes # noqa: E402
|
||||
|
||||
OUT = Path(__file__).resolve().parent / "atmi_risc.svg"
|
||||
GRAY, RED, GREEN, BLUE, INK, PURPLE = "#777", "#c00", "#188a3e", "#1a5fb4", "#333", "#7b2fbf"
|
||||
|
||||
ENTRY, TP, PPQ = 96.00, 105.60, 95.80
|
||||
DD_PCT = 20.0 # drawdown pe poziție, fără levier
|
||||
FUND = round(ENTRY * (1 - DD_PCT / 100), 2) # 76.80
|
||||
|
||||
# 3 bare de context + intrarea + 14 bare în jos + 17 bare de revenire
|
||||
CLOSES = ([98.20, 97.10, 96.40, ENTRY]
|
||||
+ [94.60, 92.80, 90.90, 89.40, 90.70, 88.60, 86.30, 84.40,
|
||||
85.60, 83.10, 81.00, 79.20, 78.10, FUND]
|
||||
+ [78.40, 80.60, 82.90, 84.50, 86.80, 88.40, 90.10, 92.30,
|
||||
94.00, ENTRY, 97.80, 99.40, 100.90, 102.20, 103.40, 104.50, TP])
|
||||
ENTRY_I, FUND_I, BE_I, TP_I = 3, 17, 27, len(CLOSES) - 1
|
||||
assert CLOSES[ENTRY_I] == ENTRY and CLOSES[FUND_I] == FUND
|
||||
assert CLOSES[BE_I] == ENTRY and CLOSES[TP_I] == TP
|
||||
|
||||
wicks = [(0.35, 0.35)] * len(CLOSES)
|
||||
wicks[ENTRY_I] = (0.30, 0.10)
|
||||
wicks[FUND_I] = (0.30, 0.00) # fundul e exact -20 %
|
||||
wicks[FUND_I + 1] = (0.35, 0.00) # nicio bară de după nu coboară sub fund
|
||||
wicks[TP_I] = (0.00, 0.35) # ținta e exact maximul seriei
|
||||
cds = from_closes(CLOSES, wicks=wicks, vols=[44 + (i * 11) % 41 for i in range(len(CLOSES))],
|
||||
start=98.90)
|
||||
|
||||
# --- ce susține textul -----------------------------------------------------
|
||||
fund = round(min(c.l for c in cds), 2)
|
||||
assert fund == FUND, fund
|
||||
assert round((ENTRY - fund) / ENTRY * 100, 1) == DD_PCT
|
||||
assert round(max(c.h for c in cds), 2) == TP
|
||||
assert round(TP / ENTRY, 3) == 1.100
|
||||
assert cds[FUND_I].l == fund and all(c.l >= fund for c in cds)
|
||||
assert FUND < PPQ, "fundul trebuie să fie sub pivotul pe care ai cumpărat"
|
||||
assert BE_I > FUND_I and CLOSES[BE_I] == ENTRY, "lipsește revenirea pe zero"
|
||||
DURATA_JOS = BE_I - ENTRY_I # câte bare stai sub prețul de intrare
|
||||
assert DURATA_JOS == 24, DURATA_JOS
|
||||
|
||||
# aceeași cădere de 20 % pe indice, tradusă pe trei instrumente
|
||||
VARIANTE = [("ETF simplu (SPY)", 1), ("ETF cu levier 2x", 2), ("ETF cu levier 3x (SPXL)", 3)]
|
||||
PIERDERI = [(n, round(DD_PCT * k, 1)) for n, k in VARIANTE]
|
||||
assert PIERDERI[-1][1] == 60.0, PIERDERI
|
||||
COVID = 34.0 # SPY în 2020, cifra cursului
|
||||
assert round(COVID * 3, 1) > 100.0, "3x pe -34 % trebuie să treacă de -100 %"
|
||||
|
||||
levels = [
|
||||
Level(TP, f"TP +10 % = {TP:.2f}", BLUE),
|
||||
Level(ENTRY, f"intrare {ENTRY:.2f}", GREEN, label_at="right"),
|
||||
Level(fund, f"fund {fund:.2f} = -{DD_PCT:.0f} % pe poziție", RED, label_at="left"),
|
||||
]
|
||||
marks = [
|
||||
Mark(FUND_I, f"-{DD_PCT:.0f} %: nimic nu te scoate", RED, "below"),
|
||||
Mark(BE_I, "abia aici ești pe zero", GRAY, "above", dy=-22),
|
||||
Mark(TP_I, "TP", BLUE, "below"),
|
||||
]
|
||||
|
||||
ch = Chart(candles=cds, levels=levels, marks=marks,
|
||||
scale=5.6, gap=16, body_w=9, left=56, width=720, vol_h=60, top=152,
|
||||
label_gap=46,
|
||||
caption="Cifra de 20-30 % pe poziție fără levier e a cursului; traseul barelor "
|
||||
"e construit de mine, ca să se vadă cât durează.")
|
||||
svg = ch.render()
|
||||
|
||||
titlu = ('<text x="24" y="24" fill="#333" style="font-weight:bold">'
|
||||
'SPY — daily: fără stop, între intrare și țintă treci prin toată căderea</text>')
|
||||
sub = (f'<text x="24" y="42" fill="#555" style="font-size:11px">'
|
||||
f'{DURATA_JOS} de bare sub prețul de intrare, fără niciun ordin care să te scoată '
|
||||
f'— ăsta e costul regulii „fără stop-loss".</text>')
|
||||
box = [f'<rect x="424" y="58" width="284" height="76" fill="#fff4f4" stroke="{RED}" '
|
||||
f'stroke-opacity="0.5"/>',
|
||||
f'<text x="436" y="76" fill="{RED}" style="font-size:11px;font-weight:bold">'
|
||||
f'aceeași cădere de {DD_PCT:.0f} % pe indice, pe poziție:</text>']
|
||||
for i, (nume, pct) in enumerate(PIERDERI):
|
||||
box.append(f'<text x="436" y="{94 + i * 15}" fill="{INK}" style="font-size:11px">'
|
||||
f'{nume}: -{pct:.0f} %</text>')
|
||||
|
||||
i = svg.index(">") + 1
|
||||
svg = svg[:i] + "\n " + "\n ".join([titlu, sub] + box) + svg[i:]
|
||||
assert "\n\n" not in svg and ".md:" not in svg
|
||||
OUT.write_text(svg)
|
||||
print(f"scris {OUT.name}: intrare {ENTRY} fund {fund} (-{DD_PCT} %) TP {TP}, "
|
||||
f"{DURATA_JOS} bare sub apă")
|
||||
Reference in New Issue
Block a user