rateslib/scheduling/calendars/
adjuster.rs1use crate::scheduling::DateRoll;
2use chrono::prelude::*;
3use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
7pub enum Adjuster {
8 Actual {},
10 Following {},
12 ModifiedFollowing {},
14 Previous {},
16 ModifiedPrevious {},
18 FollowingSettle {},
20 ModifiedFollowingSettle {},
22 PreviousSettle {},
24 ModifiedPreviousSettle {},
26 BusDaysLagSettle(i32),
29 CalDaysLagSettle(i32),
32 FollowingExLast {},
34 FollowingExLastSettle {},
36}
37
38pub trait Adjustment {
40 fn adjust<T: DateRoll>(&self, udate: &NaiveDateTime, calendar: &T) -> NaiveDateTime;
42
43 fn adjusts<T: DateRoll>(&self, udates: &Vec<NaiveDateTime>, calendar: &T)
45 -> Vec<NaiveDateTime>;
46}
47
48pub trait CalendarAdjustment {
50 fn adjust(&self, udate: &NaiveDateTime, adjuster: &Adjuster) -> NaiveDateTime
52 where
53 Self: Sized + DateRoll,
54 {
55 adjuster.adjust(udate, self)
56 }
57
58 fn adjusts(&self, udates: &Vec<NaiveDateTime>, adjuster: &Adjuster) -> Vec<NaiveDateTime>
60 where
61 Self: Sized + DateRoll,
62 {
63 adjuster.adjusts(udates, self)
64 }
65}
66
67impl Adjustment for Adjuster {
68 fn adjust<T: DateRoll>(&self, udate: &NaiveDateTime, calendar: &T) -> NaiveDateTime {
69 match self {
70 Adjuster::Actual {} => *udate,
71 Adjuster::Following {} => calendar.roll_forward_bus_day(udate),
72 Adjuster::Previous {} => calendar.roll_backward_bus_day(udate),
73 Adjuster::ModifiedFollowing {} => calendar.roll_mod_forward_bus_day(udate),
74 Adjuster::ModifiedPrevious {} => calendar.roll_mod_backward_bus_day(udate),
75 Adjuster::FollowingSettle {} => calendar.roll_forward_settled_bus_day(udate),
76 Adjuster::PreviousSettle {} => calendar.roll_backward_settled_bus_day(udate),
77 Adjuster::ModifiedFollowingSettle {} => {
78 calendar.roll_forward_mod_settled_bus_day(udate)
79 }
80 Adjuster::ModifiedPreviousSettle {} => {
81 calendar.roll_backward_mod_settled_bus_day(udate)
82 }
83 Adjuster::BusDaysLagSettle(n) => calendar.lag_bus_days(udate, *n, true),
84 Adjuster::CalDaysLagSettle(n) => {
85 let adj = if *n < 0 {
86 Adjuster::PreviousSettle {}
87 } else {
88 Adjuster::FollowingSettle {}
89 };
90 calendar.add_cal_days(udate, *n, &adj)
91 }
92 Adjuster::FollowingExLast {} => calendar.roll_forward_bus_day(udate), Adjuster::FollowingExLastSettle {} => calendar.roll_forward_settled_bus_day(udate), }
95 }
96
97 fn adjusts<T: DateRoll>(
98 &self,
99 udates: &Vec<NaiveDateTime>,
100 calendar: &T,
101 ) -> Vec<NaiveDateTime> {
102 match self {
103 Adjuster::FollowingExLast {} | Adjuster::FollowingExLastSettle {} => {
104 let mut adates: Vec<NaiveDateTime> = udates
105 .iter()
106 .map(|udate| self.adjust(udate, calendar))
107 .collect();
108 adates[udates.len() - 1] = udates[udates.len() - 1];
109 adates
110 }
111 _ => udates
112 .iter()
113 .map(|udate| self.adjust(udate, calendar))
114 .collect(),
115 }
116 }
117}
118
119#[cfg(test)]
121mod tests {
122 use super::*;
123 use crate::scheduling::{ndt, Cal};
124
125 fn fixture_hol_cal() -> Cal {
126 let hols = vec![ndt(2015, 9, 5), ndt(2015, 9, 7)]; Cal::new(hols, vec![5, 6])
128 }
129
130 #[test]
131 fn test_adjusts() {
132 let cal = fixture_hol_cal();
133 let udates = vec![
134 ndt(2015, 9, 4),
135 ndt(2015, 9, 5),
136 ndt(2015, 9, 6),
137 ndt(2015, 9, 7),
138 ];
139 let result = Adjuster::Following {}.adjusts(&udates, &cal);
140 assert_eq!(
141 result,
142 vec![
143 ndt(2015, 9, 4),
144 ndt(2015, 9, 8),
145 ndt(2015, 9, 8),
146 ndt(2015, 9, 8)
147 ]
148 );
149 }
150
151 #[test]
152 fn test_adjusts_ex_last() {
153 let cal = fixture_hol_cal();
155 let udates = vec![
156 ndt(2015, 9, 4),
157 ndt(2015, 9, 5),
158 ndt(2015, 9, 6),
159 ndt(2015, 9, 7),
160 ];
161 let result = Adjuster::FollowingExLast {}.adjusts(&udates, &cal);
162 assert_eq!(
163 result,
164 vec![
165 ndt(2015, 9, 4),
166 ndt(2015, 9, 8),
167 ndt(2015, 9, 8),
168 ndt(2015, 9, 7)
169 ]
170 );
171 }
172}