use super::bsm::Option;
extern crate nalgebra as na;
use na::*;
use rand::thread_rng;
use rand_distr::{Distribution, Normal, NormalError};
use std::cmp;
extern crate docify;
#[doc = docify::embed!("src/option_price/binomial_tree.rs", test_bintree)]
impl Option {
pub fn gen_bintree(&self, sigma: f64, steps: usize) -> (DMatrix<f64>, DMatrix<f64>) {
let dt = self.T / steps as f64;
let u = (sigma * dt.sqrt()).exp();
let d = 1.0 / u;
let p = (((self.r - self.divdend) * dt).exp() - d) / (u - d);
let mut prices = na::DMatrix::<f64>::new_random(steps, steps);
let mut options = na::DMatrix::<f64>::new_random(steps, steps);
for i in 0..steps {
for j in 0..i + 1 {
let v = self.S * u.powf((i - j) as f64) * d.powf(j as f64);
prices[(i, j)] = v;
if self.is_call {
options[(i, j)] = if (v - self.K) > 0. { v - self.K } else { 0. };
} else {
options[(i, j)] = if (self.K - v) > 0. { self.K - v } else { 0. };
}
}
}
(prices, options)
}
pub fn bintree_price(&self, sigma: f64, steps: usize) -> f64 {
let dt = self.T / steps as f64;
let u = (sigma * dt.sqrt()).exp();
let d = 1.0 / u;
let p = ((self.r * dt).exp() - d) / (u - d);
let (prices, mut options) = self.gen_bintree(sigma, steps);
for i in (0..steps - 1).rev() {
for j in 0..i + 1 {
options[(i, j)] = (p * options[(i + 1, j)] + (1. - p) * options[(i + 1, j + 1)])
* (-self.r * dt).exp();
}
}
options[(0, 0)]
}
}
#[test]
#[docify::export]
fn test_bintree() {
let op = Option {
is_call: true,
S: 217.36, K: 220.0, T: 13.0 / 365.0,
divdend: 0.44 / 100.0, r: 4.62 / 100.0, };
let sigma = 35.23 / 100.0;
let steps = 100;
let a = &op.bintree_price(sigma, steps);
}