RustyQLib 0.0.3

RustyQLib is a lightweight yet robust quantitative finance library designed to price derivatives and perform risk analysis
Documentation
use serde::{Deserialize, Serialize};
use crate::core::curves::CurveInput;
use crate::core::vols::VolInput;

#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(tag = "product_type", rename_all = "snake_case")]
pub enum ProductData {
    Option(EquityOptionData),
    Future(EquityFutureData),
    Forward(EquityForwardData),
    RainbowOption(crate::equity::rainbow::RainbowOptionData),
    CliquetOption(crate::equity::cliquet::CliquetOptionData),
    Accumulator(crate::equity::accumulator::AccumulatorData),
    VarianceSwap(crate::equity::variance_swap::VarianceSwapData),
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct EquityInstrumentBase {
    pub symbol: String,
    pub currency: Option<String>,
    pub exchange: Option<String>,
    pub name: Option<String>,
    pub cusip: Option<String>,
    pub isin: Option<String>,
    pub underlying_price: f64,
    pub long_short: Option<i32>,
    pub risk_free_rate: Option<f64>,
    /// Continuous stock borrow (repo) cost; enters the carry like an
    /// additional dividend yield (hard-to-borrow lowers the forward).
    pub borrow_cost: Option<f64>,
    pub settlement_type: Option<String>,
    /// Pricing as-of date (`YYYY-MM-DD`). Defaults to today, but setting
    /// it makes the contract price reproducibly and allows re-marking a
    /// book as of any date.
    pub valuation_date: Option<String>,
}

/// Resolve an optional contract `valuation_date`: parse it when present,
/// default to today's date otherwise.
pub fn parse_valuation_date(
    field: Option<&str>,
) -> Result<chrono::NaiveDate, crate::core::errors::RustyQLibError> {
    match field {
        Some(s) => chrono::NaiveDate::parse_from_str(s.trim(), "%Y-%m-%d").map_err(|_| {
            crate::core::errors::RustyQLibError::invalid_input(
                "valuation_date",
                format!("invalid date '{s}' (expected YYYY-MM-DD)"),
            )
        }),
        None => Ok(chrono::Local::now().date_naive()),
    }
}

/// A discrete cash dividend: ex-date and amount per share.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct CashDividendData {
    pub date: String,
    pub amount: f64,
}


