1use serde::Deserialize;
2use std::str::FromStr;
3use std::error::Error;
4use crate::core::trade::{PutOrCall};
5use std::fmt::Debug;
6use crate::core::utils::ContractStyle;
7
8#[derive(PartialEq,Clone,Debug)]
10pub enum Engine{
11 BlackScholes,
12 MonteCarlo,
13 Binomial,
14 FiniteDifference,
15 BaroneAdesiWhaley,
17 BjerksundStensland,
20}
21
22#[derive(Debug, Clone, Copy, PartialEq)]
26pub enum PricingEngine {
27 BlackScholes,
29 MonteCarlo(crate::equity::montecarlo::MonteCarloConfig),
30 Binomial(crate::core::lattice::LatticeConfig),
31 FiniteDifference(crate::equity::finite_difference::FdConfig),
32 BaroneAdesiWhaley,
33 BjerksundStensland,
34}
35
36impl PricingEngine {
37 pub fn kind(&self) -> Engine {
39 match self {
40 PricingEngine::BlackScholes => Engine::BlackScholes,
41 PricingEngine::MonteCarlo(_) => Engine::MonteCarlo,
42 PricingEngine::Binomial(_) => Engine::Binomial,
43 PricingEngine::FiniteDifference(_) => Engine::FiniteDifference,
44 PricingEngine::BaroneAdesiWhaley => Engine::BaroneAdesiWhaley,
45 PricingEngine::BjerksundStensland => Engine::BjerksundStensland,
46 }
47 }
48
49 pub fn from_kind(kind: Engine) -> PricingEngine {
51 match kind {
52 Engine::BlackScholes => PricingEngine::BlackScholes,
53 Engine::MonteCarlo => PricingEngine::MonteCarlo(Default::default()),
54 Engine::Binomial => PricingEngine::Binomial(Default::default()),
55 Engine::FiniteDifference => PricingEngine::FiniteDifference(Default::default()),
56 Engine::BaroneAdesiWhaley => PricingEngine::BaroneAdesiWhaley,
57 Engine::BjerksundStensland => PricingEngine::BjerksundStensland,
58 }
59 }
60}
61
62#[derive(Debug, Clone, Copy, PartialEq, Default)]
67pub enum Model {
68 #[default]
70 Gbm,
71 LocalVol,
73 Heston(crate::equity::heston::HestonParams),
75}
76
77impl Model {
78 pub fn is_heston(&self) -> bool {
79 matches!(self, Model::Heston(_))
80 }
81
82 pub fn with_vol_shift(&self, shift: f64) -> Model {
90 match self {
91 Model::Heston(params) => Model::Heston(params.with_vol_shift(shift)),
92 other => *other,
93 }
94 }
95
96 pub fn from_contract(
99 mc_model: Option<&str>,
100 heston: Option<crate::equity::heston::HestonParams>,
101 ) -> Result<Model, crate::core::errors::RustyQLibError> {
102 use crate::core::errors::RustyQLibError;
103 match mc_model.map(str::trim) {
104 None | Some("gbm") | Some("GBM") | Some("Gbm") => Ok(Model::Gbm),
105 Some("local_vol") | Some("localvol") | Some("LocalVol") | Some("local") => {
106 Ok(Model::LocalVol)
107 }
108 Some("heston") | Some("Heston") => {
109 let params = heston.ok_or_else(|| RustyQLibError::invalid_input(
110 "heston",
111 "heston parameters are required when mc_model = heston",
112 ))?;
113 params.validate()?;
114 Ok(Model::Heston(params))
115 }
116 Some(other) => Err(RustyQLibError::invalid_input(
117 "mc_model",
118 format!("unknown model '{other}' (use gbm, local_vol or heston)"),
119 )),
120 }
121 }
122}
123#[derive(Debug, Clone, Copy, PartialEq, Eq)]
124pub enum LongShort{
125 LONG,
126 SHORT
127}
128#[derive(Deserialize, Debug, Clone, Copy, PartialEq, Eq)]
129#[serde(rename_all = "snake_case")]
130pub enum PayoffType {
131 Vanilla,
132 Binary,
133 Barrier,
134 Asian,
135 ForwardStart,
136 Autocallable,
137 Lookback,
138 Accumulator,
139}
140impl FromStr for PayoffType {
141 type Err = Box<dyn Error>;
142 fn from_str(s: &str) -> Result<Self, Self::Err> {
143 match s.to_lowercase().as_str() {
144 "vanilla" => Ok(PayoffType::Vanilla),
145 "binary" => Ok(PayoffType::Binary),
146 "barrier" => Ok(PayoffType::Barrier),
147 "asian" => Ok(PayoffType::Asian),
148 "forward_start" | "forwardstart" => Ok(PayoffType::ForwardStart),
149 "autocallable" | "autocall" => Ok(PayoffType::Autocallable),
150 "lookback" => Ok(PayoffType::Lookback),
151 _ => Err("Invalid payoff type".into()),
152 }
153 }
154}
155
156
157pub trait Payoff: Debug + Send + Sync {
165 fn payoff(&self, spot: f64, strike: f64) -> f64;
168
169 fn path_payoff(&self, path: &[f64], strike: f64) -> f64 {
173 self.payoff(*path.last().expect("empty path"), strike)
174 }
175
176 fn is_path_dependent(&self) -> bool {
179 false
180 }
181
182 fn payoff_amount(&self, spot: f64, strike: f64) -> f64 {
185 self.payoff(spot, strike)
186 }
187
188 fn path_payoff_var<'t>(
197 &self,
198 _path: &[crate::core::aad::Var<'t>],
199 _strike: f64,
200 ) -> Option<crate::core::aad::Var<'t>> {
201 None
202 }
203
204 fn payoff_kind(&self) -> PayoffType;
205 fn put_or_call(&self) -> &PutOrCall;
206 fn exercise_style(&self)->&ContractStyle;
207
208 fn as_any(&self) -> &dyn std::any::Any;
212
213 fn clone_box(&self) -> Box<dyn Payoff>;
218}
219
220impl Clone for Box<dyn Payoff> {
221 fn clone(&self) -> Self {
222 self.clone_box()
223 }
224}