Skip to main content

RainbowOption

Struct RainbowOption 

Source
pub struct RainbowOption {
Show 16 fields pub symbol: String, pub rainbow_type: RainbowType, pub put_or_call: PutOrCall, pub spots: Vec<f64>, pub vols: Vec<f64>, pub dividends: Vec<f64>, pub correlations: Vec<Vec<f64>>, pub strike_price: f64, pub weights: Vec<f64>, pub maturity_date: NaiveDate, pub valuation_date: NaiveDate, pub discount_curve: YieldCurve, pub engine: Engine, pub paths: usize, pub sampler: Sampler, pub seed: u64, /* private fields */
}

Fields§

§symbol: String§rainbow_type: RainbowType§put_or_call: PutOrCall§spots: Vec<f64>§vols: Vec<f64>§dividends: Vec<f64>§correlations: Vec<Vec<f64>>§strike_price: f64§weights: Vec<f64>§maturity_date: NaiveDate§valuation_date: NaiveDate§discount_curve: YieldCurve§engine: Engine§paths: usize§sampler: Sampler§seed: u64

Implementations§

Source§

impl RainbowOption

Source

pub fn from_json(data: &RainbowOptionData) -> Box<RainbowOption>

Examples found in repository?
examples/rainbow_option.rs (lines 44-59)
33fn build(
34    rainbow_type: &str,
35    pc: &str,
36    strike: Option<f64>,
37    rho: f64,
38    pricer: &str,
39    assets: Vec<RainbowAssetData>,
40    correlations: Vec<Vec<f64>>,
41    weights: Option<Vec<f64>>,
42) -> Box<RainbowOption> {
43    let _ = rho;
44    RainbowOption::from_json(&RainbowOptionData {
45        symbol: rainbow_type.to_uppercase(),
46        rainbow_type: rainbow_type.to_string(),
47        put_or_call: Some(pc.to_string()),
48        assets,
49        correlations,
50        strike_price: strike,
51        weights,
52        maturity: maturity_1y(),
53        risk_free_rate: Some(RATE),
54        discount_curve: None,
55        pricer: Some(pricer.to_string()),
56        simulation: Some(100_000),
57        mc_sampler: None,
58        mc_seed: None,
59    })
60}
Source

pub fn time_to_maturity(&self) -> f64

Source

pub fn npv(&self) -> f64

Examples found in repository?
examples/rainbow_option.rs (line 76)
75fn print_rainbow(label: &str, option: &RainbowOption) {
76    let pv = option.npv();
77    let stats = option.npv_with_stats();
78    let deltas: Vec<String> = option.deltas().iter().map(|d| format!("{d:.4}")).collect();
79    let vegas: Vec<String> = option.vegas().iter().map(|v| format!("{v:.2}")).collect();
80    let se = match stats {
81        Some(s) => format!("{:.5}", s.std_err),
82        None => "-".to_string(),
83    };
84    println!(
85        "{label:<38} {pv:>12.6}  stderr={se:>9}  deltas=[{}]  vegas=[{}]",
86        deltas.join(", "),
87        vegas.join(", ")
88    );
89}
90
91fn main() {
92    common::title(&format!(
93        "RAINBOW OPTIONS — A: S={SPOT_A} sigma={VOL_A} q={DIV_A} | B: S={SPOT_B} sigma={VOL_B} q={DIV_B} | r={RATE} T=1y"
94    ));
95
96    common::section("Exchange option (Margrabe, exact) — pays (S_A - S_B)+");
97    print_rainbow("Analytical (Margrabe)", &two_asset("exchange", "C", None, 0.6, "Analytical"));
98    print_rainbow("Monte Carlo", &two_asset("exchange", "C", None, 0.6, "MC"));
99
100    common::section("Spread option (Kirk approximation) — pays (S_A - S_B - K)+");
101    for k in [0.0, 5.0, 10.0] {
102        print_rainbow(
103            &format!("Analytical (Kirk), K={k}"),
104            &two_asset("spread", "C", Some(k), 0.6, "Analytical"),
105        );
106        print_rainbow(
107            &format!("Monte Carlo,     K={k}"),
108            &two_asset("spread", "C", Some(k), 0.6, "MC"),
109        );
110    }
111    common::note("at K=0 the spread option must equal the Margrabe exchange option");
112
113    common::section("Best-of and worst-of (Monte Carlo only)");
114    for k in [90.0, 100.0, 110.0] {
115        print_rainbow(&format!("best-of call,  K={k}"), &two_asset("best_of", "C", Some(k), 0.6, "MC"));
116        print_rainbow(&format!("worst-of call, K={k}"), &two_asset("worst_of", "C", Some(k), 0.6, "MC"));
117    }
118    print_rainbow(
119        "best-of, analytic (unsupported)",
120        &two_asset("best_of", "C", Some(100.0), 0.6, "MC"),
121    );
122
123    common::section("Correlation sweep (worst-of call, K=100)");
124    for rho in [-0.5, 0.0, 0.5, 0.9, 0.99] {
125        print_rainbow(&format!("rho = {rho:>5}"), &two_asset("worst_of", "C", Some(100.0), rho, "MC"));
126    }
127    common::note("higher correlation lifts the minimum, so the worst-of call gains value");
128
129    common::section("Basket option (3 assets, moment matching)");
130    let assets3 = vec![
131        RainbowAssetData { symbol: "AAA".into(), spot: 100.0, volatility: 0.30, dividend: None },
132        RainbowAssetData { symbol: "BBB".into(), spot: 90.0, volatility: 0.25, dividend: None },
133        RainbowAssetData { symbol: "CCC".into(), spot: 110.0, volatility: 0.35, dividend: None },
134    ];
135    let corr3 = vec![
136        vec![1.0, 0.5, 0.3],
137        vec![0.5, 1.0, 0.4],
138        vec![0.3, 0.4, 1.0],
139    ];
140    print_rainbow(
141        "Analytical (moment matching)",
142        &build("basket", "C", Some(100.0), 0.0, "Analytical", assets3.clone(), corr3.clone(), None),
143    );
144    print_rainbow(
145        "Monte Carlo",
146        &build("basket", "C", Some(100.0), 0.0, "MC", assets3.clone(), corr3.clone(), None),
147    );
148    print_rainbow(
149        "Weighted 40/30/30, analytic",
150        &build(
151            "basket",
152            "C",
153            Some(100.0),
154            0.0,
155            "Analytical",
156            assets3,
157            corr3,
158            Some(vec![0.4, 0.3, 0.3]),
159        ),
160    );
161
162    common::section("Identities");
163    let spread_k0 = two_asset("spread", "C", Some(0.0), 0.6, "Analytical").npv();
164    let exchange = two_asset("exchange", "C", None, 0.6, "Analytical").npv();
165    common::check("spread(K=0) = Margrabe", spread_k0, exchange, 1e-10);
166
167    // max + min = S_A + S_B pathwise, so the two options sum to the vanillas
168    let k = 100.0;
169    let best = two_asset("best_of", "C", Some(k), 0.6, "MC").npv();
170    let worst = two_asset("worst_of", "C", Some(k), 0.6, "MC").npv();
171    let vanillas = bs_price(SPOT_A, k, RATE, DIV_A, VOL_A, 1.0, PutOrCall::Call)
172        + bs_price(SPOT_B, k, RATE, DIV_B, VOL_B, 1.0, PutOrCall::Call);
173    common::check("best-of + worst-of = sum of vanillas", best + worst, vanillas, 0.1);
174    println!();
175}
Source

