diff --git a/modules/loader/src/main/java/com/opengamma/strata/loader/csv/FxVanillaOptionTradeCsvPlugin.java b/modules/loader/src/main/java/com/opengamma/strata/loader/csv/FxVanillaOptionTradeCsvPlugin.java index b48d22c5c7..83f680e741 100644 --- a/modules/loader/src/main/java/com/opengamma/strata/loader/csv/FxVanillaOptionTradeCsvPlugin.java +++ b/modules/loader/src/main/java/com/opengamma/strata/loader/csv/FxVanillaOptionTradeCsvPlugin.java @@ -9,6 +9,7 @@ import static com.opengamma.strata.loader.csv.CsvLoaderColumns.EXPIRY_TIME_FIELD; import static com.opengamma.strata.loader.csv.CsvLoaderColumns.EXPIRY_ZONE_FIELD; import static com.opengamma.strata.loader.csv.CsvLoaderColumns.LEG_1_CURRENCY_FIELD; +import static com.opengamma.strata.loader.csv.CsvLoaderColumns.LEG_1_DIRECTION_FIELD; import static com.opengamma.strata.loader.csv.CsvLoaderColumns.LEG_1_NOTIONAL_FIELD; import static com.opengamma.strata.loader.csv.CsvLoaderColumns.LEG_2_CURRENCY_FIELD; import static com.opengamma.strata.loader.csv.CsvLoaderColumns.LEG_2_NOTIONAL_FIELD; @@ -42,10 +43,12 @@ import com.opengamma.strata.collect.io.CsvOutput; import com.opengamma.strata.collect.io.CsvOutput.CsvRowOutputWithHeaders; import com.opengamma.strata.collect.io.CsvRow; +import com.opengamma.strata.collect.tuple.Triple; import com.opengamma.strata.loader.LoaderUtils; import com.opengamma.strata.product.Trade; import com.opengamma.strata.product.TradeInfo; import com.opengamma.strata.product.common.LongShort; +import com.opengamma.strata.product.common.PayReceive; import com.opengamma.strata.product.common.PutCall; import com.opengamma.strata.product.fx.FxSingle; import com.opengamma.strata.product.fx.FxSingleTrade; @@ -166,17 +169,31 @@ private static FxVanillaOptionTrade parseRow(CsvRow row, TradeInfo info) { LocalDate paymentDate = row.getValue(PAYMENT_DATE_FIELD, LoaderUtils::parseDate); double notional1 = row.getValue(LEG_1_NOTIONAL_FIELD, LoaderUtils::parseDouble); - double strike = parseStrike(row, notional1); - + Triple notionalStrike = parseNotionalAndStrike(row, putCall, notional1, ccy1, ccy2); Optional paymentAdj = CsvLoaderUtils .parseBusinessDayAdjustment(row, PAYMENT_DATE_CNV_FIELD, PAYMENT_DATE_CAL_FIELD) .filter(adj -> !adj.equals(BusinessDayAdjustment.NONE)); ZonedDateTime expiry = expiryDate.atTime(expiryTime).atZone(expiryZone); - CurrencyPair ccyPair = CurrencyPair.of(ccy1, ccy2); FxVanillaOption option = paymentAdj - .map(adj -> FxVanillaOption.of(longShort, expiry, ccyPair, putCall, strike, notional1, paymentDate, adj)) - .orElseGet(() -> FxVanillaOption.of(longShort, expiry, ccyPair, putCall, strike, notional1, paymentDate)); + .map(adj -> FxVanillaOption.of( + longShort, + expiry, + notionalStrike.getThird(), + putCall, + notionalStrike.getSecond(), + notionalStrike.getFirst(), + paymentDate, + adj)) + .orElseGet(() -> FxVanillaOption.of( + longShort, + expiry, + notionalStrike.getThird(), + putCall, + notionalStrike.getSecond(), + notionalStrike.getFirst(), + paymentDate)); + return FxVanillaOptionTrade.builder() .info(info) .product(option) @@ -185,13 +202,39 @@ private static FxVanillaOptionTrade parseRow(CsvRow row, TradeInfo info) { .build(); } - private static double parseStrike(CsvRow row, double notional1) { + private static Triple parseNotionalAndStrike( + CsvRow row, + PutCall putCall, + double notional1, + Currency ccy1, + Currency ccy2) { + Optional strikeOpt = row.findValue(STRIKE_FIELD, LoaderUtils::parseDouble); if (strikeOpt.isPresent()) { - return strikeOpt.get(); + return Triple.of(Math.abs(notional1), strikeOpt.get(), CurrencyPair.of(ccy1, ccy2)); } else { double notional2 = row.getValue(LEG_2_NOTIONAL_FIELD, LoaderUtils::parseDouble); - return Math.abs(notional2 / notional1); + PayReceive direction1 = row.getValue(LEG_1_DIRECTION_FIELD, LoaderUtils::parsePayReceive); + double payNotional = notional1; + double receiveNotional = notional2; + Currency payCcy = ccy1; + Currency receiveCcy = ccy2; + if (direction1.isReceive()) { + payNotional = notional2; + receiveNotional = notional1; + payCcy = ccy2; + receiveCcy = ccy1; + } + if (putCall.isCall()) { + return Triple.of( + Math.abs(receiveNotional), + Math.abs(payNotional / receiveNotional), + CurrencyPair.of(receiveCcy, payCcy)); + } + return Triple.of( + Math.abs(payNotional), + Math.abs(receiveNotional / payNotional), + CurrencyPair.of(payCcy, receiveCcy)); } } diff --git a/modules/loader/src/test/java/com/opengamma/strata/loader/csv/TradeCsvLoaderTest.java b/modules/loader/src/test/java/com/opengamma/strata/loader/csv/TradeCsvLoaderTest.java index 58797ef463..b2a05f4044 100644 --- a/modules/loader/src/test/java/com/opengamma/strata/loader/csv/TradeCsvLoaderTest.java +++ b/modules/loader/src/test/java/com/opengamma/strata/loader/csv/TradeCsvLoaderTest.java @@ -450,7 +450,7 @@ public void test_load_fx_vanilla_option_equivalent() { assertThat(loadedData.getFailures().size()).as(loadedData.getFailures().toString()).isEqualTo(0); List loadedTrades = loadedData.getValue(); - assertThat(loadedTrades).hasSize(1); + assertThat(loadedTrades).hasSize(2); FxVanillaOptionTrade expectedTrade0 = FxVanillaOptionTrade.builder() .info(TradeInfo.builder() @@ -464,8 +464,8 @@ public void test_load_fx_vanilla_option_equivalent() { .expiryTime(LocalTime.of(11, 0)) .expiryZone(ZoneId.of("Europe/London")) .underlying(FxSingle.of( - CurrencyAmount.of(USD, 30000), - FxRate.of(USD, GBP, 1.31), + CurrencyAmount.of(USD, -30000), + FxRate.of(USD, GBP, 0.8), LocalDate.of(2017, 1, 10))) .build()) .premium(AdjustablePayment.of( @@ -473,6 +473,7 @@ public void test_load_fx_vanilla_option_equivalent() { AdjustableDate.of(LocalDate.of(2016, 12, 8)))) .build(); assertBeanEquals(loadedTrades.get(0), expectedTrade0); + assertBeanEquals(loadedTrades.get(1), expectedTrade0); } //------------------------------------------------------------------------- diff --git a/modules/loader/src/test/resources/com/opengamma/strata/loader/csv/fx-option-alt.csv b/modules/loader/src/test/resources/com/opengamma/strata/loader/csv/fx-option-alt.csv index 9898538777..8848f7b399 100644 --- a/modules/loader/src/test/resources/com/opengamma/strata/loader/csv/fx-option-alt.csv +++ b/modules/loader/src/test/resources/com/opengamma/strata/loader/csv/fx-option-alt.csv @@ -1,5 +1,6 @@ -Strata Trade Type,CCP,Id Scheme,Id,Trade Date,Trade Time,Trade Zone,Convention,Buy Sell,Direction,Currency,Notional,Strike,Payment Date,Payment Date Convention,Payment Date Calendar,Far FX Rate,Far Payment Date,Long Short,Expiry Date,Expiry Time,Expiry Zone,Premium Direction,Premium Currency,Premium Amount,Premium Date,Premium Date Convention,Premium Date Calendar,Leg 1 Currency,Leg 1 Notional,Leg 2 Currency,Put Call,Barrier Type,Knock Type,Barrier Level,Rebate Amount,Rebate Currency,Rebate Direction,Leg 2 Notional -FxVanillaOption,CME,OG,tradeId32,06/12/2016,,,,,,,,1.31,10/01/2017,,,,,Long,08/01/2017,11:00,Europe/London,Pay,GBP,2000,08/12/2016,,,USD,30000,GBP,Call,,,,,, -FxSingleBarrierOption,,,,,,,,,,,,1.1,2014-05-13,,,,,Short,2014-05-09,13:10,Z,Receive,USD,230.3,2014-01-12,,,EUR,1000000,USD,Call,Up,KnockIn,17.2,17.666,USD,Receive, -FxSingleBarrierOption,,,,,,,,,,,,1.1,2014-05-13,,,,,Short,2014-05-09,13:10,Z,Receive,USD,230.3,2014-01-12,,,EUR,1000000,USD,Call,Down,KnockOut,17.2,,, -FxSingleBarrierOption,,,,,,,,,,,,,2014-05-13,,,,,Short,2014-05-09,13:10,Z,Receive,USD,230.3,2014-01-12,,,EUR,1000000,USD,Call,Down,KnockOut,17.2,,,,1100000 +Strata Trade Type,CCP,Id Scheme,Id,Trade Date,Trade Time,Trade Zone,Convention,Buy Sell,Direction,Currency,Notional,Strike,Payment Date,Payment Date Convention,Payment Date Calendar,Far FX Rate,Far Payment Date,Long Short,Expiry Date,Expiry Time,Expiry Zone,Premium Direction,Premium Currency,Premium Amount,Premium Date,Premium Date Convention,Premium Date Calendar,Leg 1 Currency,Leg 1 Notional,Leg 2 Currency,Put Call,Barrier Type,Knock Type,Barrier Level,Rebate Amount,Rebate Currency,Rebate Direction,Leg 2 Notional,Leg 1 Direction,Leg 2 Direction +FxVanillaOption,CME,OG,tradeId32,06/12/2016,,,,,,,,0.8,10/01/2017,,,,,Long,08/01/2017,11:00,Europe/London,Pay,GBP,2000,08/12/2016,,,USD,30000,GBP,Put,,,,,,,, +FxSingleBarrierOption,,,,,,,,,,,,1.1,2014-05-13,,,,,Short,2014-05-09,13:10,Z,Receive,USD,230.3,2014-01-12,,,EUR,1000000,USD,Call,Up,KnockIn,17.2,17.666,USD,Receive,,, +FxSingleBarrierOption,,,,,,,,,,,,1.1,2014-05-13,,,,,Short,2014-05-09,13:10,Z,Receive,USD,230.3,2014-01-12,,,EUR,1000000,USD,Call,Down,KnockOut,17.2,,,,, +FxSingleBarrierOption,,,,,,,,,,,,,2014-05-13,,,,,Short,2014-05-09,13:10,Z,Receive,USD,230.3,2014-01-12,,,EUR,1000000,USD,Call,Down,KnockOut,17.2,,,,1100000,Receive,Pay +FxVanillaOption,CME,OG,tradeId32,06/12/2016,,,,,,,,,10/01/2017,,,,,Long,08/01/2017,11:00,Europe/London,Pay,GBP,2000,08/12/2016,,,GBP,24000,USD,Put,,,,,,,30000,Receive,Pay