research(hyro): HyroTrader nello specifico — consistency 40% refutata, DD 6% e' il vincolo
Addendum all'ondata rendita, su richiesta dell'operatore ("e hyrotrader").
CONSISTENCY 40%: ipotesi REFUTATA. Avevo previsto una tagliola (SKH01 ha P&L a scalino,
TP01 fa strappi di trend). Misurato: costo ~0pp a ogni leva e in entrambe le lenti,
perche' il book accumula il 10% in 130-300 giorni -> nessun giorno si avvicina al 40%
del cumulato. Prima di dichiararlo ho dovuto PROVARE che il controllo funziona (un
"costo 0" puo' essere un bug): su un book con profitto concentrato in 1-2 giorni la
regola porta P(pass) da >90% a <5%. Due iterazioni di test prima di avere un
discriminante valido (strappi ripetuti si diluiscono; sim_eval fa block-bootstrap,
non replay).
IL VINCOLO VERO E' IL maxDD 6% STATICO. Config A (book live TP01/SKH01) ha maxDD 9.5%
> 6% = strutturalmente incompatibile a leva piena: intraday a 1.0x sopravvive l'1.4%.
Config B (+XS01) ha maxDD 6.2% e Sharpe 1.13.
RACCOMANDAZIONE: config B a leva funded 0.50x (intraday P(vivo) 71% vs 32% a 0.75x;
E[payout] €7.69 vs €8.66/g — la sopravvivenza COMPONE su piu' anni, un conto bustato
smette di produrre per sempre). EV del biglietto $100k positivo in entrambe le lenti
(+$6.789 close-only, +$1.166 intraday), con ~69% di perdere la fee nella lente
pessimista. Cap $200k/trader => ~€15-30/g max: per €50/g servono piu' firm.
DISCREPANZA DICHIARATA col 24/07 (P(vivo) A@0.75x: 58% loro, 10% mio): il mio wick e' a
estrazione indipendente (piu' severo) e la finestra 2024+ e' quella dove A e' debole.
La direzione concorda (meno leva e' meglio); sul LIVELLO il numero del 24/07 (recon MTM
vero) e' piu' affidabile del mio.
Piu' l'addendum "10k su IB" al diario (analisi gia' committata in ea6743d).
Test: 217 pass (+3: consistency morde/non-morde, DD statico binding).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -496,6 +496,21 @@ Prima ondata di ricerca onesta su BTC/ETH certificati (5 track, harness condivis
|
||||
rendita, taglia il maxDD 15.3→12.0%, unico split che regge coi costi). ⚠ Il confronto FAVORISCE il
|
||||
crypto per costruzione (7 anni con 2 bull vs 30 anni di GTAA); tassi e aliquote (26%/33%) sono
|
||||
assunzioni dichiarate, da confermare col commercialista (non un parere fiscale).
|
||||
(7) **HYROTRADER nello specifico** (`r0725_hyro.py`): la firm meglio classificata per questo book
|
||||
(API reale da funded, nessun limite di tempo, **weekend consentito** — e il weekend porta il 38%
|
||||
del gross di TP01). **Ipotesi REFUTATA: la regola di consistency 40% NON morde** (costo ≈0pp a
|
||||
ogni leva/lente) perche' il book accumula il 10% in 130-300 giorni → nessun giorno si avvicina al
|
||||
40% del cumulato; ⚠ prima di dichiararlo ho dovuto **provare che il controllo funziona** (un
|
||||
"costo 0" puo' essere un bug): su un book con profitto concentrato in 1-2 giorni la regola porta
|
||||
P(pass) da >90% a <5% (test cablato). **Il vincolo vero e' il maxDD 6% STATICO**: config A (book
|
||||
live) ha maxDD 9.5% > 6% = strutturalmente incompatibile a leva piena — intraday a 1.0x
|
||||
sopravvive l'**1.4%**; config B (+XS01) ha maxDD 6.2%, Sharpe 1.13. **Funded consigliato: config B
|
||||
a 0.50x** (intraday P(vivo) 71% vs 32% a 0.75x, E[payout] €7.69 vs €8.66/g — la sopravvivenza
|
||||
COMPONE su piu' anni). EV del biglietto $100k **positivo in entrambe le lenti** (+$6.789
|
||||
close-only, +$1.166 intraday), ma ~69% di perdere la fee nella lente pessimista. Cap $200k/trader
|
||||
⇒ ~€15-30/g max → per €50/g servono piu' firm (punto 5). ⚠ Discrepanza col 24/07 (P(vivo) A@0.75x
|
||||
58% vs 10% mio): mio wick indipendente = piu' severo + finestra 2024+ dove A e' debole; **la
|
||||
direzione concorda, sul LIVELLO il numero del 24/07 (recon MTM vero) e' piu' affidabile**.
|
||||
⚠ Bug catturato in sessione: base di prelievo funded aggiornata giornalmente come HWM mobile →
|
||||
guadagno al checkpoint ≈ 0 → **payout $230/anno invece di ~$7.000**; regole vere = max-loss STATICO
|
||||
dal saldo iniziale + base ripristinata dopo il prelievo. Test di regressione cablato.
|
||||
|
||||
@@ -289,6 +289,69 @@ vanno confermate col commercialista (**non è un parere fiscale**).
|
||||
|
||||
---
|
||||
|
||||
## 8) HYROTRADER nello specifico (`r0725_hyro.py`)
|
||||
|
||||
La firm che il 24/07 aveva messo prima in classifica per *questo* book: unica con **API reale** da
|
||||
funded (sub-account Bybit) → il book gira automatico; **nessun limite di tempo** sull'eval (una
|
||||
strategia lenta non è penalizzata); **weekend consentito** — non banale, l'ondata 2026-07-17 ha
|
||||
misurato che il weekend porta il **38% del gross di TP01**. Biglietti $25k/$249, $50k/$379,
|
||||
$100k/$579, cap $200k, split 80%, fee rimborsata al pass.
|
||||
|
||||
Due regole mordono proprio noi, e nessuna analisi le aveva modellate: **maxDD 6% STATICO** e
|
||||
**consistency 40%** (nessun giorno > 40% del profitto totale, in eval).
|
||||
|
||||
**Ipotesi refutata: la consistency NON morde.** Avevo previsto una tagliola (SKH01 ha P&L a
|
||||
scalino, TP01 fa strappi di trend). Misurato: **costo ≈ 0pp** a ogni leva e in entrambe le lenti.
|
||||
Ragione strutturale: il book accumula il 10% in **130-300 giorni**, quindi nessun singolo giorno
|
||||
si avvicina al 40% del cumulato. ⚠️ Prima di dichiararlo ho dovuto **provare che il controllo
|
||||
funziona** (un "costo 0" può essere un bug): `test_consistency_MORDE_su_un_book_grumoso` mostra
|
||||
che su un book con profitto concentrato in 1-2 giorni la regola porta P(pass) da >90% a <5%. Il
|
||||
meccanismo c'è; è il book a non essere grumoso abbastanza. *(Il primo probe era sbagliato — strappi
|
||||
ripetuti si diluiscono a vicenda, e sim_eval fa block-bootstrap, non replay: due iterazioni di test
|
||||
prima di avere un discriminante valido.)*
|
||||
|
||||
**Il vincolo vero è il DD 6% statico.** Finestra comune 2024+, de-luck ×0.6:
|
||||
|
||||
| | Sharpe | CAGR | vol | maxDD |
|
||||
|---|---|---|---|---|
|
||||
| A — book live (TP01/SKH01) | 0.74 | 7.2% | 10.1% | 9.5% |
|
||||
| B — + XS01 | **1.13** | 10.0% | 8.8% | **6.2%** |
|
||||
|
||||
Config A ha maxDD 9.5% contro un limite di 6%: **strutturalmente incompatibile a leva piena**.
|
||||
|
||||
**Funded $100k, P(vivo 1 anno) / €-giorno:**
|
||||
|
||||
| config | leva | close-only (tetto) | intraday (pavimento) |
|
||||
|---|---|---|---|
|
||||
| A | 0.50× | 80.2% / €8.33 | 44.0% / €6.86 |
|
||||
| A | 0.75× | 51.1% / €12.21 | **10.1%** / — |
|
||||
| A | 1.00× | 27.1% / €13.89 | **1.4%** / — |
|
||||
| B | 0.50× | 98.5% / €8.69 | **71.0%** / €7.69 |
|
||||
| B | 0.75× | 85.4% / €12.78 | 31.6% / €8.66 |
|
||||
| B | 1.00× | 66.0% / €16.20 | 9.9% / — |
|
||||
|
||||
**EV del biglietto** (config B, eval 1.0×, funded a leva ottima, 1 anno): close-only P(pass) 73.0%
|
||||
→ EV **+$6.789** sul biglietto $100k; intraday P(pass) 31.1% → EV **+$1.166**. **Positivo in
|
||||
entrambe le lenti** — ma con ~69% di probabilità di perdere la fee nella lente pessimista.
|
||||
|
||||
**Raccomandazione operativa:**
|
||||
1. **Config B (con XS01), non il book live attuale.** A 1.0× intraday config A sopravvive l'1.4%:
|
||||
mandarci il book a 2 sleeve a leva piena è morte quasi certa.
|
||||
2. **Funded a 0.50×** (non 0.75× come indicava il 24/07 per la config A): E[payout] scende poco
|
||||
(€7.69 vs €8.66/g) ma la sopravvivenza raddoppia (71% vs 32%) — e su orizzonti pluriennali la
|
||||
sopravvivenza **compone**, un conto bustato smette di produrre per sempre.
|
||||
3. Eval a 0.75-1.0×; biglietto $25-50k come test economico — l'EV scala **linearmente** con la
|
||||
taglia, quindi la ragione per partire piccoli è varianza e apprendimento, non EV.
|
||||
4. **Cap $200k/trader ⇒ ~€15-30/g anche negli scenari buoni.** Per €50/g servono più firm → §6.
|
||||
|
||||
⚠️ **Discrepanza dichiarata col 24/07:** lì il funded di config A a 0.75× dava P(vivo) 58%, qui
|
||||
10%. Due cause note: (a) il mio wick è a estrazione indipendente (più severo — §6); (b) finestra
|
||||
2024+, dove config A è debole (Sharpe 0.74 vs 0.99 sulla finestra piena). **La direzione concorda
|
||||
(meno leva è meglio), il livello no** — e il numero del 24/07 usa il recon MTM vero, quindi sul
|
||||
livello è più affidabile del mio.
|
||||
|
||||
---
|
||||
|
||||
## Bug catturato in sessione
|
||||
|
||||
**Modello funded, base di prelievo aggiornata ogni giorno come un HWM mobile** → al checkpoint
|
||||
|
||||
@@ -0,0 +1,210 @@
|
||||
"""r0725_hyro — HYROTRADER nello specifico: config, leva e la regola di CONSISTENCY (2026-07-25).
|
||||
|
||||
La ricerca del 24/07 ha messo HyroTrader prima in classifica per QUESTO book:
|
||||
* unica con **API reale** da funded (sub-account Bybit) -> il book gira automatico, non a mano;
|
||||
* **nessun limite di tempo** sull'eval -> una strategia lenta non e' penalizzata;
|
||||
* **weekend consentito** -> non banale: l'ondata 2026-07-17 ha misurato che il weekend porta
|
||||
il **38% del gross di TP01** nel 31% del tempo (de-esporlo e' attivamente dannoso);
|
||||
* funding = mercato (stessa economia del book Deribit), fee rimborsata al pass, payout ~12h.
|
||||
Biglietti 1-step: $25k/$249, $50k/$379, $100k/$579. Cap $200k per trader.
|
||||
|
||||
Ma ha due regole che mordono ESATTAMENTE questo book, e nessuna analisi le aveva modellate:
|
||||
1. **max drawdown 6% STATICO** (dal saldo iniziale) — il book de-luckato ha maxDD 15.4% a 1.0x;
|
||||
2. **CONSISTENCY 40% in eval**: nessun singolo giorno puo' valere piu' del 40% del profitto
|
||||
totale. E' una tagliola per un book LENTO e GRUMOSO: SKH01 ha P&L per-trade a scalino
|
||||
(caveat noto "equity daily-step") e TP01 fa mesi piatti seguiti da strappi di trend. Se il
|
||||
target del 10% arriva con 2-3 giornatone, l'eval **non passa**: si deve continuare a
|
||||
tradare finche' il profitto totale si diluisce — esponendosi altro tempo al DD 6%.
|
||||
|
||||
Questo script misura: P(pass) con e senza consistency, la leva ottima, e l'EV di ogni biglietto.
|
||||
|
||||
ONESTA': doppia lente. CLOSE-ONLY = tetto ottimista; INTRADAY = pavimento (gap lognormale
|
||||
calibrato sul recon MTM 1h del 24/07, ma estratto indipendente dal rendimento del giorno ->
|
||||
breach spuri: vedi il caveat in r0725_prop_ladder.py). La verita' sta in mezzo. Finestra comune
|
||||
2024+ (dove esiste XS01) = anche la finestra di scoperta di XS01 -> la config B e' favorita.
|
||||
|
||||
Uso: `uv run python scripts/research/r0725_hyro.py`
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
sys.path.insert(0, str(ROOT))
|
||||
sys.path.insert(0, str(ROOT / "scripts" / "research"))
|
||||
|
||||
from src.portfolio.portfolio import combine_outer, metrics # noqa: E402
|
||||
from src.portfolio.sleeves import _xsec_returns # noqa: E402
|
||||
|
||||
import r0724_skh_live_weight as skl # noqa: E402
|
||||
from r0725_capcurve import EURUSD, TAX_RATE, tp01_realistic # noqa: E402
|
||||
from r0725_prop_ladder import WICK_MU, WICK_SIGMA, WICK_REF_VOL # noqa: E402
|
||||
|
||||
# --- regole HyroTrader 1-step (ricerca 24/07, fonti primarie)
|
||||
EV_TARGET, EV_DD, EV_DL = 0.10, 0.06, 0.04
|
||||
FU_ML, FU_DL = 0.06, 0.04
|
||||
CONSISTENCY = 0.40 # nessun giorno > 40% del profitto totale (solo in eval)
|
||||
SPLIT = 0.80
|
||||
TICKETS = [(25_000, 249.0), (50_000, 379.0), (100_000, 579.0)]
|
||||
CAP = 200_000
|
||||
DELUCK = 0.6
|
||||
RNG = np.random.default_rng(20260725)
|
||||
|
||||
|
||||
def _d(s: pd.Series) -> pd.Series:
|
||||
s = s.dropna().sort_index()
|
||||
if s.index.tz is None:
|
||||
s.index = s.index.tz_localize("UTC")
|
||||
return s
|
||||
|
||||
|
||||
def configs() -> dict:
|
||||
skh = _d(skl.skh_book(0, "hourly"))
|
||||
tp = _d(tp01_realistic(100_000 * 0.75))
|
||||
xs = _d(_xsec_returns()).resample("1D").apply(lambda x: (1 + x).prod() - 1)
|
||||
lo = max(tp.index.min(), skh.index.min(), xs.index.min())
|
||||
out = {}
|
||||
for name, cols, w in (
|
||||
("A book live (TP01/SKH01)", {"TP01": tp, "SKH01": skh}, {"TP01": .75, "SKH01": .25}),
|
||||
("B + XS01 (19 alt perp)", {"TP01": tp, "SKH01": skh, "XS01": xs},
|
||||
{"TP01": .55, "SKH01": .20, "XS01": .25}),
|
||||
):
|
||||
s = combine_outer(cols, w, lo=lo)
|
||||
s = s - (1.0 - DELUCK) * float(s.mean())
|
||||
out[name] = s
|
||||
return out
|
||||
|
||||
|
||||
def _paths(r: np.ndarray, n_days: int, n_paths: int, block: int = 20) -> np.ndarray:
|
||||
nb = int(np.ceil(n_days / block))
|
||||
st = RNG.integers(0, len(r) - block, size=(n_paths, nb))
|
||||
idx = (st[:, :, None] + np.arange(block)[None, None, :]).reshape(n_paths, -1)[:, :n_days]
|
||||
return r[idx]
|
||||
|
||||
|
||||
def _wick(shape, vol: float) -> np.ndarray:
|
||||
scale = float(np.clip(vol / WICK_REF_VOL, 0.0, 3.0))
|
||||
return -np.exp(RNG.normal(WICK_MU, WICK_SIGMA, size=shape)) * scale
|
||||
|
||||
|
||||
def sim_eval(r: np.ndarray, k: float, consistency: bool, intraday: bool,
|
||||
max_days: int = 540, n_paths: int = 8000) -> dict:
|
||||
"""Eval HYRO. Il pass richiede equity >= 1+target E (se consistency) che il MIGLIOR giorno
|
||||
non superi il 40% del profitto cumulato. Breach su equity intraday."""
|
||||
R = _paths(r, max_days, n_paths) * k
|
||||
G = _wick(R.shape, float(r.std() * np.sqrt(365)) * k) if intraday else np.zeros_like(R)
|
||||
eq = np.ones(n_paths)
|
||||
best_day = np.zeros(n_paths) # miglior guadagno giornaliero in USD-equity
|
||||
alive = np.ones(n_paths, bool)
|
||||
passed = np.zeros(n_paths, bool)
|
||||
day_pass = np.full(n_paths, max_days + 1, int)
|
||||
for t in range(max_days):
|
||||
prev = eq
|
||||
eq = np.where(alive & ~passed, eq * (1 + R[:, t]), eq)
|
||||
low = np.where(alive & ~passed, prev * (1 + R[:, t] + G[:, t]), eq)
|
||||
gain = np.maximum(eq - prev, 0.0)
|
||||
best_day = np.where(alive & ~passed, np.maximum(best_day, gain), best_day)
|
||||
bust = alive & ~passed & ((low < 1.0 - EV_DD) | ((R[:, t] + G[:, t]) < -EV_DL))
|
||||
alive &= ~bust
|
||||
profit = eq - 1.0
|
||||
ok = alive & ~passed & (profit >= EV_TARGET)
|
||||
if consistency:
|
||||
ok &= best_day <= CONSISTENCY * np.maximum(profit, 1e-9)
|
||||
day_pass[ok] = t
|
||||
passed |= ok
|
||||
return dict(p_pass=float(passed.mean()),
|
||||
median_days=float(np.median(day_pass[passed])) if passed.any() else float("nan"))
|
||||
|
||||
|
||||
def sim_funded(r: np.ndarray, k: float, intraday: bool, notional: float,
|
||||
years: int = 1, n_paths: int = 8000) -> dict:
|
||||
n_days = years * 365
|
||||
R = _paths(r, n_days, n_paths) * k
|
||||
G = _wick(R.shape, float(r.std() * np.sqrt(365)) * k) if intraday else np.zeros_like(R)
|
||||
eq = np.ones(n_paths)
|
||||
alive = np.ones(n_paths, bool)
|
||||
payout = np.zeros(n_paths)
|
||||
for t in range(n_days):
|
||||
prev = eq
|
||||
eq = np.where(alive, eq * (1 + R[:, t]), eq)
|
||||
low = np.where(alive, prev * (1 + R[:, t] + G[:, t]), eq)
|
||||
bust = alive & ((low < 1.0 - FU_ML) | ((R[:, t] + G[:, t]) < -FU_DL))
|
||||
alive &= ~bust
|
||||
if (t + 1) % 30 == 0:
|
||||
g = np.where(alive & (eq > 1.0), eq - 1.0, 0.0)
|
||||
payout += g * SPLIT
|
||||
eq = np.where(alive & (eq > 1.0), 1.0, eq)
|
||||
usd = payout * notional
|
||||
return dict(p_alive=float(alive.mean()), e_payout=float(usd.mean()),
|
||||
eur_day=float(usd.mean() * (1 - TAX_RATE) / EURUSD / 365.0))
|
||||
|
||||
|
||||
def main() -> None:
|
||||
cfg = configs()
|
||||
print("=" * 100)
|
||||
print(" HYROTRADER — config, leva e la regola di CONSISTENCY 40%")
|
||||
print("=" * 100)
|
||||
print(f" regole: target {EV_TARGET:.0%} | maxDD {EV_DD:.0%} STATICO | daily {EV_DL:.0%} | "
|
||||
f"consistency {CONSISTENCY:.0%} (eval) | split {SPLIT:.0%} | cap ${CAP:,}")
|
||||
for n, s in cfg.items():
|
||||
m = metrics(s)
|
||||
print(f" {n:>28}: Sharpe {m['sharpe']:>5.2f} CAGR {m['cagr']:>6.1%} "
|
||||
f"vol {s.std()*np.sqrt(365):>5.1%} maxDD {m['maxdd']:>5.1%}")
|
||||
|
||||
for intraday in (False, True):
|
||||
lens = "INTRADAY (pavimento)" if intraday else "CLOSE-ONLY (tetto)"
|
||||
print("\n" + "-" * 100)
|
||||
print(f" EVAL — {lens}: quanto costa la regola di CONSISTENCY")
|
||||
print("-" * 100)
|
||||
print(f" {'config':>28} {'leva':>5} {'P(pass) senza':>14} {'P(pass) CON':>12} "
|
||||
f"{'costo regola':>13} {'giorni med':>11}")
|
||||
for n, s in cfg.items():
|
||||
r = s.values.astype(float)
|
||||
for k in (0.5, 0.75, 1.0):
|
||||
a = sim_eval(r, k, consistency=False, intraday=intraday, n_paths=4000)
|
||||
b = sim_eval(r, k, consistency=True, intraday=intraday, n_paths=4000)
|
||||
print(f" {n:>28} {k:>5.2f} {a['p_pass']:>14.1%} {b['p_pass']:>12.1%} "
|
||||
f"{b['p_pass']-a['p_pass']:>+13.1f}pp {b['median_days']:>11.0f}")
|
||||
|
||||
print(f"\n FUNDED $100k — {lens}")
|
||||
print(f" {'config':>28} {'leva':>5} {'P(vivo 1a)':>11} {'E[payout]':>11} {'EUR/g':>7}")
|
||||
for n, s in cfg.items():
|
||||
r = s.values.astype(float)
|
||||
for k in (0.5, 0.75, 1.0):
|
||||
f = sim_funded(r, k, intraday, 100_000.0, n_paths=4000)
|
||||
print(f" {n:>28} {k:>5.2f} {f['p_alive']:>11.1%} ${f['e_payout']:>10,.0f} "
|
||||
f"{f['eur_day']:>7.2f}")
|
||||
|
||||
# --- EV del biglietto (lente intraday = quella su cui si decide, piu' close-only come tetto)
|
||||
print("\n" + "-" * 100)
|
||||
print(" EV DEL BIGLIETTO — config B, eval a leva 1.0x, funded a leva ottima, 1 anno")
|
||||
print(" (la fee e' rimborsata al pass: il costo atteso e' fee x P(fallire l'eval))")
|
||||
print("-" * 100)
|
||||
r = cfg["B + XS01 (19 alt perp)"].values.astype(float)
|
||||
for intraday in (False, True):
|
||||
lens = "intraday" if intraday else "close-only"
|
||||
pe = sim_eval(r, 1.0, consistency=True, intraday=intraday, n_paths=4000)["p_pass"]
|
||||
best = None
|
||||
for k in (0.5, 0.75, 1.0):
|
||||
f = sim_funded(r, k, intraday, 100_000.0, n_paths=4000)
|
||||
if best is None or f["e_payout"] > best[1]["e_payout"]:
|
||||
best = (k, f)
|
||||
print(f"\n [{lens}] P(pass eval) {pe:.1%} | leva funded ottima {best[0]:.2f}x "
|
||||
f"(P(vivo) {best[1]['p_alive']:.1%})")
|
||||
print(f" {'biglietto':>12} {'prezzo':>8} {'E[payout] 1a':>14} {'costo atteso':>13} "
|
||||
f"{'EV':>10} {'EUR/g atteso':>13}")
|
||||
for size, price in TICKETS:
|
||||
scale = size / 100_000.0
|
||||
ev_payout = pe * best[1]["e_payout"] * scale
|
||||
cost = price * (1.0 - pe) # la fee e' rimborsata al pass -> si perde solo se si fallisce
|
||||
ev = ev_payout - cost
|
||||
print(f" ${size:>11,} ${price:>7,.0f} ${ev_payout:>13,.0f} "
|
||||
f"${cost:>12,.0f} ${ev:>9,.0f} {ev*(1-TAX_RATE)/EURUSD/365:>13.2f}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -180,3 +180,48 @@ def test_senza_cassa_nessun_conto_e_nessun_reddito(pl):
|
||||
assert r["p_zero"] == 1.0
|
||||
finally:
|
||||
pl.START_EUR = old
|
||||
|
||||
|
||||
# ------------------------------------------- 5) regola di CONSISTENCY HyroTrader
|
||||
@pytest.fixture(scope="module")
|
||||
def hy():
|
||||
return _load("r0725_hyro", "scripts/research/r0725_hyro.py")
|
||||
|
||||
|
||||
def test_consistency_MORDE_su_un_book_grumoso(hy):
|
||||
"""PROVA CHE IL CONTROLLO FUNZIONA. Un UNICO giorno da +12% porta da solo tutto il profitto
|
||||
e non arriva mai altro: con la regola 40% quel path non deve passare MAI (0.12 > 0.40*0.12),
|
||||
senza regola passa subito. Se questo test non discrimina, il 'costo ~0pp' misurato sul book
|
||||
vero sarebbe un bug, non un risultato.
|
||||
|
||||
NB sul probe: sim_eval fa BLOCK BOOTSTRAP (blocchi di 20g), non replay -> uno strappo isolato
|
||||
finirebbe solo in alcuni path. Qui gli strappi sono spaziati di 20 giorni = esattamente uno per
|
||||
blocco, cosi' OGNI path ne vede uno ogni 20 giorni in modo deterministico. In 40 giorni:
|
||||
senza regola si passa al 1o strappo (+12% >= target 10%); con la regola servono 3 strappi
|
||||
perche' il giorno migliore scenda sotto il 40% del profitto cumulato -> oltre la finestra.
|
||||
"""
|
||||
r = np.zeros(200)
|
||||
r[::20] = 0.12
|
||||
senza = hy.sim_eval(r, 1.0, consistency=False, intraday=False, max_days=40, n_paths=200)
|
||||
con = hy.sim_eval(r, 1.0, consistency=True, intraday=False, max_days=40, n_paths=200)
|
||||
assert senza["p_pass"] > 0.9, "senza regola un +12% secco deve passare il target 10%"
|
||||
assert con["p_pass"] < 0.05, "la regola 40% deve bloccare un profitto concentrato in 1-2 giorni"
|
||||
|
||||
|
||||
def test_consistency_non_morde_su_un_book_liscio(hy):
|
||||
"""Controprova: un book che accumula il target in tanti giorni piccoli non e' toccato
|
||||
dalla regola. E' il motivo per cui sul book vero il costo misurato e' ~0."""
|
||||
r = np.full(400, 0.0008) # ~+0.08%/g: il 10% arriva in ~120 giorni
|
||||
senza = hy.sim_eval(r, 1.0, consistency=False, intraday=False, n_paths=200)
|
||||
con = hy.sim_eval(r, 1.0, consistency=True, intraday=False, n_paths=200)
|
||||
assert abs(con["p_pass"] - senza["p_pass"]) < 0.02
|
||||
|
||||
|
||||
def test_dd_statico_6pct_e_binding(hy):
|
||||
"""Il maxDD 6% STATICO di HYRO e' il vincolo vero: un book con DD storico sopra il 6%
|
||||
non puo' girare a leva piena. Sanity: alzando la leva la sopravvivenza funded scende."""
|
||||
cfg = hy.configs()
|
||||
r = list(cfg.values())[0].values.astype(float)
|
||||
lo = hy.sim_funded(r, 0.5, False, 100_000.0, n_paths=400)["p_alive"]
|
||||
hi = hy.sim_funded(r, 1.0, False, 100_000.0, n_paths=400)["p_alive"]
|
||||
assert lo > hi
|
||||
|
||||
Reference in New Issue
Block a user