rustyqlib/equity/
equity_future.rs1use 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;
8pub 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 pub borrow_cost: f64,
28 pub maturity_date: NaiveDate,
29 pub valuation_date: NaiveDate,
30 pub long_short:LongShort,
31}
32
33impl EquityFuture {
34 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}