1use chrono::{Local, NaiveDate};
2use crate::core::traits::Rates;
3use crate::rates::utils::{DayCountConvention,TermStructure};
4
5pub struct FRA {
14 pub start_date: NaiveDate, pub maturity_date: NaiveDate,
16 pub valuation_date: NaiveDate,
17 pub notional: f64,
18 pub currency: String,
19 pub fix_rate: f64,
20 pub day_count: DayCountConvention,
21 pub business_day_adjustment: i8,
22 pub term_structure: Option<TermStructure>,
23}
24impl FRA {
25 pub fn new(start_date: NaiveDate, maturity_date: NaiveDate, valuation_date: NaiveDate,
26 notional: f64, fix_rate: f64, day_count: DayCountConvention,
27 business_day_adjustment: i8) -> FRA {
28 FRA {
29 start_date,
30 maturity_date,
31 valuation_date,
32 notional,
33 currency: String::from("USD"),
34 fix_rate,
35 day_count,
36 business_day_adjustment,
37 term_structure: None,
38 }
39 }
40 pub fn builder(start_date: String,maturity_date:String,notional: f64, fix_rate: f64,day_count: String) ->FRA{
41
42 let today = Local::now().date_naive();
43 let start_date = NaiveDate::parse_from_str(&start_date, "%Y-%m-%d").expect("Invalid date format");
44 let maturity_date = NaiveDate::parse_from_str(&maturity_date, "%Y-%m-%d").expect("Invalid date format");
45 let mut fra = FRA {
46 start_date: start_date,
47 maturity_date: maturity_date,
48 valuation_date: today,
49 notional: notional,
50 currency: String::from("USD"),
51 fix_rate: fix_rate,
52 day_count: DayCountConvention::Act360,
53 business_day_adjustment: 0,
54 term_structure: None,
55 };
56 match day_count.as_str() {
57 "Act360" |"A360" => {
58 fra.day_count = DayCountConvention::Act360;
59 }
60 "Act365" |"A365" => {
61 fra.day_count = DayCountConvention::Act365;
62 }
63 "Thirty360" |"30/360" => {
64 fra.day_count = DayCountConvention::Thirty360;
65 }
66 _ => {}
67 }
68 fra
69 }
70 pub fn get_year_fraction(&self,date:NaiveDate) -> f64 {
71 let duration = self.maturity_date.signed_duration_since(date);
72 let year_fraction = duration.num_days() as f64 / self.day_count.num_of_days() as f64;
73 year_fraction
74 }
75 pub fn get_discount_factor(&self,df_start_date:f64) -> f64 {
76 let year_fraction = self.get_year_fraction(self.start_date);
77 let discount_factor = df_start_date / (1.0 + self.fix_rate * year_fraction);
78 discount_factor
79 }
80}
81
82impl Rates for FRA{
83 fn get_implied_rates(&self) -> f64 {
84 let curve = self.term_structure.as_ref().expect("Term structure is not set");
85 let df = curve.interpolate_log_linear(self.valuation_date,self.maturity_date);
86 let implied_rate = (1.0/df - 1.0)/self.get_year_fraction(self.valuation_date);
87 return implied_rate;
88 }
89 fn get_maturity_date(&self) -> NaiveDate {
90 self.maturity_date
91 }
92 fn get_rate(&self) -> f64 {
93 let df = self.get_maturity_discount_factor();
94 let time = self.get_year_fraction(self.valuation_date);
95 -df.ln() / time
96 }
97 fn get_maturity_discount_factor(&self) -> f64 {
98 let curve = self.term_structure.as_ref().expect("Term structure is not set");
99 let df = curve.interpolate_log_linear(self.valuation_date,self.start_date);
100 self.get_discount_factor(df)
101 }
102 fn get_day_count(&self) -> &DayCountConvention {
103 &self.day_count
104 }
105 fn set_term_structure(&mut self,term_structure:TermStructure) {
106 self.term_structure = Some(term_structure);
107 }
108}