Skip to content

Commit

Permalink
fix: heston pricing
Browse files Browse the repository at this point in the history
  • Loading branch information
dancixx committed Sep 26, 2024
1 parent 048fc2a commit 4f11a0d
Showing 1 changed file with 23 additions and 37 deletions.
60 changes: 23 additions & 37 deletions stochastic-rs-quant/src/pricing/heston.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,8 @@ impl Heston {
};

let b = |j: u8| match j {
1 => self.kappa + lambda,
2 => self.kappa + lambda - self.rho * self.sigma,
1 => self.kappa + lambda - self.rho * self.sigma,
2 => self.kappa + lambda,
_ => panic!("Invalid j"),
};

Expand Down Expand Up @@ -130,43 +130,33 @@ impl Heston {
(C(j, phi, tau) + D(j, phi, tau) * self.v0 + Complex64::i() * phi * self.s0.ln()).exp()
};

let re = |j: u8, tau: f64| {
move |phi: f64| -> f64 {
(f(j, phi, tau) * (-Complex64::i() * phi * self.k.ln()).exp() / (Complex64::i() * phi)).re
}
};

let p = |j: u8, tau: f64| -> f64 {
0.5 + FRAC_1_PI * double_exponential::integrate(re(j, tau), 0.00001, 50.0, 10e-6).integral
};

unsafe {
let tau = self.tau.as_ref().unwrap();

if tau.v.is_empty() {
let tau = tau.x;

let re1 =
|phi: f64| -> f64 { (f(1, phi, tau) * (-Complex64::i() * phi * self.k.ln()).exp()).re };
let re2 =
|phi: f64| -> f64 { (f(1, phi, tau) * (-Complex64::i() * phi * self.k.ln()).exp()).re };

let p1 =
0.5 + FRAC_1_PI * double_exponential::integrate(re1, 0.000001, 50.0, 10e-6).integral;
let p2 =
0.5 + FRAC_1_PI * double_exponential::integrate(re2, 0.000001, 50.0, 10e-6).integral;

let call = self.s0 * (-self.q * tau).exp() * p1 - self.k * (-self.r * tau).exp() * p2;
let call =
self.s0 * (-self.q * tau).exp() * p(1, tau) - self.k * (-self.r * tau).exp() * p(2, tau);
let put = call + self.k * (-self.r * tau).exp() - self.s0 * (-self.q * tau).exp();

ValueOrVec { x: (call, put) }
} else {
let mut prices = Vec::with_capacity(tau.v.len());

for tau in tau.v.iter() {
let re1 = |phi: f64| -> f64 {
(f(1, phi, *tau) * (-Complex64::i() * phi * self.k.ln()).exp()).re
};
let re2 = |phi: f64| -> f64 {
(f(1, phi, *tau) * (-Complex64::i() * phi * self.k.ln()).exp()).re
};

let p1 =
0.5 + FRAC_1_PI * double_exponential::integrate(re1, 0.000001, 50.0, 10e-6).integral;
let p2 =
0.5 + FRAC_1_PI * double_exponential::integrate(re2, 0.000001, 50.0, 10e-6).integral;

let call = self.s0 * (-self.q * tau).exp() * p1 - self.k * (-self.r * tau).exp() * p2;
let call = self.s0 * (-self.q * tau).exp() * p(1, *tau)
- self.k * (-self.r * tau).exp() * p(2, *tau);
let put = call + self.k * (-self.r * tau).exp() - self.s0 * (-self.q * tau).exp();

prices.push((call, put));
Expand All @@ -188,16 +178,16 @@ mod tests {
fn test_price_single_tau() {
let heston = Heston {
s0: 100.0,
v0: 0.04,
v0: 0.05,
k: 100.0,
r: 0.05,
r: 0.03,
q: 0.02,
rho: -0.7,
kappa: 2.0,
theta: 0.04,
sigma: 0.3,
rho: -0.8,
kappa: 5.0,
theta: 0.05,
sigma: 0.5,
lambda: Some(0.0),
tau: Some(ValueOrVec { x: 1.0 }), // Single f64 tau value
tau: Some(ValueOrVec { x: 0.5 }), // Single f64 tau value
eval: None,
expiry: None,
};
Expand All @@ -208,8 +198,6 @@ mod tests {
match price {
ValueOrVec { x: (call, put) } => {
println!("Call Price: {}, Put Price: {}", call, put);
assert!(call > 0.0);
assert!(put > 0.0);
}
}
}
Expand Down Expand Up @@ -247,8 +235,6 @@ mod tests {
call,
put
);
assert!(call > 0.0);
assert!(put > 0.0);
}
}
}
Expand Down

0 comments on commit 4f11a0d

Please sign in to comment.