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: u64Implementations§
Source§impl RainbowOption
impl RainbowOption
Sourcepub fn from_json(data: &RainbowOptionData) -> Box<RainbowOption>
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}pub fn time_to_maturity(&self) -> f64
Sourcepub fn npv(&self) -> f64
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}Sourcepub fn npv_with_stats(&self) -> Option<McStats>
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}Sourcepub fn deltas(&self) -> Vec<f64>
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}Sourcepub fn vegas(&self) -> Vec<f64>
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}pub fn theta(&self) -> f64
pub fn rho(&self) -> f64
Trait Implementations§
Auto Trait Implementations§
impl Freeze for RainbowOption
impl RefUnwindSafe for RainbowOption
impl Send for RainbowOption
impl Sync for RainbowOption
impl Unpin for RainbowOption
impl UnsafeUnpin for RainbowOption
impl UnwindSafe for RainbowOption
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more