pub use self::bonds::{bootstrap, YtMMethod, BondType, Bond};
pub use self::derivatives::{
minimum_variance_hedge_ratio, black_scholes_formula, ContractType, OptionType, BlackScholesType, OptionPricingMethod, PresentValueSurface, Contract,
OptionContract,
};
pub use self::rates_and_swaps::ForwardRateAgreement;
pub use self::stocks::{QuoteValues, StockValuationType, ValuationByComparablesParams, Stock};
pub mod bonds;
pub mod derivatives;
pub mod rates_and_swaps;
pub mod stocks;
use ndarray::Array1;
#[cfg(feature = "serde")]
use serde::{Serialize, Deserialize};
#[cfg(feature = "plotly")]
use plotly::{Plot, Scatter, Layout, layout::Axis};
use crate::error::{DigiFiError, ErrorTitle};
use crate::portfolio_applications::AssetHistData;
use crate::stochastic_processes::StochasticProcess;
#[derive(Clone, Copy, Debug)]
pub enum FinancialInstrumentType {
CashInstrument,
DerivativeInstrument,
}
#[derive(Clone, Copy, Debug)]
pub enum AssetClass {
DebtBasedInstrument,
EquityBasedInstrument,
ForeignExchangeInstrument,
}
#[derive(Clone, Debug)]
pub struct FinancialInstrumentId {
pub instrument_type: FinancialInstrumentType,
pub asset_class: AssetClass,
pub identifier: String,
}
pub trait FinancialInstrument {
fn present_value(&self) -> Result<f64, DigiFiError>;
fn net_present_value(&self) -> Result<f64, DigiFiError>;
fn future_value(&self) -> Result<f64, DigiFiError>;
fn historical_data(&self) -> &AssetHistData;
fn update_historical_data(&mut self, new_data: &AssetHistData) -> ();
fn stochastic_model(&mut self) -> &mut Option<Box<dyn StochasticProcess>>;
fn update_n_stochastic_paths(&mut self, n_paths: usize) -> () {
if let Some(sm) = self.stochastic_model() { sm.update_n_paths(n_paths); }
}
fn stochastic_simulation(&mut self) -> Result<Option<Vec<Array1<f64>>>, DigiFiError> {
let paths: Vec<Array1<f64>> = match self.stochastic_model() {
Some(sm) => sm.get_paths()?,
None => return Ok(None),
};
Ok(Some(paths))
}
fn generate_historic_data(&mut self, in_place: bool) -> Result<Option<AssetHistData>, DigiFiError> {
match self.stochastic_model() {
Some(sm) => {
let prices: Array1<f64> = sm.get_paths()?.remove(0);
let length: usize = prices.len();
let new_data: AssetHistData = AssetHistData::build(
prices, Array1::from_vec(vec![0.0; length]), self.historical_data().time.clone(),
)?;
if in_place {
self.update_historical_data(&new_data);
}
Ok(Some(new_data))
},
None => Ok(None)
}
}
}
pub trait PayoffClone {
fn clone_box(&self) -> Box<dyn Payoff>;
}
impl<T> PayoffClone for T
where
T: 'static + Payoff + Clone,
{
fn clone_box(&self) -> Box<dyn Payoff> {
Box::new(self.clone())
}
}
pub trait Payoff: PayoffClone {
fn payoff(&self, s: f64) -> f64;
fn payoff_iter(&self, s: &Array1<f64>) -> Array1<f64> {
s.map(|s| self.payoff(*s) )
}
fn validate_payoff(&self, val_length: usize) -> Result<(), DigiFiError> {
let s: Array1<f64> = Array1::from_vec(vec![1.0; val_length]);
let result: Array1<f64> = self.payoff_iter(&s);
if result.len() != val_length {
return Err(DigiFiError::CustomFunctionLengthVal { title: "Validate Payoff".to_owned(), });
}
Ok(())
}
fn profit(&self, s: f64) -> f64;
fn profit_iter(&self, s: &Array1<f64>) -> Array1<f64> {
s.map(|s| self.profit(*s) )
}
fn update_cost(&mut self, new_cost: f64) -> ();
}
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct LongCall {
pub k: f64,
pub cost: f64,
}
impl Payoff for LongCall {
fn payoff(&self, s: f64) -> f64 {
(s - self.k).max(0.0)
}
fn profit(&self, s: f64) -> f64 {
self.payoff(s) - self.cost
}
fn update_cost(&mut self, new_cost: f64) -> () {
self.cost = new_cost;
}
}
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct ShortCall {
pub k: f64,
pub cost: f64,
}
impl Payoff for ShortCall {
fn payoff(&self, s: f64) -> f64 {
(self.k - s).min(0.0)
}
fn profit(&self, s: f64) -> f64 {
self.payoff(s) + self.cost
}
fn update_cost(&mut self, new_cost: f64) -> () {
self.cost = new_cost;
}
}
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct LongPut {
pub k: f64,
pub cost: f64,
}
impl Payoff for LongPut {
fn payoff(&self, s: f64) -> f64 {
(self.k - s).max(0.0)
}
fn profit(&self, s: f64) -> f64 {
self.payoff(s) - self.cost
}
fn update_cost(&mut self, new_cost: f64) -> () {
self.cost = new_cost;
}
}
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct ShortPut {
pub k: f64,
pub cost: f64,
}
impl Payoff for ShortPut {
fn payoff(&self, s: f64) -> f64 {
(s - self.k).min(0.0)
}
fn profit(&self, s: f64) -> f64 {
self.payoff(s) + self.cost
}
fn update_cost(&mut self, new_cost: f64) -> () {
self.cost = new_cost;
}
}
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct BullCollar {
k_p: f64,
k_c: f64,
cost: f64,
cost_s: f64,
}
impl BullCollar {
pub fn build(k_p: f64, k_c: f64, cost: f64, cost_s: f64) -> Result<Self, DigiFiError> {
if k_c < k_p {
return Err(DigiFiError::ParameterConstraint {
title: Self::error_title(),
constraint: "The argument `k_p` must be smaller or equal to `k_c`.".to_owned(),
});
}
Ok(Self { k_p, k_c, cost, cost_s })
}
}
impl ErrorTitle for BullCollar {
fn error_title() -> String {
String::from("Bull Collar")
}
}
impl Payoff for BullCollar {
fn payoff(&self, s: f64) -> f64 {
s - self.cost_s + (self.k_p - s).max(0.0) + (self.k_c - s).min(0.0)
}
fn profit(&self, s: f64) -> f64 {
self.payoff(s) - self.cost
}
fn update_cost(&mut self, new_cost: f64) -> () {
self.cost = new_cost;
}
}
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct BearCollar {
k_p: f64,
k_c: f64,
cost: f64,
cost_s: f64,
}
impl BearCollar {
pub fn build(k_p: f64, k_c: f64, cost: f64, cost_s: f64) -> Result<Self, DigiFiError> {
if k_c < k_p {
return Err(DigiFiError::ParameterConstraint {
title: Self::error_title(),
constraint: "The argument `k_p` must be smaller or equal to `k_c`.".to_owned(),
});
}
Ok(Self { k_p, k_c, cost, cost_s })
}
}
impl ErrorTitle for BearCollar {
fn error_title() -> String {
String::from("Bear Collar")
}
}
impl Payoff for BearCollar {
fn payoff(&self, s: f64) -> f64 {
self.cost_s - s + (s - self.k_p).min(0.0) + (s - self.k_c).max(0.0)
}
fn profit(&self, s: f64) -> f64 {
self.payoff(s) - self.cost
}
fn update_cost(&mut self, new_cost: f64) -> () {
self.cost = new_cost;
}
}
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct BullSpread {
k_l: f64,
k_s: f64,
cost: f64,
}
impl BullSpread {
pub fn build(k_l: f64, k_s: f64, cost: f64) -> Result<Self, DigiFiError> {
if k_s < k_l {
return Err(DigiFiError::ParameterConstraint {
title: Self::error_title(),
constraint: "The argument `k_l` must be smaller or equal to `k_s`.".to_owned(),
});
}
Ok(Self { k_l, k_s, cost })
}
}
impl ErrorTitle for BullSpread {
fn error_title() -> String {
String::from("Bull Spread")
}
}
impl Payoff for BullSpread {
fn payoff(&self, s: f64) -> f64 {
(s - self.k_l).max(0.0) + (self.k_s - s).min(0.0)
}
fn profit(&self, s: f64) -> f64 {
self.payoff(s) - self.cost
}
fn update_cost(&mut self, new_cost: f64) -> () {
self.cost = new_cost;
}
}
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct BearSpread {
k_l: f64,
k_s: f64,
cost: f64,
}
impl BearSpread {
pub fn build(k_l: f64, k_s: f64, cost: f64) -> Result<Self, DigiFiError> {
if k_l < k_s {
return Err(DigiFiError::ParameterConstraint {
title: Self::error_title(),
constraint: "The argument `k_s` must be smaller or equal to `k_l`.".to_owned(),
});
}
Ok(Self { k_l, k_s, cost })
}
}
impl ErrorTitle for BearSpread {
fn error_title() -> String {
String::from("Bear Spread")
}
}
impl Payoff for BearSpread {
fn payoff(&self, s: f64) -> f64 {
(self.k_l - s).max(0.0) + (s - self.k_s).min(0.0)
}
fn profit(&self, s: f64) -> f64 {
self.payoff(s) - self.cost
}
fn update_cost(&mut self, new_cost: f64) -> () {
self.cost = new_cost;
}
}
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct LongButterfly {
k1_c: f64,
k2_c: f64,
k_p: f64,
cost: f64,
}
impl LongButterfly {
pub fn build(k1_c: f64, k2_c: f64, k_p: f64, cost: f64) -> Result<Self, DigiFiError> {
if k2_c < k_p {
return Err(DigiFiError::ParameterConstraint {
title: Self::error_title(),
constraint: "The argument `k_p` must be smaller or equal to `k1_c`.".to_owned(),
});
}
if k_p < k1_c {
return Err(DigiFiError::ParameterConstraint {
title: Self::error_title(),
constraint: "The argument `k1_c` must be smaller or equal to `k_p`.".to_owned(),
});
}
Ok(Self { k1_c, k2_c, k_p, cost })
}
}
impl ErrorTitle for LongButterfly {
fn error_title() -> String {
String::from("Long Butterfly")
}
}
impl Payoff for LongButterfly {
fn payoff(&self, s: f64) -> f64 {
(s - self.k1_c).max(0.0) + 2.0*(self.k_p - s).min(0.0) + (s - self.k2_c).max(0.0)
}
fn profit(&self, s: f64) -> f64 {
self.payoff(s) - self.cost
}
fn update_cost(&mut self, new_cost: f64) -> () {
self.cost = new_cost;
}
}
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct BoxSpread {
k_1: f64,
k_2: f64,
cost: f64,
}
impl BoxSpread {
pub fn build(k_1: f64, k_2: f64, cost: f64) -> Result<Self, DigiFiError> {
if k_2 < k_1 {
return Err(DigiFiError::ParameterConstraint {
title: Self::error_title(),
constraint: "The argument `k_1` must be smaller or equal to `k_2`.".to_owned(),
});
}
Ok(Self { k_1, k_2, cost })
}
}
impl ErrorTitle for BoxSpread {
fn error_title() -> String {
String::from("Box Spread")
}
}
impl Payoff for BoxSpread {
fn payoff(&self, s: f64) -> f64 {
(s - self.k_1).max(0.0) + (self.k_2 - s).min(0.0) + (self.k_2 - s).max(0.0) + (s - self.k_1).min(0.0)
}
fn profit(&self, s: f64) -> f64 {
self.payoff(s) - self.cost
}
fn update_cost(&mut self, new_cost: f64) -> () {
self.cost = new_cost;
}
}
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Straddle {
pub k: f64,
pub cost: f64,
}
impl Payoff for Straddle {
fn payoff(&self, s: f64) -> f64 {
(s - self.k).max(0.0) + (self.k - s).max(0.0)
}
fn profit(&self, s: f64) -> f64 {
self.payoff(s) - self.cost
}
fn update_cost(&mut self, new_cost: f64) -> () {
self.cost = new_cost;
}
}
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Strangle {
k_c: f64,
k_p: f64,
cost: f64,
}
impl Strangle {
pub fn build(k_c: f64, k_p: f64, cost: f64) -> Result<Self, DigiFiError> {
if k_c <= k_p {
return Err(DigiFiError::ParameterConstraint {
title: Self::error_title(),
constraint: "The argument `k_p` must be smaller than `k_c`.".to_owned(),
});
}
Ok(Self { k_c, k_p, cost })
}
}
impl ErrorTitle for Strangle {
fn error_title() -> String {
String::from("Strangle")
}
}
impl Payoff for Strangle {
fn payoff(&self, s: f64) -> f64 {
(s - self.k_c).max(0.0) + (self.k_p - s).max(0.0)
}
fn profit(&self, s: f64) -> f64 {
self.payoff(s) - self.cost
}
fn update_cost(&mut self, new_cost: f64) -> () {
self.cost = new_cost;
}
}
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Strip {
pub k: f64,
pub cost: f64,
}
impl Payoff for Strip {
fn payoff(&self, s: f64) -> f64 {
(s - self.k).max(0.0) + 2.0*(self.k - s).max(0.0)
}
fn profit(&self, s: f64) -> f64 {
self.payoff(s) - self.cost
}
fn update_cost(&mut self, new_cost: f64) -> () {
self.cost = new_cost;
}
}
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Strap {
pub k: f64,
pub cost: f64,
}
impl Payoff for Strap {
fn payoff(&self, s: f64) -> f64 {
2.0*(s - self.k).max(0.0) + (self.k - s).max(0.0)
}
fn profit(&self, s: f64) -> f64 {
self.payoff(s) - self.cost
}
fn update_cost(&mut self, new_cost: f64) -> () {
self.cost = new_cost;
}
}
#[cfg(feature = "plotly")]
pub fn plot_payoff(payoff_obj: &impl Payoff, start_price: f64, stop_price: f64, n_points: usize) -> Plot {
let prices: Array1<f64> = Array1::linspace(start_price, stop_price, n_points);
let payoff: Array1<f64> = payoff_obj.payoff_iter(&prices);
let mut plot: Plot = Plot::new();
plot.add_trace(Scatter::new(prices.to_vec(), payoff.to_vec()));
let x_axis: Axis = Axis::new().title("Price at Maturity");
let y_axis: Axis = Axis::new().title("Payoff at Maturity");
let layout: Layout = Layout::new().title("<b>Payoff Plot</b>").x_axis(x_axis).y_axis(y_axis);
plot.set_layout(layout);
plot
}
#[cfg(feature = "plotly")]
pub fn plot_profit(payoff_obj: &impl Payoff, start_price: f64, stop_price: f64, n_points: usize) -> Plot {
let prices: Array1<f64> = Array1::linspace(start_price, stop_price, n_points);
let profit: Array1<f64> = payoff_obj.profit_iter(&prices);
let mut plot: Plot = Plot::new();
plot.add_trace(Scatter::new(prices.to_vec(), profit.to_vec()));
let x_axis: Axis = Axis::new().title("Price at Maturity");
let y_axis: Axis = Axis::new().title("Profit at Maturity");
let layout: Layout = Layout::new().title("<b>Profit Plot</b>").x_axis(x_axis).y_axis(y_axis);
plot.set_layout(layout);
plot
}
#[cfg(test)]
mod tests {
use ndarray::{Array1, array};
#[cfg(feature = "plotly")]
use plotly::Plot;
use crate::utilities::TEST_ACCURACY;
use crate::financial_instruments::Payoff;
#[test]
fn unit_test_long_call() -> () {
use crate::financial_instruments::LongCall;
let s: Array1<f64> = array![10.0, 9.0, 13.0];
let long_call: LongCall = LongCall { k: 10.0, cost: 1.0 };
assert!((long_call.payoff_iter(&s) - Array1::from_vec(vec![0.0, 0.0, 3.0])).map(|v| v.abs() ).sum() < TEST_ACCURACY);
}
#[test]
fn unit_test_short_call() -> () {
use crate::financial_instruments::ShortCall;
let s: Array1<f64> = array![10.0, 9.0, 13.0];
let short_call: ShortCall = ShortCall { k: 10.0, cost: 1.0 };
assert!((short_call.payoff_iter(&s) - Array1::from_vec(vec![0.0, 0.0, -3.0])).map(|v| v.abs() ).sum() < TEST_ACCURACY);
}
#[test]
fn unit_test_long_put() -> () {
use crate::financial_instruments::LongPut;
let s: Array1<f64> = array![10.0, 9.0, 13.0];
let long_put: LongPut = LongPut { k: 10.0, cost: 1.0 };
assert!((long_put.payoff_iter(&s) - Array1::from_vec(vec![0.0, 1.0, 0.0])).map(|v| v.abs() ).sum() < TEST_ACCURACY);
}
#[test]
fn unit_test_short_put() -> () {
use crate::financial_instruments::ShortPut;
let s: Array1<f64> = array![10.0, 9.0, 13.0];
let short_put: ShortPut = ShortPut { k: 10.0, cost: 1.0 };
assert!((short_put.payoff_iter(&s) - Array1::from_vec(vec![0.0, -1.0, 0.0])).map(|v| v.abs() ).sum() < TEST_ACCURACY);
}
#[test]
fn unit_test_bull_collar() -> () {
use crate::financial_instruments::BullCollar;
let s: Array1<f64> = Array1::range(3.0, 7.0, 0.5);
let bull_collar: BullCollar = BullCollar::build(4.0, 6.0, 0.0, 5.0).unwrap();
assert!((bull_collar.payoff_iter(&s) - Array1::from_vec(vec![-1.0, -1.0, -1.0, -0.5, 0.0, 0.5, 1.0, 1.0])).map(|v| v.abs() ).sum() < TEST_ACCURACY);
}
#[test]
fn unit_test_bear_collar() -> () {
use crate::financial_instruments::BearCollar;
let s: Array1<f64> = Array1::range(3.0, 7.0, 0.5);
let bear_collar: BearCollar = BearCollar::build(4.0, 6.0, 0.0, 5.0).unwrap();
assert!((bear_collar.payoff_iter(&s) - Array1::from_vec(vec![1.0, 1.0, 1.0, 0.5, 0.0, -0.5, -1.0, -1.0])).map(|v| v.abs() ).sum() < TEST_ACCURACY);
}
#[test]
fn unit_test_bull_spread() -> () {
use crate::financial_instruments::BullSpread;
let s: Array1<f64> = Array1::from_vec(vec![3.0, 4.0, 5.0, 6.0, 7.0]);
let bull_spread: BullSpread = BullSpread::build(4.0, 6.0, 1.0).unwrap();
assert!((bull_spread.payoff_iter(&s) - Array1::from_vec(vec![0.0, 0.0, 1.0, 2.0, 2.0])).map(|v| v.abs() ).sum() < TEST_ACCURACY);
}
#[test]
fn unit_test_bear_spread() -> () {
use crate::financial_instruments::BearSpread;
let s: Array1<f64> = Array1::from_vec(vec![3.0, 4.0, 5.0, 6.0, 7.0]);
let bear_spread: BearSpread = BearSpread::build(6.0, 4.0, 1.0).unwrap();
assert!((bear_spread.payoff_iter(&s) - Array1::from_vec(vec![2.0, 2.0, 1.0, 0.0, 0.0])).map(|v| v.abs() ).sum() < TEST_ACCURACY);
}
#[test]
fn unit_test_long_butterfly() -> () {
use crate::financial_instruments::LongButterfly;
let s: Array1<f64> = Array1::from_vec(vec![3.0, 4.0, 5.0, 6.0, 7.0]);
let long_butterfly: LongButterfly = LongButterfly::build(4.0, 6.0, 5.0, 1.0).unwrap();
assert!((long_butterfly.payoff_iter(&s) - Array1::from_vec(vec![0.0, 0.0, 1.0, 0.0, 0.0])).map(|v| v.abs() ).sum() < TEST_ACCURACY);
}
#[test]
fn unit_test_box_spread() -> () {
use crate::financial_instruments::BoxSpread;
let s: Array1<f64> = Array1::from_vec(vec![3.0, 4.0, 5.0, 6.0, 7.0]);
let box_spread: BoxSpread = BoxSpread::build(4.0, 6.0, 1.0).unwrap();
assert!((box_spread.payoff_iter(&s) - Array1::from_vec(vec![2.0, 2.0, 2.0, 2.0, 2.0])).map(|v| v.abs() ).sum() < TEST_ACCURACY);
}
#[test]
fn unit_test_straddle() -> () {
use crate::financial_instruments::Straddle;
let s: Array1<f64> = Array1::from_vec(vec![3.0, 4.0, 5.0, 6.0, 7.0]);
let straddle: Straddle = Straddle { k: 5.0, cost: 1.0 };
assert!((straddle.payoff_iter(&s) - Array1::from_vec(vec![2.0, 1.0, 0.0, 1.0, 2.0])).map(|v| v.abs() ).sum() < TEST_ACCURACY);
}
#[test]
fn unit_test_strangle() -> () {
use crate::financial_instruments::Strangle;
let s: Array1<f64> = Array1::from_vec(vec![3.0, 4.0, 5.0, 6.0, 7.0]);
let strangle: Strangle = Strangle::build(6.0, 4.0, 1.0).unwrap();
assert!((strangle.payoff_iter(&s) - Array1::from_vec(vec![1.0, 0.0, 0.0, 0.0, 1.0])).map(|v| v.abs() ).sum() < TEST_ACCURACY);
}
#[test]
fn unit_test_strip() -> () {
use crate::financial_instruments::Strip;
let s: Array1<f64> = Array1::from_vec(vec![3.0, 4.0, 5.0, 6.0, 7.0]);
let strip: Strip = Strip { k: 5.0, cost: 1.0 };
assert!((strip.payoff_iter(&s) - Array1::from_vec(vec![4.0, 2.0, 0.0, 1.0, 2.0])).map(|v| v.abs() ).sum() < TEST_ACCURACY);
}
#[test]
fn unit_test_strap() -> () {
use crate::financial_instruments::Strap;
let s: Array1<f64> = Array1::from_vec(vec![3.0, 4.0, 5.0, 6.0, 7.0]);
let strap: Strap = Strap { k: 5.0, cost: 1.0 };
assert!((strap.payoff_iter(&s) - Array1::from_vec(vec![2.0, 1.0, 0.0, 2.0, 4.0])).map(|v| v.abs() ).sum() < TEST_ACCURACY);
}
#[cfg(feature = "plotly")]
#[test]
#[ignore]
fn unit_test_long_call_plot() -> () {
use crate::financial_instruments::{LongCall, plot_payoff, plot_profit};
let payoff_obj: LongCall = LongCall { k: 50.0, cost: 1.0 };
let payoff_plot: Plot = plot_payoff(&payoff_obj, 30.0, 70.0, 41);
payoff_plot.show();
let profit_plot: Plot = plot_profit(&payoff_obj, 30.0, 70.0, 41);
profit_plot.show();
}
#[cfg(feature = "plotly")]
#[test]
#[ignore]
fn unit_test_short_call_plot() -> () {
use crate::financial_instruments::{ShortCall, plot_payoff, plot_profit};
let payoff_obj: ShortCall = ShortCall { k: 50.0, cost: 1.0 };
let payoff_plot: Plot = plot_payoff(&payoff_obj, 30.0, 70.0, 41);
payoff_plot.show();
let profit_plot: Plot = plot_profit(&payoff_obj, 30.0, 70.0, 41);
profit_plot.show();
}
#[cfg(feature = "plotly")]
#[test]
#[ignore]
fn unit_test_long_put_plot() -> () {
use crate::financial_instruments::{LongPut, plot_payoff, plot_profit};
let payoff_obj: LongPut = LongPut { k: 50.0, cost: 1.0 };
let payoff_plot: Plot = plot_payoff(&payoff_obj, 30.0, 70.0, 41);
payoff_plot.show();
let profit_plot: Plot = plot_profit(&payoff_obj, 30.0, 70.0, 41);
profit_plot.show();
}
#[cfg(feature = "plotly")]
#[test]
#[ignore]
fn unit_test_short_put_plot() -> () {
use crate::financial_instruments::{ShortPut, plot_payoff, plot_profit};
let payoff_obj: ShortPut = ShortPut { k: 50.0, cost: 1.0 };
let payoff_plot: Plot = plot_payoff(&payoff_obj, 30.0, 70.0, 41);
payoff_plot.show();
let profit_plot: Plot = plot_profit(&payoff_obj, 30.0, 70.0, 41);
profit_plot.show();
}
#[cfg(feature = "plotly")]
#[test]
#[ignore]
fn unit_test_bull_collar_plot() -> () {
use crate::financial_instruments::{BullCollar, plot_payoff, plot_profit};
let payoff_obj: BullCollar = BullCollar::build(4.0, 6.0, 1.0, 5.0).unwrap();
let payoff_plot: Plot = plot_payoff(&payoff_obj, 0.0, 10.0, 21);
payoff_plot.show();
let profit_plot: Plot = plot_profit(&payoff_obj, 0.0, 10.0, 21);
profit_plot.show();
}
#[cfg(feature = "plotly")]
#[test]
#[ignore]
fn unit_test_bear_collar_plot() -> () {
use crate::financial_instruments::{BearCollar, plot_payoff, plot_profit};
let payoff_obj: BearCollar = BearCollar::build(4.0, 6.0, 1.0, 5.0).unwrap();
let payoff_plot: Plot = plot_payoff(&payoff_obj, 0.0, 10.0, 21);
payoff_plot.show();
let profit_plot: Plot = plot_profit(&payoff_obj, 0.0, 10.0, 21);
profit_plot.show();
}
#[cfg(feature = "plotly")]
#[test]
#[ignore]
fn unit_test_bull_spread_plot() -> () {
use crate::financial_instruments::{BullSpread, plot_payoff, plot_profit};
let payoff_obj: BullSpread = BullSpread::build(4.0, 6.0, 1.0).unwrap();
let payoff_plot: Plot = plot_payoff(&payoff_obj, 0.0, 10.0, 21);
payoff_plot.show();
let profit_plot: Plot = plot_profit(&payoff_obj, 0.0, 10.0, 21);
profit_plot.show();
}
#[cfg(feature = "plotly")]
#[test]
#[ignore]
fn unit_test_bear_spread_plot() -> () {
use crate::financial_instruments::{BearSpread, plot_payoff, plot_profit};
let payoff_obj: BearSpread = BearSpread::build(6.0, 4.0, 1.0).unwrap();
let payoff_plot: Plot = plot_payoff(&payoff_obj, 0.0, 10.0, 21);
payoff_plot.show();
let profit_plot: Plot = plot_profit(&payoff_obj, 0.0, 10.0, 21);
profit_plot.show();
}
#[cfg(feature = "plotly")]
#[test]
#[ignore]
fn unit_test_long_butterfly_plot() -> () {
use crate::financial_instruments::{LongButterfly, plot_payoff, plot_profit};
let payoff_obj: LongButterfly = LongButterfly::build(4.0, 6.0, 5.0, 1.0).unwrap();
let payoff_plot: Plot = plot_payoff(&payoff_obj, 0.0, 10.0, 21);
payoff_plot.show();
let profit_plot: Plot = plot_profit(&payoff_obj, 0.0, 10.0, 21);
profit_plot.show();
}
#[cfg(feature = "plotly")]
#[test]
#[ignore]
fn unit_test_box_spread_plot() -> () {
use crate::financial_instruments::{BoxSpread, plot_payoff, plot_profit};
let payoff_obj: BoxSpread = BoxSpread::build(4.0, 6.0, 1.0).unwrap();
let payoff_plot: Plot = plot_payoff(&payoff_obj, 0.0, 10.0, 21);
payoff_plot.show();
let profit_plot: Plot = plot_profit(&payoff_obj, 0.0, 10.0, 21);
profit_plot.show();
}
#[cfg(feature = "plotly")]
#[test]
#[ignore]
fn unit_test_straddle_plot() -> () {
use crate::financial_instruments::{Straddle, plot_payoff, plot_profit};
let payoff_obj: Straddle = Straddle { k: 5.0, cost: 1.0 };
let payoff_plot: Plot = plot_payoff(&payoff_obj, 0.0, 10.0, 21);
payoff_plot.show();
let profit_plot: Plot = plot_profit(&payoff_obj, 0.0, 10.0, 21);
profit_plot.show();
}
#[cfg(feature = "plotly")]
#[test]
#[ignore]
fn unit_test_strangle_plot() -> () {
use crate::financial_instruments::{Strangle, plot_payoff, plot_profit};
let payoff_obj: Strangle = Strangle::build(6.0, 4.0, 1.0).unwrap();
let payoff_plot: Plot = plot_payoff(&payoff_obj, 0.0, 10.0, 21);
payoff_plot.show();
let profit_plot: Plot = plot_profit(&payoff_obj, 0.0, 10.0, 21);
profit_plot.show();
}
#[cfg(feature = "plotly")]
#[test]
#[ignore]
fn unit_test_strip_plot() -> () {
use crate::financial_instruments::{Strip, plot_payoff, plot_profit};
let payoff_obj: Strip = Strip { k: 5.0, cost: 1.0 };
let payoff_plot: Plot = plot_payoff(&payoff_obj, 0.0, 10.0, 21);
payoff_plot.show();
let profit_plot: Plot = plot_profit(&payoff_obj, 0.0, 10.0, 21);
profit_plot.show();
}
#[cfg(feature = "plotly")]
#[test]
#[ignore]
fn unit_test_strap_plot() -> () {
use crate::financial_instruments::{Strap, plot_payoff, plot_profit};
let payoff_obj: Strap = Strap { k: 5.0, cost: 1.0 };
let payoff_plot: Plot = plot_payoff(&payoff_obj, 0.0, 10.0, 21);
payoff_plot.show();
let profit_plot: Plot = plot_profit(&payoff_obj, 0.0, 10.0, 21);
profit_plot.show();
}
}