Skip to content

Commit fe23aad

Browse files
Fix time spread and flaky strategies (#48)
* Fix covered_call, diagonal_spread and iron_butterfly * Update README.md * Update README and examples * Update README.md * Update tests
1 parent f8a25e7 commit fe23aad

21 files changed

+109
-68
lines changed

README.md

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ Greeks { delta: 0.013645840354947947, gamma: -0.0008813766475726433, theta: 0.17
129129

130130
Quantrs also supports plotting option prices and strategies using the `plotters` backend.
131131

132-
E.g., Plot the P/L of a slightly skewed Condor spread:
132+
E.g., Plot the P/L of a slightly skewed Condor spread using the Monte-Carlo model:
133133

134134
<details>
135135
<summary><i>Click to see example code</i></summary>
@@ -148,24 +148,26 @@ let options = vec![
148148
EuropeanOption::new(instrument.clone(), 115.0, 1.0, Call),
149149
];
150150

151-
// Create a new Black-Scholes model with:
151+
// Create a new Monte-Carlo model with:
152152
// - Risk-free interest rate (r) = 5%
153153
// - Volatility (σ) = 20%
154-
let model = BlackScholesModel::new(0.05, 0.2);
154+
// - Number of simulations = 10,000
155+
// - Number of time steps = 365
156+
let model = MonteCarloModel::geometric(0.05, 0.2, 10_000, 365);
155157

156158
// Plot a breakdown of the Condor spread with a spot price range of [80,120]
157159
model.plot_strategy_breakdown(
158160
"Condor Example",
159161
model.condor(&options[0], &options[1], &options[2], &options[3]),
160162
80.0..120.0,
161-
"path/to/destination.png",
163+
"examples/images/strategy.png",
162164
&options,
163165
);
164166
```
165167

166168
</details>
167169

168-
![condor_strategy](./examples/images/condor.png)
170+
![condor_strategy](./examples/images/strategy.png)
169171

170172
<!--<div align="center">
171173
<img src="https://github.com/user-attachments/assets/0298807f-43ed-4458-9c7d-43b0f70defea" alt="condor_strategy" width="600"/>
@@ -176,7 +178,7 @@ See the [documentation][docs-url] for more information and examples.
176178
## Benchmarks
177179

178180
Compared to other popular and well-maintained (i.e., actively developed, well-documented, and feature-rich) options pricing libraries, quantrs competes well in terms of performance:
179-
E.g., for building and pricing a European call with the Merton Black-Scholes model, quantrs is:
181+
E.g., for pricing a European call with the Merton Black-Scholes model, quantrs is:
180182

181183
- **87x faster** than `py_vollib`
182184
- **29x faster** than `QuantLib` (python bindings)

examples/images/condor.png

-957 KB
Binary file not shown.

examples/images/covered_call.png

507 KB
Loading
843 KB
Loading
796 KB
Loading

examples/images/strategy.png

987 KB
Loading

examples/options_pricing.rs

Lines changed: 18 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,9 @@ fn example_rainbow() {
249249
}
250250

251251
fn example_strategy() {
252-
let model = BlackScholesModel::new(0.0025, 0.15);
252+
// let model = BlackScholesModel::new(0.0025, 0.15);
253+
// let model = MonteCarloModel::geometric(0.05, 0.2, 10_000, 365);
254+
let model = BinomialTreeModel::new(0.05, 0.2, 100);
253255
let instrument = Instrument::new().with_spot(50.0);
254256

255257
////////////////////
@@ -587,32 +589,28 @@ fn example_strategy() {
587589
); // => Calendar Spread: examples/images/calendar_spread_strategy.png
588590

589591
let options = vec![
590-
EuropeanOption::new(instrument.clone(), 60.0, 1.0 / 12.0, Call),
591-
EuropeanOption::new(instrument.clone(), 75.0, 2.0 / 12.0, Call),
592-
EuropeanOption::new(instrument.clone(), 60.0, 1.0 / 12.0, Call),
592+
EuropeanOption::new(Instrument::new().with_spot(48.0), 49.0, 1.0 / 12.0, Call),
593+
EuropeanOption::new(Instrument::new().with_spot(48.0), 49.0, 1.0 / 12.0, Call),
594+
EuropeanOption::new(Instrument::new().with_spot(48.0), 50.0, 2.0 / 12.0, Call),
593595
];
594596
let _ = model.plot_strategy_breakdown(
595597
"Diagonal Spread",
596598
model.diagonal_spread(&options[0], &options[1], &options[2]),
597-
20.0..80.0,
599+
40.0..60.0,
598600
"examples/images/diagonal_spread_strategy.png",
599601
&options,
600-
); // => Diagonal Spread: examples/images/diagonal_spread_strategy.png
602+
); //model.diagonal_spread(&options[0], &options[1], &options[2])(50.0);
601603
}
602604

603605
fn example_plots() {
604-
// Create a new plotter and plot the option prices
605-
// let plotter = Plotter::new();
606-
// let _ = plotter.plot_option_prices(
607-
// "Binary Call Option",
608-
// instrument,
609-
// 80.0..120.0,
610-
// 0.1..1.0,
611-
// 0.1,
612-
// Call,
613-
// |k, t| BinaryOption::cash_or_nothing(instrument.clone(), k, t, Call),
614-
// "path/to/destination.png",
615-
// );
606+
// Create a new Monte-Carlo model with:
607+
// - Risk-free interest rate (r) = 5%
608+
// - Volatility (σ) = 20%
609+
// - Number of simulations = 10,000
610+
// - Number of time steps = 365
611+
let model = MonteCarloModel::geometric(0.05, 0.2, 10_000, 365);
612+
613+
// Create a new instrument with a spot price of 100 and a dividend yield of 2%
616614
let instrument = Instrument::new().with_spot(100.0).with_cont_yield(0.02);
617615

618616
// Create a vector of European call options with different strike prices
@@ -623,16 +621,12 @@ fn example_plots() {
623621
EuropeanOption::new(instrument.clone(), 115.0, 1.0, Call),
624622
];
625623

626-
// Create a new Black-Scholes model with:
627-
// - Risk-free interest rate (r) = 5%
628-
// - Volatility (σ) = 20%
629-
let model = BlackScholesModel::new(0.05, 0.2);
630-
624+
// Plot a breakdown of the Condor spread with a spot price range of [80,120]
631625
let _ = model.plot_strategy_breakdown(
632626
"Condor Example",
633627
model.condor(&options[0], &options[1], &options[2], &options[3]),
634628
80.0..120.0,
635-
"examples/images/condor.png",
629+
"examples/images/strategy.png",
636630
&options,
637631
);
638632
}

src/options/models/binomial_tree.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@
7272
//! println!("Option price: {}", price);
7373
//! ```
7474
75-
use crate::options::{Option, OptionPricing, OptionStyle};
75+
use crate::options::{Option, OptionPricing, OptionStrategy, OptionStyle};
7676

7777
/// Binomial tree option pricing model.
7878
#[derive(Debug, Default)]
@@ -150,3 +150,5 @@ impl OptionPricing for BinomialTreeModel {
150150
panic!("BinomialTreeModel does not support implied volatility calculation yet");
151151
}
152152
}
153+
154+
impl OptionStrategy for BinomialTreeModel {}

src/options/models/black_76.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Module for Black76 option pricing model.
22
3-
use crate::options::{Option, OptionPricing};
3+
use crate::options::{Option, OptionPricing, OptionStrategy};
44

55
/// Black76 option pricing model.
66
#[derive(Debug, Default)]
@@ -33,3 +33,5 @@ impl OptionPricing for Black76Model {
3333
panic!("Black76Model does not support implied volatility calculation yet");
3434
}
3535
}
36+
37+
impl OptionStrategy for Black76Model {}

src/options/models/finite_diff.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Module for finite difference option pricing model.
22
3-
use crate::options::{Option, OptionPricing};
3+
use crate::options::{Option, OptionPricing, OptionStrategy};
44

55
/// Finite difference option pricing model.
66
#[derive(Debug, Default)]
@@ -33,3 +33,5 @@ impl OptionPricing for FiniteDiffModel {
3333
panic!("FiniteDiffModel does not support implied volatility calculation yet");
3434
}
3535
}
36+
37+
impl OptionStrategy for FiniteDiffModel {}

0 commit comments

Comments
 (0)