diff --git a/modules/basics/src/main/java/com/opengamma/strata/basics/date/GlobalHolidayCalendars.java b/modules/basics/src/main/java/com/opengamma/strata/basics/date/GlobalHolidayCalendars.java index abe56f42d8..5f4c6ac3da 100644 --- a/modules/basics/src/main/java/com/opengamma/strata/basics/date/GlobalHolidayCalendars.java +++ b/modules/basics/src/main/java/com/opengamma/strata/basics/date/GlobalHolidayCalendars.java @@ -17,7 +17,6 @@ import static java.time.temporal.TemporalAdjusters.lastInMonth; import static java.time.temporal.TemporalAdjusters.nextOrSame; import static java.time.temporal.TemporalAdjusters.previous; -import static java.util.stream.Collectors.toSet; import java.io.DataOutputStream; import java.io.File; @@ -25,7 +24,6 @@ import java.io.IOException; import java.time.DayOfWeek; import java.time.LocalDate; -import java.time.MonthDay; import java.time.temporal.TemporalAdjusters; import java.util.ArrayList; import java.util.HashSet; @@ -183,7 +181,7 @@ static ImmutableHolidayCalendar generateLondon() { // New Years Eve is holiday for cash markets and derivatives in 2015 // https://www.euronext.com/en/holidays-and-hours // https://www.euronext.com/en/trading/nyse-euronext-trading-calendar/archives - // evidence suggests that Monday is holiday when Tuesday is, and Friday is holiday when Thursday is + // some sources have Monday is holiday when Tuesday is, and Friday is holiday when Thursday is (not applying this) static ImmutableHolidayCalendar generateParis() { List holidays = new ArrayList<>(2000); for (int year = 1950; year <= 2099; year++) { @@ -204,7 +202,6 @@ static ImmutableHolidayCalendar generateParis() { holidays.add(date(year, 12, 26)); // saint stephen } holidays.add(date(1999, 12, 31)); // millennium - applyBridging(holidays); removeSatSun(holidays); return ImmutableHolidayCalendar.of(HolidayCalendarIds.FRPA, holidays, SATURDAY, SUNDAY); } @@ -214,6 +211,7 @@ static ImmutableHolidayCalendar generateParis() { // data sources // https://www.feiertagskalender.ch/index.php?geo=3122&klasse=3&jahr=2017&hl=en // http://jollyday.sourceforge.net/data/de.html + // http://en.boerse-frankfurt.de/basics-marketplaces-tradingcalendar2019 static ImmutableHolidayCalendar generateFrankfurt() { List holidays = new ArrayList<>(2000); for (int year = 1950; year <= 2099; year++) { @@ -231,6 +229,7 @@ static ImmutableHolidayCalendar generateFrankfurt() { // Wed before the Sunday that is 2 weeks before first advent, which is 4th Sunday before Christmas holidays.add(date(year, 12, 25).with(previous(SUNDAY)).minusWeeks(6).minusDays(4)); // repentance } + holidays.add(date(year, 12, 24)); // christmas eve holidays.add(date(year, 12, 25)); // christmas day holidays.add(date(year, 12, 26)); // saint stephen holidays.add(date(year, 12, 31)); // new year @@ -494,6 +493,7 @@ static ImmutableHolidayCalendar generateNewYorkStockExchange() { // http://www8.cao.go.jp/chosei/shukujitsu/gaiyou.html (law) // http://www.nao.ac.jp/faq/a0301.html (equinox) // http://eco.mtk.nao.ac.jp/koyomi/faq/holiday.html.en + // https://www.jpx.co.jp/english/announce/market-holidays.html static ImmutableHolidayCalendar generateTokyo() { List holidays = new ArrayList<>(2000); for (int year = 1950; year <= 2099; year++) { @@ -545,7 +545,7 @@ static ImmutableHolidayCalendar generateTokyo() { } // mountain if (year >= 2016) { - holidays.add(bumpSunToMon(date(year, 8, 11))); + holidays.add(bumpSunAndTueToMon(date(year, 8, 11))); } // aged if (year >= 2003) { @@ -571,10 +571,13 @@ static ImmutableHolidayCalendar generateTokyo() { holidays.add(bumpSunToMon(date(year, 11, 3))); // labor (from 1948) holidays.add(bumpSunToMon(date(year, 11, 23))); - // emperor (current emporer) - if (year >= 1990) { + // emperor (current emporer birthday) + if (year >= 1990 && year < 2019) { holidays.add(bumpSunToMon(date(year, 12, 23))); } + if (year >= 2020) { + holidays.add(bumpSunToMon(date(year, 2, 23))); + } // new years eve - bank of Japan, but not national holiday holidays.add(bumpSunToMon(date(year, 12, 31))); } @@ -582,6 +585,10 @@ static ImmutableHolidayCalendar generateTokyo() { holidays.add(date(1989, 2, 24)); // funeral showa holidays.add(date(1990, 11, 12)); // enthrone akihito holidays.add(date(1993, 6, 9)); // marriage naruhito + holidays.add(date(2019, 4, 30)); // abdication + holidays.add(date(2019, 5, 1)); // accession + holidays.add(date(2019, 5, 2)); // accession + holidays.add(date(2019, 10, 22)); // enthronement removeSatSun(holidays); return ImmutableHolidayCalendar.of(HolidayCalendarIds.JPTO, holidays, SATURDAY, SUNDAY); } @@ -820,6 +827,9 @@ private static void newZealand(List holidays, int year) { // http://isap.sejm.gov.pl/DetailsServlet?id=WDU19510040028 and linked pages // https://www.gpw.pl/dni_bez_sesji_en // http://jollyday.sourceforge.net/data/pl.html + // https://www.gpw.pl/session-details + // https://www.gpw.pl/news?cmn_id=107609&title=No+exchange+trading+session+on+12+November+2018 + // https://www.gpw.pl/news?cmn_id=107794&title=December+24%2C+2018+-+Closing+day static ImmutableHolidayCalendar generateWarsaw() { // holiday law dates from 1951, but don't know situation before then, so ignore 1951 date List holidays = new ArrayList<>(2000); @@ -830,8 +840,6 @@ static ImmutableHolidayCalendar generateWarsaw() { if (year < 1961 || year >= 2011) { holidays.add(date(year, 1, 6)); } - // good friday - holidays.add(easter(year).minusDays(2)); // easter monday holidays.add(easter(year).plusDays(1)); // state @@ -1010,6 +1018,7 @@ static ImmutableHolidayCalendar generateJohannesburg() { // https://englishhungary.wordpress.com/2012/01/15/bridge-days/ // http://www.ucmsgroup.hu/newsletter/public-holiday-and-related-work-schedule-changes-in-2015/ // http://www.ucmsgroup.hu/newsletter/public-holiday-and-related-work-schedule-changes-in-2014/ + // https://www.bse.hu/Products-and-Services/Trading-information/tranding-calendar-2019 static ImmutableHolidayCalendar generateBudapest() { List holidays = new ArrayList<>(2000); Set workDays = new HashSet<>(500); @@ -1035,6 +1044,7 @@ static ImmutableHolidayCalendar generateBudapest() { // all saints day addDateWithHungarianBridging(date(year, 11, 1), -3, 1, holidays, workDays); // christmas + holidays.add(date(year, 12, 24)); holidays.add(date(year, 12, 25)); holidays.add(date(year, 12, 26)); if (date(year, 12, 25).getDayOfWeek() == TUESDAY) { @@ -1240,6 +1250,17 @@ private static LocalDate bumpSunToMon(LocalDate date) { return date; } + // bump Sunday & Tuesday to the Monday + private static LocalDate bumpSunAndTueToMon(LocalDate date) { + if (date.getDayOfWeek() == SUNDAY) { + return date.plusDays(1); + } + if (date.getDayOfWeek() == TUESDAY) { + return date.minusDays(1); + } + return date; + } + // bump to Saturday to Friday and Sunday to Monday private static LocalDate bumpToFriOrMon(LocalDate date) { if (date.getDayOfWeek() == SATURDAY) { @@ -1296,22 +1317,6 @@ private static void removeSatSun(List holidays) { holidays.removeIf(date -> date.getDayOfWeek() == SATURDAY || date.getDayOfWeek() == SUNDAY); } - // apply bridging (Mon/Fri are holidays if Tue/Thu are) - private static void applyBridging(List holidays) { - Set additional1 = holidays.stream() - .filter(date -> date.getDayOfWeek() == TUESDAY && - !MonthDay.from(date).equals(MonthDay.of(1, 1))) - .map(date -> date.minusDays(1)) - .collect(toSet()); - Set additional2 = holidays.stream() - .filter(date -> date.getDayOfWeek() == THURSDAY && - !MonthDay.from(date).equals(MonthDay.of(12, 26))) - .map(date -> date.plusDays(1)) - .collect(toSet()); - holidays.addAll(additional1); - holidays.addAll(additional2); - } - // calculate easter day by Delambre static LocalDate easter(int year) { int a = year % 19; diff --git a/modules/basics/src/main/resources/com/opengamma/strata/basics/date/GlobalHolidayCalendars.bin b/modules/basics/src/main/resources/com/opengamma/strata/basics/date/GlobalHolidayCalendars.bin index 11470d7170..d3b35b19bd 100644 Binary files a/modules/basics/src/main/resources/com/opengamma/strata/basics/date/GlobalHolidayCalendars.bin and b/modules/basics/src/main/resources/com/opengamma/strata/basics/date/GlobalHolidayCalendars.bin differ diff --git a/modules/basics/src/test/java/com/opengamma/strata/basics/date/GlobalHolidayCalendarsTest.java b/modules/basics/src/test/java/com/opengamma/strata/basics/date/GlobalHolidayCalendarsTest.java index 881c152344..db22e2bf81 100644 --- a/modules/basics/src/test/java/com/opengamma/strata/basics/date/GlobalHolidayCalendarsTest.java +++ b/modules/basics/src/test/java/com/opengamma/strata/basics/date/GlobalHolidayCalendarsTest.java @@ -289,29 +289,29 @@ public void test_gblo(int year, List holidays) { public static Object[][] data_frpa() { return new Object[][] { // dates not shifted if fall on a weekend - {2003, mds(2003, md(1, 1), md(4, 18), md(4, 21), md(5, 1), md(5, 2), md(5, 8), md(5, 9), md(5, 29), md(5, 30), - md(6, 9), md(7, 14), md(8, 15), md(11, 1), md(11, 10), md(11, 11), md(12, 25), md(12, 26))}, - {2004, mds(2004, md(1, 1), md(1, 2), md(4, 9), md(4, 12), md(5, 1), md(5, 8), md(5, 20), md(5, 21), md(5, 31), - md(7, 14), md(8, 15), md(11, 1), md(11, 11), md(11, 12), md(12, 25), md(12, 26))}, - {2005, mds(2005, md(1, 1), md(3, 25), md(3, 28), md(5, 1), md(5, 5), md(5, 6), md(5, 8), - md(7, 14), md(7, 15), md(8, 15), md(10, 31), md(11, 1), md(11, 11), md(12, 25), md(12, 26))}, - {2006, mds(2006, md(1, 1), md(4, 14), md(4, 17), md(5, 1), md(5, 8), md(5, 25), md(5, 26), - md(7, 14), md(8, 14), md(8, 15), md(11, 1), md(11, 11), md(12, 25), md(12, 26))}, - {2007, mds(2007, md(1, 1), md(4, 6), md(4, 9), md(4, 30), md(5, 1), md(5, 7), md(5, 8), md(5, 17), md(5, 18), - md(7, 14), md(8, 15), md(11, 1), md(11, 2), md(11, 11), md(12, 24), md(12, 25), md(12, 26))}, - {2008, mds(2008, md(1, 1), md(3, 21), md(3, 24), md(5, 1), md(5, 2), md(5, 8), md(5, 9), md(5, 12), md(5, 24), - md(7, 14), md(8, 15), md(11, 1), md(11, 10), md(11, 11), md(12, 25), md(12, 26))}, - - {2012, mds(2012, md(1, 1), md(4, 6), md(4, 9), md(4, 30), md(5, 1), md(5, 7), md(5, 8), md(5, 17), md(5, 18), - md(5, 28), md(7, 14), md(8, 15), md(11, 1), md(11, 2), md(11, 10), md(11, 11), md(12, 24), md(12, 25), md(12, 26))}, - {2013, mds(2013, md(1, 1), md(3, 29), md(4, 1), md(5, 1), md(5, 8), md(5, 9), md(5, 10), md(5, 20), - md(7, 14), md(8, 15), md(8, 16), md(11, 1), md(11, 11), md(12, 25), md(12, 26))}, - {2014, mds(2014, md(1, 1), md(4, 18), md(4, 21), md(5, 1), md(5, 2), md(5, 8), md(5, 9), md(5, 29), md(5, 30), - md(6, 9), md(7, 14), md(8, 15), md(11, 1), md(11, 10), md(11, 11), md(12, 25), md(12, 26))}, - {2015, mds(2015, md(1, 1), md(1, 2), md(4, 3), md(4, 6), md(5, 1), md(5, 8), md(5, 14), md(5, 15), md(5, 25), - md(7, 13), md(7, 14), md(8, 15), md(11, 1), md(11, 11), md(12, 25), md(12, 26))}, - {2016, mds(2016, md(1, 1), md(3, 25), md(3, 28), md(5, 1), md(5, 5), md(5, 6), md(5, 8), md(5, 16), - md(7, 14), md(7, 15), md(8, 15), md(10, 31), md(11, 1), md(11, 11), md(12, 25), md(12, 26))}, + {2003, mds(2003, md(1, 1), md(4, 18), md(4, 21), md(5, 1), md(5, 8), md(5, 29), + md(6, 9), md(7, 14), md(8, 15), md(11, 1), md(11, 11), md(12, 25), md(12, 26))}, + {2004, mds(2004, md(1, 1), md(4, 9), md(4, 12), md(5, 1), md(5, 8), md(5, 20), md(5, 31), + md(7, 14), md(8, 15), md(11, 1), md(11, 11), md(12, 25), md(12, 26))}, + {2005, mds(2005, md(1, 1), md(3, 25), md(3, 28), md(5, 1), md(5, 5), md(5, 8), + md(7, 14), md(8, 15), md(11, 1), md(11, 11), md(12, 25), md(12, 26))}, + {2006, mds(2006, md(1, 1), md(4, 14), md(4, 17), md(5, 1), md(5, 8), md(5, 25), + md(7, 14), md(8, 15), md(11, 1), md(11, 11), md(12, 25), md(12, 26))}, + {2007, mds(2007, md(1, 1), md(4, 6), md(4, 9), md(5, 1), md(5, 8), md(5, 17), + md(7, 14), md(8, 15), md(11, 1), md(11, 11), md(12, 25), md(12, 26))}, + {2008, mds(2008, md(1, 1), md(3, 21), md(3, 24), md(5, 1), md(5, 8), md(5, 12), md(5, 24), + md(7, 14), md(8, 15), md(11, 1), md(11, 11), md(12, 25), md(12, 26))}, + + {2012, mds(2012, md(1, 1), md(4, 6), md(4, 9), md(5, 1), md(5, 8), md(5, 17), + md(5, 28), md(7, 14), md(8, 15), md(11, 1), md(11, 11), md(12, 25), md(12, 26))}, + {2013, mds(2013, md(1, 1), md(3, 29), md(4, 1), md(5, 1), md(5, 8), md(5, 9), md(5, 20), + md(7, 14), md(8, 15), md(11, 1), md(11, 11), md(12, 25), md(12, 26))}, + {2014, mds(2014, md(1, 1), md(4, 18), md(4, 21), md(5, 1), md(5, 8), md(5, 29), + md(6, 9), md(7, 14), md(8, 15), md(11, 1), md(11, 11), md(12, 25), md(12, 26))}, + {2015, mds(2015, md(1, 1), md(4, 3), md(4, 6), md(5, 1), md(5, 8), md(5, 14), md(5, 25), + md(7, 14), md(8, 15), md(11, 1), md(11, 11), md(12, 25), md(12, 26))}, + {2016, mds(2016, md(1, 1), md(3, 25), md(3, 28), md(5, 1), md(5, 5), md(5, 8), md(5, 16), + md(7, 14), md(8, 15), md(11, 1), md(11, 11), md(12, 25), md(12, 26))}, }; } @@ -334,9 +334,9 @@ public static Object[][] data_defr() { return new Object[][] { // dates not shifted if fall on a weekend {2014, mds(2014, md(1, 1), md(4, 18), md(4, 21), md(5, 1), md(5, 29), md(6, 9), md(6, 19), - md(10, 3), md(12, 25), md(12, 26), md(12, 31))}, + md(10, 3), md(12, 24), md(12, 25), md(12, 26), md(12, 31))}, {2015, mds(2015, md(1, 1), md(4, 3), md(4, 6), md(5, 1), md(5, 14), md(5, 25), md(6, 4), - md(10, 3), md(12, 25), md(12, 26), md(12, 31))}, + md(10, 3), md(12, 24), md(12, 25), md(12, 26), md(12, 31))}, {2016, mds(2016, md(1, 1), md(3, 25), md(3, 28), md(5, 1), md(5, 5), md(5, 16), md(5, 26), md(10, 3), md(12, 25), md(12, 26), md(12, 31))}, {2017, mds(2017, md(1, 1), md(4, 14), md(4, 17), md(5, 1), md(5, 25), md(6, 5), md(6, 15), @@ -1066,17 +1066,17 @@ public void test_nzbd(int year, List holidays) { public static Object[][] data_plwa() { // based on government law data and stock exchange holidays return new Object[][] { - {2013, mds(2013, md(1, 1), md(3, 29), md(4, 1), + {2013, mds(2013, md(1, 1), md(4, 1), md(5, 1), md(5, 3), md(5, 30), md(8, 15), md(11, 1), md(11, 11), md(12, 24), md(12, 25), md(12, 26))}, - {2014, mds(2014, md(1, 1), md(1, 6), md(4, 18), md(4, 21), + {2014, mds(2014, md(1, 1), md(1, 6), md(4, 21), md(5, 1), md(6, 19), md(8, 15), md(11, 11), md(12, 24), md(12, 25), md(12, 26))}, - {2015, mds(2015, md(1, 1), md(1, 6), md(4, 3), md(4, 6), + {2015, mds(2015, md(1, 1), md(1, 6), md(4, 6), md(5, 1), md(6, 4), md(11, 11), md(12, 24), md(12, 25), md(12, 31))}, - {2016, mds(2016, md(1, 1), md(1, 6), md(3, 25), md(3, 28), + {2016, mds(2016, md(1, 1), md(1, 6), md(3, 28), md(5, 3), md(5, 26), md(8, 15), md(11, 1), md(11, 11), md(12, 26))}, - {2017, mds(2017, md(1, 6), md(4, 14), md(4, 17), + {2017, mds(2017, md(1, 6), md(4, 17), md(5, 1), md(5, 3), md(6, 15), md(8, 15), md(11, 1), md(12, 25), md(12, 26))}, - {2018, mds(2018, md(1,1), md(1,6), md(3,30), md(4,1), md(4,2), md(5,1), md(5,3), + {2018, mds(2018, md(1, 1), md(1, 6), md(4, 1), md(4, 2), md(5, 1), md(5, 3), md(5,20), md(5,31), md(8,15), md(11,1), md(11,11), md(11,12), md(12,24), md(12,25), md(12,26), md(12,31))} }; }