Skip to main content

rustyqlib/equity/
utils.rs

1use serde::Deserialize;
2use crate::equity::vanila_option::EquityOptionBase;
3use std::str::FromStr;
4use std::error::Error;
5use crate::core::trade::{PutOrCall};
6use std::fmt::Debug;
7use crate::core::utils::ContractStyle;
8
9///Enum for different engines to price options
10#[derive(PartialEq,Clone,Debug)]
11pub enum Engine{
12    BlackScholes,
13    MonteCarlo,
14    Binomial,
15    FiniteDifference
16}
17#[derive(Debug)]
18pub enum LongShort{
19    LONG,
20    SHORT
21}
22#[derive(Deserialize, Debug, Clone, Copy, PartialEq, Eq)]
23#[serde(rename_all = "snake_case")]
24pub enum PayoffType {
25    Vanilla,
26    Binary,
27    Barrier,
28    Asian,
29    ForwardStart,
30    Autocallable,
31}
32impl FromStr for PayoffType {
33    type Err = Box<dyn Error>;
34    fn from_str(s: &str) -> Result<Self, Self::Err> {
35        match s.to_lowercase().as_str() {
36            "vanilla" => Ok(PayoffType::Vanilla),
37            "binary" => Ok(PayoffType::Binary),
38            "barrier" => Ok(PayoffType::Barrier),
39            "asian" => Ok(PayoffType::Asian),
40            "forward_start" | "forwardstart" => Ok(PayoffType::ForwardStart),
41            "autocallable" | "autocall" => Ok(PayoffType::Autocallable),
42            _ => Err("Invalid payoff type".into()),
43        }
44    }
45}
46
47
48/// Common interface linking all payoffs (Vanilla, Binary, Barrier, Asian).
49///
50/// Terminal payoffs implement [`payoff`](Payoff::payoff); path-dependent
51/// payoffs (Asian, Barrier) additionally override
52/// [`path_payoff`](Payoff::path_payoff), which defaults to evaluating the
53/// terminal payoff on the last point of the path. Engines only ever call
54/// these two methods, so a new payoff plugs into every engine at once.
55pub trait Payoff: Debug + Send + Sync {
56    /// Payoff for a given level of the underlying: the terminal spot for
57    /// European exercise, or the exercise spot for American.
58    fn payoff(&self, spot: f64, strike: f64) -> f64;
59
60    /// Payoff for a full simulated path (used by Monte Carlo). Terminal
61    /// payoffs default to the last point; Asian/Barrier override this.
62    /// The path excludes the initial spot (it starts at the first step).
63    fn path_payoff(&self, path: &[f64], strike: f64) -> f64 {
64        self.payoff(*path.last().expect("empty path"), strike)
65    }
66
67    /// True when the payoff depends on the whole path (Asian, Barrier), so
68    /// engines must simulate paths rather than terminal values.
69    fn is_path_dependent(&self) -> bool {
70        false
71    }
72
73    /// Intrinsic value at the option's current underlying price.
74    fn payoff_amount(&self, base: &EquityOptionBase) -> f64 {
75        self.payoff(base.underlying_price.value(), base.strike_price)
76    }
77
78    fn payoff_kind(&self) -> PayoffType;
79    fn put_or_call(&self) -> &PutOrCall;
80    fn exercise_style(&self)->&ContractStyle;
81
82    /// Downcast hook so pricers that need payoff-specific details (e.g. the
83    /// analytic pricer distinguishing cash- from asset-or-nothing binaries)
84    /// can recover the concrete payoff type.
85    fn as_any(&self) -> &dyn std::any::Any;
86}