Skip to main content

rustyqlib/equity/
equity_future.rs

1// An equity
2use chrono::NaiveDate;
3use crate::core::data_models::EquityFutureData;
4use crate::core::quotes::Quote;
5use crate::core::traits::Instrument;
6use crate::equity::utils::LongShort;
7use crate::core::errors::RustyQLibError;
8//use crate::equity::vanilla_option::EquityOption;
9
10pub struct EquityFuture {
11
12    pub symbol: String,
13    pub currency: Option<String>,
14    pub exchange: Option<String>,
15    pub name: Option<String>,
16    pub cusip: Option<String>,
17    pub isin: Option<String>,
18    pub settlement_type: Option<String>,
19
20    pub underlying_price: Quote,
21    pub current_price: Quote,
22    pub entry_price: f64,
23    pub multiplier: f64,
24    pub risk_free_rate: f64,
25    pub dividend_yield: f64,
26    /// Continuous stock borrow (repo) cost; part of the carry.
27    pub borrow_cost: f64,
28    pub maturity_date: NaiveDate,
29    pub valuation_date: NaiveDate,
30    pub long_short:LongShort,
31}
32
33impl EquityFuture {
34    /// Build from contract data, panicking on any invalid field. Fallible
35    /// callers should use [`EquityFuture::try_from_json`].
36    pub fn from_json(data: &EquityFutureData) -> Box<Self> {
37        Self::try_from_json(data).unwrap_or_else(|e| panic!("{e}"))
38    }
39
40    pub fn try_from_json(data: &EquityFutureData) -> Result<Box<Self>, RustyQLibError> {
41        let today =
42            crate::core::data_models::parse_valuation_date(data.base.valuation_date.as_deref())?;
43        let maturity_date = NaiveDate::parse_from_str(&data.maturity, "%Y-%m-%d")
44            .map_err(|_| RustyQLibError::invalid_input(
45                "maturity",
46                format!("invalid date '{}' (expected YYYY-MM-DD)", data.maturity),
47            ))?;
48
49        let underlying_quote = Quote::new(data.base.underlying_price);
50        let current_quote = Quote::new(data.current_price.unwrap_or(0.0));
51        let risk_free_rate = data.base.risk_free_rate;
52        let dividend = data.dividend;
53        let long_short = data.base.long_short.unwrap_or(1);
54        let position = match long_short{
55            1=>LongShort::LONG,
56            -1=>LongShort::SHORT,
57            _=>LongShort::LONG,
58        };
59        Ok(Box::new(Self {
60            symbol:data.base.symbol.clone(),
61            currency: data.base.currency.clone(),
62            exchange:data.base.exchange.clone(),
63            name: data.base.name.clone(),
64            cusip: data.base.cusip.clone(),
65            isin: data.base.isin.clone(),
66            settlement_type: data.base.settlement_type.clone(),
67
68            underlying_price: underlying_quote,
69            current_price:current_quote,
70            entry_price: data.entry_price.unwrap_or(0.0),
71            multiplier: data.multiplier.unwrap_or(1.0),
72            risk_free_rate: risk_free_rate.unwrap_or(0.0),
73            dividend_yield: dividend.unwrap_or(0.0),
74            borrow_cost: data.base.borrow_cost.unwrap_or(0.0),
75            maturity_date: maturity_date,
76            valuation_date: today,
77            long_short:position
78        }))
79    }
80    fn pnl(&self)->f64{
81        let pnl = (self.current_price.value()-self.entry_price)*self.multiplier;
82        match self.long_short {
83            LongShort::LONG => pnl,
84            LongShort::SHORT => -pnl,
85        }
86    }
87}
88impl Instrument for EquityFuture {
89    fn try_npv(&self) -> Result<f64, RustyQLibError> {
90        Ok(self.pnl())
91    }
92
93    fn price(&self) -> Result<crate::core::results::PricingResult, RustyQLibError> {
94        Ok(crate::core::results::PricingResult {
95            pv: self.try_npv()?,
96            greeks: crate::core::results::Greeks { delta: self.delta(), ..Default::default() },
97            std_err: None,
98        })
99    }
100}
101impl EquityFuture{
102    pub fn delta(&self) -> f64 { 1.0 }
103    pub fn gamma(&self) -> f64 { 0.0 }
104    pub fn vega(&self) -> f64  { 0.0 }
105    pub fn theta(&self) -> f64 { 0.0 }
106    pub fn rho(&self) -> f64   { 0.0 }
107    pub fn vanna(&self) -> f64 { 0.0 }
108    pub fn charm(&self) -> f64 { 0.0 }
109    pub fn gamma_p(&self) -> f64 { 0.0 }
110    pub fn zomma(&self) -> f64 { 0.0 }
111}