Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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<Double, Double, CurrencyPair> notionalStrike = parseNotionalAndStrike(row, putCall, notional1, ccy1, ccy2);
Optional<BusinessDayAdjustment> 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)
Expand All @@ -185,13 +202,39 @@ private static FxVanillaOptionTrade parseRow(CsvRow row, TradeInfo info) {
.build();
}

private static double parseStrike(CsvRow row, double notional1) {
private static Triple<Double, Double, CurrencyPair> parseNotionalAndStrike(
CsvRow row,
PutCall putCall,
double notional1,
Currency ccy1,
Currency ccy2) {

Optional<Double> 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));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -450,7 +450,7 @@ public void test_load_fx_vanilla_option_equivalent() {
assertThat(loadedData.getFailures().size()).as(loadedData.getFailures().toString()).isEqualTo(0);

List<FxVanillaOptionTrade> loadedTrades = loadedData.getValue();
assertThat(loadedTrades).hasSize(1);
assertThat(loadedTrades).hasSize(2);

FxVanillaOptionTrade expectedTrade0 = FxVanillaOptionTrade.builder()
.info(TradeInfo.builder()
Expand All @@ -464,15 +464,16 @@ 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(
CurrencyAmount.of(GBP, -2000),
AdjustableDate.of(LocalDate.of(2016, 12, 8))))
.build();
assertBeanEquals(loadedTrades.get(0), expectedTrade0);
assertBeanEquals(loadedTrades.get(1), expectedTrade0);
}

//-------------------------------------------------------------------------
Expand Down
Original file line number Diff line number Diff line change
@@ -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