use stochastic_rs_distributions::special::norm_cdf;
use crate::traits::PricerExt;
use crate::traits::TimeExt;
#[derive(Debug, Clone)]
pub struct AsianPricer {
pub s: f64,
pub v: f64,
pub k: f64,
pub r: f64,
pub q: Option<f64>,
pub tau: Option<f64>,
pub eval: Option<chrono::NaiveDate>,
pub expiration: Option<chrono::NaiveDate>,
}
impl AsianPricer {
pub fn new(
s: f64,
v: f64,
k: f64,
r: f64,
q: Option<f64>,
tau: Option<f64>,
eval: Option<chrono::NaiveDate>,
expiration: Option<chrono::NaiveDate>,
) -> Self {
Self {
s,
v,
k,
r,
q,
tau,
eval,
expiration,
}
}
pub fn builder(s: f64, v: f64, k: f64, r: f64) -> AsianPricerBuilder {
AsianPricerBuilder {
s,
v,
k,
r,
q: None,
tau: None,
eval: None,
expiration: None,
}
}
}
#[derive(Debug, Clone)]
pub struct AsianPricerBuilder {
s: f64,
v: f64,
k: f64,
r: f64,
q: Option<f64>,
tau: Option<f64>,
eval: Option<chrono::NaiveDate>,
expiration: Option<chrono::NaiveDate>,
}
impl AsianPricerBuilder {
pub fn q(mut self, q: f64) -> Self {
self.q = Some(q);
self
}
pub fn tau(mut self, tau: f64) -> Self {
self.tau = Some(tau);
self
}
pub fn eval(mut self, eval: chrono::NaiveDate) -> Self {
self.eval = Some(eval);
self
}
pub fn expiration(mut self, expiration: chrono::NaiveDate) -> Self {
self.expiration = Some(expiration);
self
}
pub fn build(self) -> AsianPricer {
AsianPricer {
s: self.s,
v: self.v,
k: self.k,
r: self.r,
q: self.q,
tau: self.tau,
eval: self.eval,
expiration: self.expiration,
}
}
}
impl PricerExt for AsianPricer {
fn calculate_call_put(&self) -> (f64, f64) {
let T = self.calculate_tau_in_years();
let v = self.v / 3.0_f64.sqrt();
let b = 0.5 * (self.r - self.q.unwrap_or(0.0) - 0.5 * v.powi(2) / 6.0);
let d1 = ((self.s / self.k).ln() + (b + 0.5 * v.powi(2) * T)) / (v * T.sqrt());
let d2 = d1 - v * T.sqrt();
let call = self.s * ((b - self.r) * T).exp() * norm_cdf(d1)
- self.k * (-self.r * T).exp() * norm_cdf(d2);
let put = -self.s * ((b - self.r) * T).exp() * norm_cdf(-d1)
+ self.k * (-self.r * T).exp() * norm_cdf(-d2);
(call, put)
}
fn calculate_price(&self) -> f64 {
self.calculate_call_put().0
}
}
impl TimeExt for AsianPricer {
fn tau(&self) -> Option<f64> {
self.tau
}
fn eval(&self) -> Option<chrono::NaiveDate> {
self.eval
}
fn expiration(&self) -> Option<chrono::NaiveDate> {
self.expiration
}
}