pub fn npv_with_stats(&self) -> Option<McStats>

Examples found in repository?
examples/rainbow_option.rs (line 77)
75fn print_rainbow(label: &str, option: &RainbowOption) {
76    let pv = option.npv();
77    let stats = option.npv_with_stats();
78    let deltas: Vec<String> = option.deltas().iter().map(|d| format!("{d:.4}")).collect();
79    let vegas: Vec<String> = option.vegas().iter().map(|v| format!("{v:.2}")).collect();
80    let se = match stats {
81        Some(s) => format!("{:.5}", s.std_err),
82        None => "-".to_string(),
83    };
84    println!(
85        "{label:<38} {pv:>12.6}  stderr={se:>9}  deltas=[{}]  vegas=[{}]",
86        deltas.join(", "),
87        vegas.join(", ")
88    );
89}
Source

pub fn deltas(&self) -> Vec<f64>

Per-asset spot deltas (central bumps, common random numbers).

Examples found in repository?
examples/rainbow_option.rs (line 78)
75fn print_rainbow(label: &str, option: &RainbowOption) {
76    let pv = option.npv();
77    let stats = option.npv_with_stats();
78    let deltas: Vec<String> = option.deltas().iter().map(|d| format!("{d:.4}")).collect();
79    let vegas: Vec<String> = option.vegas().iter().map(|v| format!("{v:.2}")).collect();
80    let se = match stats {
81        Some(s) => format!("{:.5}", s.std_err),
82        None => "-".to_string(),
83    };
84    println!(
85        "{label:<38} {pv:>12.6}  stderr={se:>9}  deltas=[{}]  vegas=[{}]",
86        deltas.join(", "),
87        vegas.join(", ")
88    );
89}
Source

pub fn vegas(&self) -> Vec<f64>

Per-asset vegas (central bumps of each asset’s vol).

Examples found in repository?
examples/rainbow_option.rs (line 79)
75fn print_rainbow(label: &str, option: &RainbowOption) {
76    let pv = option.npv();
77    let stats = option.npv_with_stats();
78    let deltas: Vec<String> = option.deltas().iter().map(|d| format!("{d:.4}")).collect();
79    let vegas: Vec<String> = option.vegas().iter().map(|v| format!("{v:.2}")).collect();
80    let se = match stats {
81        Some(s) => format!("{:.5}", s.std_err),
82        None => "-".to_string(),
83    };
84    println!(
85        "{label:<38} {pv:>12.6}  stderr={se:>9}  deltas=[{}]  vegas=[{}]",
86        deltas.join(", "),
87        vegas.join(", ")
88    );
89}
Source

pub fn theta(&self) -> f64

Source

pub fn rho(&self) -> f64

Trait Implementations§

Source§

impl Debug for RainbowOption

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V