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}
|