21 lines
1.1 KiB
Python
21 lines
1.1 KiB
Python
import numpy as np
| |||
| |||
def monte_carlo(trades, initial, runs=2000, ruin_dd_pct=30.0, seed=42):
| |||
"""Rééchantillonne les trades (rendement par trade, composé) pour estimer la dispersion des résultats."""
| |||
if len(trades) < 10:
| |||
return None
| |||
rets = (trades.pnl / trades.equity_before).to_numpy()
| |||
rng = np.random.default_rng(seed)
| |||
idx = rng.integers(0, len(rets), size=(runs, len(rets)))
| |||
paths = initial * np.cumprod(1 + rets[idx], axis=1)
| |||
paths = np.concatenate([np.full((runs, 1), initial), paths], axis=1)
| |||
peak = np.maximum.accumulate(paths, axis=1)
| |||
dd = ((peak - paths) / peak).max(axis=1) * 100
| |||
final = paths[:, -1]
| |||
q = lambda x, p: float(np.percentile(x, p))
| |||
return {"runs": runs, "trades": len(rets),
| |||
"final_p5": q(final, 5), "final_p50": q(final, 50), "final_p95": q(final, 95),
| |||
"dd_p50": q(dd, 50), "dd_p95": q(dd, 95),
| |||
"prob_loss": float((final < initial).mean() * 100),
| |||
"prob_dd10": float((dd >= 10).mean() * 100),
| |||
"prob_ruin": float((dd >= ruin_dd_pct).mean() * 100), "ruin_dd_pct": ruin_dd_pct}
|