Skip to content

Monte Carlo API Reference

financelib.quant.monte_carlo.geometric_brownian_motion(S0: float, mu: float, sigma: float, T: float, n_steps: int = 252, n_simulations: int = 10000, seed: Optional[int] = None) -> np.ndarray

Simulate price paths using Geometric Brownian Motion.

dS = mu * S * dt + sigma * S * dW

Parameters:

Name Type Description Default
S0 float

Initial price.

required
mu float

Expected return (annualized drift).

required
sigma float

Volatility (annualized).

required
T float

Time horizon in years.

required
n_steps int

Number of time steps.

252
n_simulations int

Number of simulation paths.

10000
seed Optional[int]

Random seed for reproducibility.

None

Returns:

Type Description
ndarray

Array of shape (n_steps + 1, n_simulations) with simulated prices.

Example

paths = geometric_brownian_motion(S0=100, mu=0.05, sigma=0.2, T=1) paths.shape (253, 10000)

Source code in financelib/quant/monte_carlo.py
def geometric_brownian_motion(
    S0: float,
    mu: float,
    sigma: float,
    T: float,
    n_steps: int = 252,
    n_simulations: int = 10000,
    seed: Optional[int] = None,
) -> np.ndarray:
    """Simulate price paths using Geometric Brownian Motion.

    dS = mu * S * dt + sigma * S * dW

    Args:
        S0: Initial price.
        mu: Expected return (annualized drift).
        sigma: Volatility (annualized).
        T: Time horizon in years.
        n_steps: Number of time steps.
        n_simulations: Number of simulation paths.
        seed: Random seed for reproducibility.

    Returns:
        Array of shape (n_steps + 1, n_simulations) with simulated prices.

    Example:
        >>> paths = geometric_brownian_motion(S0=100, mu=0.05, sigma=0.2, T=1)
        >>> paths.shape
        (253, 10000)
    """
    if seed is not None:
        np.random.seed(seed)

    dt = T / n_steps
    paths = np.zeros((n_steps + 1, n_simulations))
    paths[0] = S0

    for t in range(1, n_steps + 1):
        z = np.random.standard_normal(n_simulations)
        paths[t] = paths[t - 1] * np.exp(
            (mu - 0.5 * sigma**2) * dt + sigma * np.sqrt(dt) * z
        )

    return paths

financelib.quant.monte_carlo.monte_carlo_var(returns: pd.Series, confidence: float = 0.95, n_simulations: int = 10000, horizon: int = 1, seed: Optional[int] = None) -> float

Calculate Value at Risk using Monte Carlo simulation.

Simulates future returns based on historical distribution parameters.

Parameters:

Name Type Description Default
returns Series

Historical returns series.

required
confidence float

Confidence level (e.g., 0.95).

0.95
n_simulations int

Number of simulations.

10000
horizon int

Holding period in days.

1
seed Optional[int]

Random seed.

None

Returns:

Type Description
float

VaR as a negative decimal (potential loss).

Source code in financelib/quant/monte_carlo.py
def monte_carlo_var(
    returns: pd.Series,
    confidence: float = 0.95,
    n_simulations: int = 10000,
    horizon: int = 1,
    seed: Optional[int] = None,
) -> float:
    """Calculate Value at Risk using Monte Carlo simulation.

    Simulates future returns based on historical distribution parameters.

    Args:
        returns: Historical returns series.
        confidence: Confidence level (e.g., 0.95).
        n_simulations: Number of simulations.
        horizon: Holding period in days.
        seed: Random seed.

    Returns:
        VaR as a negative decimal (potential loss).
    """
    if seed is not None:
        np.random.seed(seed)

    mu = float(returns.mean())
    sigma = float(returns.std())

    simulated = np.random.normal(mu * horizon, sigma * np.sqrt(horizon), n_simulations)
    var = float(np.percentile(simulated, (1 - confidence) * 100))
    return var

financelib.quant.monte_carlo.portfolio_monte_carlo(returns: pd.DataFrame, weights: np.ndarray, initial_value: float = 1000000, n_simulations: int = 5000, horizon: int = 252, seed: Optional[int] = None) -> Tuple[np.ndarray, dict]

Simulate portfolio value paths and compute risk statistics.

Parameters:

Name Type Description Default
returns DataFrame

DataFrame of asset returns (columns = assets).

required
weights ndarray

Portfolio weights array.

required
initial_value float

Initial portfolio value.

1000000
n_simulations int

Number of simulation paths.

5000
horizon int

Simulation horizon in trading days.

252
seed Optional[int]

Random seed.

None

Returns:

Type Description
ndarray

Tuple of (simulated_values array, statistics dict).

dict

statistics contains: mean_final, median_final, var_95, cvar_95,

Tuple[ndarray, dict]

prob_loss, expected_return, worst_case, best_case.

Source code in financelib/quant/monte_carlo.py
def portfolio_monte_carlo(
    returns: pd.DataFrame,
    weights: np.ndarray,
    initial_value: float = 1000000,
    n_simulations: int = 5000,
    horizon: int = 252,
    seed: Optional[int] = None,
) -> Tuple[np.ndarray, dict]:
    """Simulate portfolio value paths and compute risk statistics.

    Args:
        returns: DataFrame of asset returns (columns = assets).
        weights: Portfolio weights array.
        initial_value: Initial portfolio value.
        n_simulations: Number of simulation paths.
        horizon: Simulation horizon in trading days.
        seed: Random seed.

    Returns:
        Tuple of (simulated_values array, statistics dict).
        statistics contains: mean_final, median_final, var_95, cvar_95,
        prob_loss, expected_return, worst_case, best_case.
    """
    if seed is not None:
        np.random.seed(seed)

    mean_returns = returns.mean().values
    cov_matrix = returns.cov().values
    port_mean = np.dot(weights, mean_returns)
    port_std = np.sqrt(np.dot(weights.T, np.dot(cov_matrix, weights)))

    simulated = np.zeros((horizon + 1, n_simulations))
    simulated[0] = initial_value

    for t in range(1, horizon + 1):
        z = np.random.standard_normal(n_simulations)
        daily_return = port_mean + port_std * z
        simulated[t] = simulated[t - 1] * (1 + daily_return)

    final_values = simulated[-1]
    final_returns = (final_values - initial_value) / initial_value

    stats = {
        "mean_final": float(np.mean(final_values)),
        "median_final": float(np.median(final_values)),
        "var_95": float(np.percentile(final_values, 5)),
        "cvar_95": float(np.mean(final_values[final_values <= np.percentile(final_values, 5)])),
        "prob_loss": float(np.mean(final_values < initial_value)),
        "expected_return": float(np.mean(final_returns)),
        "worst_case": float(np.min(final_values)),
        "best_case": float(np.max(final_values)),
    }

    return simulated, stats