avhz / RustQuant

Rust library for quantitative finance.
https://avhz.github.io
Apache License 2.0
1.02k stars 117 forks source link

Implementation of the Milstein Scheme + a Monte Carlo Engine #244

Open yfnaji opened 1 month ago

yfnaji commented 1 month ago

Background

There are two traits in the Stochastics module, StochasticProcess and StochasticVolatilityProcess. The two traits utilise the Euler-Maruyama scheme through methods euler_maruyama() and seedable_euler_maruyama() to approximate solutions to stochastic differential equations (SDEs).

Feature requests

Mathematical context for the feature requests

Milstein Method

Take the SDE

$$ dX_t = A(X_t)dt + B(X_t) dW_t $$

where $W_t\sim N\left(0, t\right)$ is the Wiener process. The Milstein method at time $\tau_n\in\left[0, T\right]$ is defined as

$$ \tilde{X}_{n+1} = \tilde{X}_n + A(\tilde{X}_n)\Delta t + B(\tilde{X}_n)\Delta W_t + \frac{1}{2}b(\tilde{X}_n)\frac{\partial}{\partial X}B\left(\tilde{X}_n\right)\left(\Delta W_n^2 - \Delta t\right) $$

with the initial condition $\tilde{X_0} = x_0$.

Monte Carlo Method for Option Pricing

The Monte-Carlo method provides the following approximation

$$ \textrm{E}\left[X\right] \approx \frac{1}{n}\sum^N_{i=0} X_i $$

for some stochastic process $X$, simulated samples $X_i$ and sufficiently large $N$.

We can simulate a numerical scheme $N$ times, each approximating the value of an asset $S_T$ and then obtain the Monte-Carlo approximation from there:

$$ \textrm{E}\left[\left(S_T - K\right)_{+}\right] \approx \textrm{E}\left[\left(\tilde{S}_T - K\right)_{+}\right] \approx \frac{1}{n}\sum^N_{i=0} \left(\tilde{S}_{T, i} - K\right)_{+} $$

where $\tilde{S}_{T, i}$ is the $i^{\textrm{th}}$ numerical approximation of $S_T$.

avhz commented 1 month ago

Sounds great :) Go ahead.

It would be good to implement using a payoff trait like:

trait PathDependentPayoff {
    fn payoff(&self, path: &[f64]) -> f64;
}

That way each type of option can implement their respective payoffs and the Monte-Carlo engine can handle them all.

Note: start with StochasticProcess first, I believe StochasticVolatilityProcess needs work.

avhz commented 2 weeks ago

Edit: I have done a basic Monte-Carlo pricer trait, and impl'd it for a vanilla option here: https://github.com/avhz/RustQuant/blob/main/src/instruments/options/vanilla.rs

Hi, following up on this as I am doing a fair bit of re-working to the instruments module.

I will be using a Payoff trait of the form instead of my previous comment:

/// Generic payoff trait.
pub trait Payoff {
    /// Underlying input type for the payoff function.
    type Underlying;

    /// Payoff function for the derivative.
    fn payoff(&self, underlying: Self::Underlying) -> f64;
}

impl Payoff for VanillaOption {
    type Underlying = f64;

    fn payoff(&self, underlying: Self::Underlying) -> f64 {
        ...
    }
}

impl Payoff for AsianOption {
    type Underlying = Vec<f64>;

    fn payoff(&self, underlying: Self::Underlying) -> f64 {
        ...
    }
}