Skip to content

Commit ce02da8

Browse files
committed
2 parents 6d7a75b + daa08eb commit ce02da8

File tree

9 files changed

+157
-26
lines changed

9 files changed

+157
-26
lines changed

src/core/utils.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,17 @@ impl EngineType {
3939
#[derive(Clone,Debug,Deserialize,Serialize)]
4040
pub struct MarketData {
4141
pub underlying_price:f64,
42-
pub option_type:String,
43-
pub strike_price:f64,
42+
pub option_type:Option<String>,
43+
pub strike_price:Option<f64>,
4444
pub volatility:Option<f64>,
4545
pub option_price:Option<f64>,
4646
pub risk_free_rate:Option<f64>,
4747
pub maturity:String,
4848
pub dividend: Option<f64>,
4949
pub simulation:Option<u64>,
50+
pub current_price:Option<f64>
5051
}
52+
5153
#[derive(Clone,Debug,Deserialize,Serialize)]
5254
pub struct RateData {
5355
pub instrument: String,
@@ -66,6 +68,7 @@ pub struct Contract {
6668
pub action: String,
6769
pub pricer: String,
6870
pub asset: String,
71+
pub product_type: Option<String>,
6972
pub payoff_type:Option<String>,
7073
pub style: Option<String>,
7174
pub market_data: Option<MarketData>,

src/equity/equity_forward.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
use chrono::NaiveDate;
2+
use crate::core::quotes::Quote;
3+
use crate::equity::utils::LongShort;
4+
pub struct EquityForward {
5+
pub underlying_price: Quote,
6+
pub forward_price: Quote,
7+
pub risk_free_rate: f64,
8+
pub dividend_yield: f64,
9+
pub maturity_date: NaiveDate,
10+
pub valuation_date: NaiveDate,
11+
pub long_short:LongShort,
12+
pub notional:f64
13+
}
14+

src/equity/equity_future.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// An equity
2+
use chrono::{Datelike, Local, NaiveDate};
3+
use crate::core::quotes::Quote;
4+
use crate::core::traits::Instrument;
5+
use crate::core::utils::{Contract,ContractStyle};
6+
use crate::equity::vanila_option::EquityOption;
7+
8+
pub struct EquityFuture {
9+
pub underlying_price: Quote,
10+
pub current_price: Quote,
11+
pub risk_free_rate: f64,
12+
pub dividend_yield: f64,
13+
pub maturity_date: NaiveDate,
14+
pub valuation_date: NaiveDate,
15+
}
16+
17+
impl EquityFuture {
18+
pub fn from_json(data: &Contract) -> Box<Self> {
19+
let market_data = data.market_data.as_ref().unwrap();
20+
//let future_date = NaiveDate::parse_from_str(&maturity_date, "%Y-%m-%d").expect("Invalid date format");
21+
let today = Local::today();
22+
let maturity_date = NaiveDate::parse_from_str(&market_data.maturity, "%Y-%m-%d")
23+
.expect("Invalid maturity date");
24+
25+
let underlying_quote = Quote::new(market_data.underlying_price);
26+
let quote = Some(market_data.current_price).unwrap();
27+
let current_quote = Quote::new(quote.unwrap_or(0.0));
28+
let risk_free_rate = Some(market_data.risk_free_rate).unwrap();
29+
let dividend = Some(market_data.dividend).unwrap();
30+
Box::new(Self {
31+
underlying_price: underlying_quote,
32+
current_price:current_quote,
33+
risk_free_rate: risk_free_rate.unwrap_or(0.0),
34+
dividend_yield: dividend.unwrap_or(0.0),
35+
maturity_date: maturity_date,
36+
valuation_date: today.naive_utc(),
37+
})
38+
}
39+
40+
fn time_to_maturity(&self) -> f64 {
41+
let days = (self.maturity_date - self.valuation_date).num_days();
42+
(days as f64) / 365.0
43+
}
44+
fn premiun(&self)->f64{
45+
self.current_price.value()-self.underlying_price.value()
46+
}
47+
}
48+
impl Instrument for EquityFuture {
49+
fn npv(&self) -> f64 {
50+
// F_0 = S_0 * e^{(r - q)*t}
51+
let t = self.time_to_maturity();
52+
self.underlying_price.value() * ((self.risk_free_rate - self.dividend_yield) * t).exp()
53+
}
54+
}
55+
impl EquityFuture{
56+
pub fn delta(&self) -> f64 { 1.0 }
57+
pub fn gamma(&self) -> f64 { 0.0 }
58+
pub fn vega(&self) -> f64 { 0.0 }
59+
pub fn theta(&self) -> f64 { 0.0 }
60+
pub fn rho(&self) -> f64 { 0.0 }
61+
}
62+
// }
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
use crate::core::traits::Instrument;
2+
use crate::core::utils::{Contract,CombinedContract, ContractOutput};
3+
use crate::equity::vanila_option::EquityOption;
4+
use crate::equity::equity_future::EquityFuture;
5+
pub fn handle_equity_contract(data: &Contract) -> String {
6+
match data.product_type.as_deref() {
7+
Some("Option") => {
8+
let option = EquityOption::from_json(&data);
9+
let contract_output = ContractOutput {
10+
pv: option.npv(),
11+
delta: option.delta(),
12+
gamma: option.gamma(),
13+
vega: option.vega(),
14+
theta: option.theta(),
15+
rho: option.rho(),
16+
error: None
17+
};
18+
println!("Theoretical Price ${}", contract_output.pv);
19+
println!("Delta ${}", contract_output.delta);
20+
let combined_ = CombinedContract{
21+
contract: data.clone(),
22+
output:contract_output
23+
};
24+
serde_json::to_string(&combined_).expect("Failed to generate output")
25+
}
26+
Some("Future") => {
27+
let future = EquityFuture::from_json(data);
28+
let contract_output = ContractOutput {
29+
pv: future.npv(),
30+
delta: future.delta(),
31+
gamma: future.gamma(),
32+
vega: future.vega(),
33+
theta: future.theta(),
34+
rho: future.rho(),
35+
error: None
36+
};
37+
println!("Equity Future Price: {}", contract_output.pv);
38+
let combined_ = CombinedContract {
39+
contract: data.clone(),
40+
output: contract_output
41+
};
42+
serde_json::to_string(&combined_).expect("Failed to generate output")
43+
}
44+
_ => {
45+
panic!("Unsupported or missing product_type for asset EQ");
46+
}
47+
}
48+
}

src/equity/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,6 @@ pub mod build_contracts;
88
pub mod vol_surface;
99
pub mod finite_difference;
1010
pub mod binary_option;
11+
mod equity_future;
12+
pub mod handle_equity_contracts;
13+
mod equity_forward;

src/equity/utils.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@ pub enum Engine{
1212
Binomial,
1313
FiniteDifference
1414
}
15-
15+
pub enum LongShort{
16+
LONG,
17+
SHORT
18+
}
1619
#[derive(Deserialize, Debug)]
1720
#[serde(rename_all = "snake_case")]
1821
pub enum PayoffType {

src/equity/vanila_option.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -79,14 +79,16 @@ impl EquityOption{
7979
}
8080
}
8181
impl EquityOption {
82-
//pub fn new(x:T)->Self{
83-
//
84-
//}
82+
8583
pub fn from_json(data: &Contract) -> Box<EquityOption> {
8684
let payoff_type = data.payoff_type.as_ref().unwrap().parse::<PayoffType>();
8785
let market_data = data.market_data.as_ref().unwrap();
88-
let option_type = &market_data.option_type;
86+
//let option_type = &market_data.option_type;
8987
let side: OptionType;
88+
let option_type = match &market_data.option_type {
89+
Some(x) => x.clone(),
90+
None => "".to_string(),
91+
};
9092
match option_type.trim() {
9193
"C" | "c" | "Call" | "call" => side = OptionType::Call,
9294
"P" | "p" | "Put" | "put" => side = OptionType::Put,
@@ -130,7 +132,7 @@ impl EquityOption {
130132
transection: Transection::Buy,
131133
underlying_price: underlying_quote,
132134
current_price: option_price,
133-
strike_price: market_data.strike_price,
135+
strike_price: market_data.strike_price.unwrap_or(0.0),
134136
volatility: volatility,
135137
maturity_date: future_date,
136138
risk_free_rate: risk_free_rate.unwrap_or(0.0),

src/examples/EQ/equity_option.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
{"contracts" : [
1+
{"asset":"EQ",
2+
"contracts" : [
23
{
34
"action":"PV",
45
"pricer":"Analytical",
56
"asset":"EQ",
7+
"product_type": "Option",
68
"payoff_type": "Vanilla",
79
"market_data":{
810
"underlying_price":100,
@@ -18,12 +20,10 @@
1820
"action":"PV",
1921
"pricer":"Analytical",
2022
"asset":"EQ",
21-
"payoff_type": "Vanilla",
23+
"product_type": "Future",
2224
"market_data":{
2325
"underlying_price":100,
24-
"option_type":"P",
25-
"strike_price":100,
26-
"volatility":0.4,
26+
"current_price":104,
2727
"risk_free_rate":0.06,
2828
"maturity":"2025-03-31",
2929
"dividend": 0.01

src/utils/parse_json.rs

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ use crate::rates::deposits::Deposit;
2525
use crate::rates::build_contracts::{build_ir_contracts, build_ir_contracts_from_json, build_term_structure};
2626
use crate::equity::build_contracts::{build_eq_contracts_from_json};
2727
use crate::equity::vol_surface::VolSurface;
28+
use crate::equity::handle_equity_contracts::handle_equity_contract;
29+
2830
use rayon::prelude::*;
2931
/// This function saves the output to a file and returns the path to the file.
3032
pub fn save_to_file<'a>(output_folder: &'a str, subfolder: &'a str, filename: &'a str, output: &'a str) -> String {
@@ -110,24 +112,18 @@ pub fn process_contract(data: &Contract) -> String {
110112
let ts = YieldTermStructure::new(date,rates);
111113

112114
if data.action=="PV" && data.asset=="EQ"{
113-
//let market_data = data.market_data.clone().unwrap();
114-
let option = EquityOption::from_json(&data);
115-
let contract_output = ContractOutput{pv:option.npv(),delta:option.delta(),gamma:option.gamma(),
116-
vega:option.vega(),theta:option.theta(),rho:option.rho(), error: None };
117-
println!("Theoretical Price ${}", contract_output.pv);
118-
println!("Delta ${}", contract_output.delta);
119-
let combined_ = CombinedContract{
120-
contract: data.clone(),
121-
output:contract_output
122-
};
123-
let output_json = serde_json::to_string(&combined_).expect("Failed to generate output");
124-
return output_json;
115+
return handle_equity_contract(data);
116+
125117
}
126118
else if data.action=="PV" && data.asset=="CO"{
127119
let market_data = data.market_data.clone().unwrap();
128120
let curr_quote = Quote::new( market_data.underlying_price);
129121
let option_type = &market_data.option_type;
130122
let side: trade::OptionType;
123+
let option_type = match &market_data.option_type {
124+
Some(x) => x.clone(),
125+
None => "".to_string(),
126+
};
131127
match option_type.trim() {
132128
"C" | "c" | "Call" | "call" => side = trade::OptionType::Call,
133129
"P" | "p" | "Put" | "put" => side = trade:: OptionType::Put,
@@ -146,7 +142,7 @@ pub fn process_contract(data: &Contract) -> String {
146142
option_type: side,
147143
transection: trade::Transection::Buy,
148144
current_price: curr_quote,
149-
strike_price: market_data.strike_price,
145+
strike_price: market_data.strike_price.unwrap_or(0.0),
150146
volatility: vol.unwrap(),
151147
time_to_maturity: year_fraction,
152148
transection_price: 0.0,

0 commit comments

Comments
 (0)