#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct EquityFutureData {
    #[serde(flatten)]
    pub base: EquityInstrumentBase,
    pub current_price: Option<f64>,
    pub multiplier:Option<f64>,
    pub entry_price:Option<f64>,
    pub maturity: String,
    pub dividend: Option<f64>,

}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct EquityForwardData {
    #[serde(flatten)]
    pub base: EquityInstrumentBase,
    pub current_price: Option<f64>,
    pub notional: Option<f64>,
    pub entry_price:Option<f64>,
    pub maturity: String,
    pub dividend: Option<f64>,

}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct EquityOptionData {
    #[serde(flatten)]
    pub base: EquityInstrumentBase,
    pub put_or_call: String, // "Call"/"Put"
    pub payoff_type: String, // Vanilla/Barrier/Binary
    /// Binary settlement: "cash" (default) or "asset".
    pub binary_type: Option<String>,
    /// Amount paid by a cash-or-nothing binary (default 1.0).
    pub cash_amount: Option<f64>,
    /// Barrier variant: "up_in" | "up_out" | "down_in" | "down_out".
    pub barrier_type: Option<String>,
    pub barrier_level: Option<f64>,
    /// Second barrier level (makes the option a double barrier).
    pub barrier_level2: Option<f64>,
    /// Barrier rebate amount.
    pub rebate: Option<f64>,
    /// Knock-out rebate paid at the touch (default: at expiry).
    pub rebate_at_hit: Option<bool>,
    /// Lookback flavor: "floating" (default) or "fixed".
    pub lookback_type: Option<String>,
    /// Asian averaging: "arithmetic" (default) | "geometric".
    pub averaging_type: Option<String>,
    /// Asian strike: "fixed" (default, average price) | "floating" (average strike).
    pub asian_strike_type: Option<String>,
    /// Forward-start: strike fixing date and strike as a fraction of the
    /// fixing spot (default 1.0).
    pub forward_start_date: Option<String>,
    pub strike_fraction: Option<f64>,
    /// Autocallable: early-redemption and knock-in protection levels
    /// (absolute), per-period coupon (rebate), observation count, notional.
    pub autocall_barrier: Option<f64>,
    pub protection_barrier: Option<f64>,
    pub autocall_coupon: Option<f64>,
    pub autocall_observations: Option<usize>,
    /// Binomial tree parameterization: `LeisenReimer` (default), `CRR`,
    /// `JarrowRudd`, `Tian`, `Trigeorgis`, `EQP`.
    pub tree_type: Option<String>,
    /// Binomial tree steps (default 1000; Leisen-Reimer bumps even
    /// counts to odd).
    pub tree_steps: Option<usize>,
    /// Price the tree with term structures of rates and volatility
    /// applied per step (variance-equal time grid). `tree_type` is then
    /// ignored.
    pub tree_term_structure: Option<bool>,
    /// Bermudan exercise dates (`YYYY-MM-DD`, strictly increasing,
    /// after valuation and at or before maturity). Required when
    /// `exercise_style` is `Bermudan`. Expiry is always exercisable
    /// through the terminal payoff.
    pub exercise_dates: Option<Vec<String>>,
    /// Explicit autocall observation dates (`YYYY-MM-DD`, strictly
    /// increasing, after valuation and at or before maturity). Overrides
    /// `autocall_observations`; use business-day adjusted dates from a
    /// holiday calendar so observations do not land on weekends.
    pub autocall_observation_dates: Option<Vec<String>>,
    /// Phoenix: conditional-coupon barrier (absolute level).
    pub coupon_barrier: Option<f64>,
    /// Phoenix: memory coupons (missed coupons recovered later).
    pub coupon_memory: Option<bool>,
    pub notional: Option<f64>,
    /// Discrete cash dividends (ex-date + amount per share).
    pub cash_dividends: Option<Vec<CashDividendData>>,
    /// When set, the option is on a future (Black-76): "discounted"
    /// (standard) or "margined" (futures-style). `underlying_price` is then
    /// the futures price.
    pub futures_settlement: Option<String>,
    /// Strike; required for vanilla/binary/barrier/asian payoffs, unused
    /// for forward-start and autocallable contracts.
    pub strike_price: Option<f64>,
    /// Constant volatility; the simple alternative to `vol_surface`.
    pub volatility: Option<f64>,
    pub maturity: String,
    pub dividend: Option<f64>,
    pub current_price: Option<f64>,
    pub multiplier:Option<f64>,
    pub entry_price:Option<f64>,
    /// Monte Carlo path count (engine "MC" only).
    pub simulation: Option<u64>,
    /// MC time steps: 1 = terminal simulation; > 1 = path-wise stepping.
    pub mc_time_steps: Option<usize>,
    /// "exact" (default) | "euler" | "milstein"
    pub mc_scheme: Option<String>,
    /// "sobol" (default, low-discrepancy) | "pseudo" (seeded PCG64)
    pub mc_sampler: Option<String>,
    pub mc_seed: Option<u64>,
    /// "gbm" (default, constant vol) | "local_vol" (Dupire from the
    /// option's vol surface). Applies to the MonteCarlo and
    /// FiniteDifference engines.
    pub mc_model: Option<String>,
    /// Finite difference grid nodes in spot (default 400).
    pub fd_spot_steps: Option<usize>,
    /// Finite difference time steps (default 400).
    pub fd_time_steps: Option<usize>,
    /// Heston parameters; required when `mc_model` is "heston".
    pub heston: Option<crate::equity::heston::HestonParams>,
    pub exercise_style: Option<String>, //European, American,
    pub pricer:Option<String>,
    /// Optional discount curve; when absent a flat curve is built from
    /// `risk_free_rate` (which stays the simple way to specify a rate).
    pub discount_curve: Option<CurveInput>,
    /// Optional volatility surface; when absent a flat surface is built
    /// from `volatility`. One of the two must be provided.
    pub vol_surface: Option<VolInput>,
}