1 /*
2 * ObjectLab, http://www.objectlab.co.uk/open is sponsoring the ObjectLab Kit.
3 *
4 * Based in London, we are world leaders in the design and development
5 * of bespoke applications for the securities financing markets.
6 *
7 * <a href="http://www.objectlab.co.uk/open">Click here to learn more</a>
8 * ___ _ _ _ _ _
9 * / _ \| |__ (_) ___ ___| |_| | __ _| |__
10 * | | | | '_ \| |/ _ \/ __| __| | / _` | '_ \
11 * | |_| | |_) | | __/ (__| |_| |__| (_| | |_) |
12 * \___/|_.__// |\___|\___|\__|_____\__,_|_.__/
13 * |__/
14 *
15 * www.ObjectLab.co.uk
16 *
17 * $Id$
18 *
19 * Copyright 2006 the original author or authors.
20 *
21 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
22 * use this file except in compliance with the License. You may obtain a copy of
23 * the License at
24 *
25 * http://www.apache.org/licenses/LICENSE-2.0
26 *
27 * Unless required by applicable law or agreed to in writing, software
28 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
29 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
30 * License for the specific language governing permissions and limitations under
31 * the License.
32 */
33 package net.objectlab.kit.datecalc.joda;
34
35 import static net.objectlab.kit.datecalc.common.IMMPeriod.QUARTERLY;
36 import static org.joda.time.DateTimeConstants.DECEMBER;
37 import static org.joda.time.DateTimeConstants.JUNE;
38 import static org.joda.time.DateTimeConstants.MARCH;
39 import static org.joda.time.DateTimeConstants.SEPTEMBER;
40
41 import java.util.ArrayList;
42 import java.util.List;
43
44 import org.joda.time.LocalDate;
45
46 import net.objectlab.kit.datecalc.common.AbstractIMMDateCalculator;
47 import net.objectlab.kit.datecalc.common.IMMPeriod;
48
49 /**
50 * Joda <code>LocalDate</code> based implementation of the
51 * {@link net.objectlab.kit.datecalc.common.IMMDateCalculator}.
52 *
53 * @author Benoit Xhenseval
54 *
55 */
56 public class LocalDateIMMDateCalculator extends AbstractIMMDateCalculator<LocalDate> {
57 /**
58 * Returns a list of IMM dates between 2 dates, it will exclude the start
59 * date if it is an IMM date but would include the end date if it is an IMM.
60 *
61 * @param start
62 * start of the interval, excluded
63 * @param end
64 * end of the interval, may be included.
65 * @param period
66 * specify when the "next" IMM is, if quarterly then it is the
67 * conventional algorithm.
68 * @return list of IMM dates
69 */
70 @Override
71 public List<LocalDate> getIMMDates(final LocalDate start, final LocalDate end, final IMMPeriod period) {
72 final List<LocalDate> dates = new ArrayList<>();
73
74 LocalDate date = start;
75 while (true) {
76 date = getNextIMMDate(true, date, period);
77 if (!date.isAfter(end)) {
78 dates.add(date);
79 } else {
80 break;
81 }
82 }
83
84 return dates;
85 }
86
87 @Override
88 protected LocalDate getNextIMMDate(final boolean requestNextIMM, final LocalDate start, final IMMPeriod period) {
89 LocalDate date = start;
90
91 final int month = date.getMonthOfYear();
92 date = calculateIMMMonth(requestNextIMM, date, month);
93
94 LocalDate imm = calculate3rdWednesday(date);
95 final int immMonth = imm.getMonthOfYear();
96 final boolean isMarchSept = immMonth == MARCH || immMonth == SEPTEMBER;
97
98 switch (period) {
99
100 case BI_ANNUALY_JUN_DEC:
101 if (isMarchSept) {
102 imm = getNextIMMDate(requestNextIMM, imm, period);
103 }
104 break;
105
106 case BI_ANNUALY_MAR_SEP:
107 if (!isMarchSept) {
108 imm = getNextIMMDate(requestNextIMM, imm, period);
109 }
110 break;
111
112 case ANNUALLY:
113 // second jump
114 imm = getNextIMMDate(requestNextIMM, imm, QUARTERLY);
115 // third jump
116 imm = getNextIMMDate(requestNextIMM, imm, QUARTERLY);
117 // fourth jump
118 imm = getNextIMMDate(requestNextIMM, imm, QUARTERLY);
119 // fifth jump
120 imm = getNextIMMDate(requestNextIMM, imm, QUARTERLY);
121 break;
122
123 case QUARTERLY:
124 default:
125 break;
126 }
127
128 return imm;
129 }
130
131 // -----------------------------------------------------------------------
132 //
133 // ObjectLab, world leaders in the design and development of bespoke
134 // applications for the securities financing markets.
135 // www.ObjectLab.co.uk
136 //
137 // -----------------------------------------------------------------------
138
139 private LocalDate calculateIMMMonth(final boolean requestNextIMM, final LocalDate startDate, final int month) {
140 int monthOffset;
141 LocalDate date = startDate;
142 switch (month) {
143 case MARCH:
144 case JUNE:
145 case SEPTEMBER:
146 case DECEMBER:
147 final LocalDate immDate = calculate3rdWednesday(date);
148 if (requestNextIMM && !date.isBefore(immDate)) {
149 date = date.plusMonths(MONTHS_IN_QUARTER);
150 } else if (!requestNextIMM && !date.isAfter(immDate)) {
151 date = date.minusMonths(MONTHS_IN_QUARTER);
152 }
153 break;
154
155 default:
156 if (requestNextIMM) {
157 monthOffset = (MONTH_IN_YEAR - month) % MONTHS_IN_QUARTER;
158 date = date.plusMonths(monthOffset);
159 } else {
160 monthOffset = month % MONTHS_IN_QUARTER;
161 date = date.minusMonths(monthOffset);
162 }
163 break;
164 }
165 return date;
166 }
167
168 /**
169 * Assumes that the month is correct, get the day for the 2rd wednesday.
170 *
171 * @param original
172 * the start date
173 * @return the 3rd Wednesday of the month
174 */
175 private LocalDate calculate3rdWednesday(final LocalDate original) {
176 final LocalDate firstOfMonth = original.withDayOfMonth(1);
177 LocalDate firstWed = firstOfMonth.withDayOfWeek(MONTHS_IN_QUARTER);
178 if (firstWed.isBefore(firstOfMonth)) {
179 firstWed = firstWed.plusWeeks(1);
180 }
181 return firstWed.plusWeeks(2);
182 }
183
184 /**
185 * Checks if a given date is an official IMM Date (3rd Wednesdays of
186 * March/June/Sept/Dec.
187 *
188 * @param date
189 * @return true if that date is an IMM date.
190 */
191 @Override
192 public boolean isIMMDate(final LocalDate date) {
193 boolean same = false;
194
195 final List<LocalDate> dates = getIMMDates(date.minusDays(1), date, QUARTERLY);
196
197 if (!dates.isEmpty()) {
198 same = date.equals(dates.get(0));
199 }
200
201 return same;
202 }
203 }
204
205 /*
206 * ObjectLab, http://www.objectlab.co.uk/open is sponsoring the ObjectLab Kit.
207 *
208 * Based in London, we are world leaders in the design and development
209 * of bespoke applications for the securities financing markets.
210 *
211 * <a href="http://www.objectlab.co.uk/open">Click here to learn more about us</a>
212 * ___ _ _ _ _ _
213 * / _ \| |__ (_) ___ ___| |_| | __ _| |__
214 * | | | | '_ \| |/ _ \/ __| __| | / _` | '_ \
215 * | |_| | |_) | | __/ (__| |_| |__| (_| | |_) |
216 * \___/|_.__// |\___|\___|\__|_____\__,_|_.__/
217 * |__/
218 *
219 * www.ObjectLab.co.uk
220 */