View Javadoc
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  */