diff --git a/examples/src/main/java/com/opengamma/strata/examples/SwapPricingExample.java b/examples/src/main/java/com/opengamma/strata/examples/SwapPricingExample.java
index f8193e3062..c28004cd86 100644
--- a/examples/src/main/java/com/opengamma/strata/examples/SwapPricingExample.java
+++ b/examples/src/main/java/com/opengamma/strata/examples/SwapPricingExample.java
@@ -62,7 +62,12 @@
/**
* Example to illustrate using the calculation API to price a swap.
*
- * This makes use of the example market data environment.
+ * This makes use of the example market data environment. The example uses a
+ * multi-curve setup: the USD discount curve is used for discounting and the
+ * USD-LIBOR-3M curve is used for floating-rate projection. The resulting NPV
+ * is therefore not directly comparable with a single flat risk-free-rate curve
+ * used by another pricing library unless the market data and conventions are
+ * aligned first.
*/
public class SwapPricingExample {
@@ -95,7 +100,9 @@ private static void calculate(CalculationRunner runner) {
Column.of(Measures.PV01_CALIBRATED_BUCKETED),
Column.of(AdvancedMeasures.PV01_SEMI_PARALLEL_GAMMA_BUCKETED));
- // use the built-in example market data
+ // Use the built-in multi-curve example market data. USD-Disc is used for
+ // discounting and USD-3ML for USD-LIBOR-3M projection. This is not a flat
+ // 1% risk-free-rate setup.
LocalDate valuationDate = LocalDate.of(2014, 1, 22);
ExampleMarketDataBuilder marketDataBuilder = ExampleMarketData.builder();
MarketData marketData = marketDataBuilder.buildSnapshot(valuationDate);
diff --git a/modules/loader/src/main/java/com/opengamma/strata/loader/csv/SwapTradeCsvPlugin.java b/modules/loader/src/main/java/com/opengamma/strata/loader/csv/SwapTradeCsvPlugin.java
index 4aa599f505..0524e5e240 100644
--- a/modules/loader/src/main/java/com/opengamma/strata/loader/csv/SwapTradeCsvPlugin.java
+++ b/modules/loader/src/main/java/com/opengamma/strata/loader/csv/SwapTradeCsvPlugin.java
@@ -68,6 +68,7 @@
import com.opengamma.strata.product.swap.SwapTrade;
import com.opengamma.strata.product.swap.type.SingleCurrencySwapConvention;
import com.opengamma.strata.product.swap.type.XCcyIborIborSwapConvention;
+import com.opengamma.strata.product.swap.type.XCcyOvernightOvernightSwapConvention;
/**
* Loads Swap trades from CSV files.
@@ -357,10 +358,9 @@ static SwapTrade parseWithConvention(CsvRow row, TradeInfo info, ReferenceData r
Period periodToStart = periodToStartOpt.get();
Tenor tenor = tenorOpt.get();
if (fxRateOpt.isPresent()) {
- XCcyIborIborSwapConvention convention = XCcyIborIborSwapConvention.of(conventionStr);
- double notionalFlat = notional * fxRateOpt.get();
- SwapTrade trade = convention.createTrade(
- tradeDate, periodToStart, tenor, buySell, notional, notionalFlat, fixedRate, refData);
+ SwapTrade trade = createCrossCurrencySwap(
+ conventionStr, tradeDate, periodToStart, tenor, buySell, notional,
+ notional * fxRateOpt.get(), fixedRate, refData);
trade = trade.toBuilder().info(info).build();
return adjustTrade(trade, rollCnvOpt, stubCnvOpt, firstRegStartDateOpt, lastRegEndDateOpt, dateCnv, dateCalOpt);
} else {
@@ -396,15 +396,52 @@ private static SwapTrade createSwap(
Optional fxRateOpt) {
if (fxRateOpt.isPresent()) {
- XCcyIborIborSwapConvention convention = XCcyIborIborSwapConvention.of(conventionStr);
- double notionalFlat = notional * fxRateOpt.get();
- return convention.toTrade(info, startDate, endDate, buySell, notional, notionalFlat, fixedRate);
+ return createCrossCurrencySwap(
+ conventionStr, info, startDate, endDate, buySell, notional,
+ notional * fxRateOpt.get(), fixedRate);
} else {
SingleCurrencySwapConvention convention = SingleCurrencySwapConvention.of(conventionStr);
return convention.toTrade(info, startDate, endDate, buySell, notional, fixedRate);
}
}
+ private static SwapTrade createCrossCurrencySwap(
+ String conventionStr,
+ LocalDate tradeDate,
+ Period periodToStart,
+ Tenor tenor,
+ BuySell buySell,
+ double notionalSpreadLeg,
+ double notionalFlatLeg,
+ double spread,
+ ReferenceData refData) {
+
+ if (XCcyIborIborSwapConvention.extendedEnum().lookupAll().containsKey(conventionStr)) {
+ return XCcyIborIborSwapConvention.of(conventionStr).createTrade(
+ tradeDate, periodToStart, tenor, buySell, notionalSpreadLeg, notionalFlatLeg, spread, refData);
+ }
+ return XCcyOvernightOvernightSwapConvention.of(conventionStr).createTrade(
+ tradeDate, periodToStart, tenor, buySell, notionalSpreadLeg, notionalFlatLeg, spread, refData);
+ }
+
+ private static SwapTrade createCrossCurrencySwap(
+ String conventionStr,
+ TradeInfo info,
+ LocalDate startDate,
+ LocalDate endDate,
+ BuySell buySell,
+ double notionalSpreadLeg,
+ double notionalFlatLeg,
+ double spread) {
+
+ if (XCcyIborIborSwapConvention.extendedEnum().lookupAll().containsKey(conventionStr)) {
+ return XCcyIborIborSwapConvention.of(conventionStr).toTrade(
+ info, startDate, endDate, buySell, notionalSpreadLeg, notionalFlatLeg, spread);
+ }
+ return XCcyOvernightOvernightSwapConvention.of(conventionStr).toTrade(
+ info, startDate, endDate, buySell, notionalSpreadLeg, notionalFlatLeg, spread);
+ }
+
// adjust trade based on additional fields specified
private static SwapTrade adjustTrade(
SwapTrade trade,
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 41df48bc69..c3aa46a982 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
@@ -168,7 +168,7 @@
public class TradeCsvLoaderTest {
private static final ReferenceData REF_DATA = ReferenceData.standard();
- private static final int NUMBER_SWAPS = 11;
+ private static final int NUMBER_SWAPS = 12;
private static final ResourceLocator FILE =
ResourceLocator.of("classpath:com/opengamma/strata/loader/csv/trades.csv");
@@ -745,6 +745,13 @@ public void test_load_swap() {
assertBeanEquals(expected8, filtered.get(8));
assertBeanEquals(expected9, filtered.get(9));
assertBeanEquals(expected10, filtered.get(10));
+ SwapTrade overnightSwap = filtered.get(11);
+ assertThat(overnightSwap.getInfo().getId().get().getValue()).isEqualTo("123422");
+ assertThat(overnightSwap.getProduct().getLegs()).hasSize(2);
+ assertThat(overnightSwap.getProduct().getLegs().get(0).getCurrency()).isEqualTo(EUR);
+ assertThat(overnightSwap.getProduct().getLegs().get(1).getCurrency()).isEqualTo(USD);
+ assertThat(overnightSwap.getProduct().getLegs().get(0).getPayReceive()).isEqualTo(PAY);
+ assertThat(overnightSwap.getProduct().getLegs().get(1).getPayReceive()).isEqualTo(RECEIVE);
checkRoundtrip(
SwapTrade.class,
@@ -759,7 +766,8 @@ public void test_load_swap() {
expected7,
expected8,
expected9,
- expected10);
+ expected10,
+ overnightSwap);
}
private SwapTrade expectedSwap0() {
@@ -2315,7 +2323,7 @@ public void test_load_filtered() {
ImmutableList.of(FILE.getCharSource()), ImmutableList.of(FraTrade.class, TermDepositTrade.class));
assertThat(trades.getValue()).hasSize(6);
- assertThat(trades.getFailures()).hasSize(29);
+ assertThat(trades.getFailures()).hasSize(30);
assertThat(trades.getFailures().get(0).getMessage()).isEqualTo(
"Trade type not allowed " + SwapTrade.class.getName() + ", only these types are supported: FraTrade, TermDepositTrade");
}
diff --git a/modules/loader/src/test/resources/com/opengamma/strata/loader/csv/trades.csv b/modules/loader/src/test/resources/com/opengamma/strata/loader/csv/trades.csv
index 07687db0b1..e640046462 100644
--- a/modules/loader/src/test/resources/com/opengamma/strata/loader/csv/trades.csv
+++ b/modules/loader/src/test/resources/com/opengamma/strata/loader/csv/trades.csv
@@ -19,6 +19,7 @@ Variable,,,,,,,,,,,,,,,,,,01/06/2018,,,,,,,,,,,,,,2500000,,,,,,,,,,,,,,,,,,,,,,,
Swap,OG,123419,01/06/2017,,,,,,,,,,,,,,,,,,,,Pay,01/07/2017,01/07/2018,,,1T,BRL,1000000,1.3,,BUS/252,,,Receive,01/07/2017,01/07/2018,1T,BRL,1000000,BRL-CDI,OvernightCompoundedAnnualRate,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
Swap,OG,123420,01/06/2017,,,,,,,,,,,,,,,,,,,,Pay,01/07/2017,01/07/2018,,,1T,BRL,2000000,1.5,,BUS/252,,,Receive,01/07/2017,01/07/2018,1T,BRL,2000000,BRL-CDI,OvernightCompoundedAnnualRate,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
Swap,OG,123421,01/06/2017,,,,,,,,,,,,,,,,,,,,Pay,01/07/2017,01/07/2018,,,1T,BRL,3000000,1.7,,BUS/252,,,Receive,01/07/2017,01/07/2018,1T,BRL,3000000,BRL-CDI,Compounded,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
+Swap,OG,123422,01/06/2017,,,,EUR-ESTR-3M-USD-SOFR-3M,Buy,,P3Y,,,0.6,1.25,,,2000000,05/07/2017,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
Swaption,OG,123411,01/06/2017,,,,GBP-FIXED-1Y-LIBOR-3M,Buy,P1M,P5Y,,,0.4,,,,2000000,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,Long,ParYield,03/07/2017,30/06/2017,11:00,Europe/London,Pay,GBP,1000,03/06/2017,,,,,,,,,,,,,,,,,,,,,
Swaption,OG,123412,01/06/2017,,,,GBP-FIXED-6M-LIBOR-6M,BUY,,,,,-0.01,,,,3100000,01/08/2017,01/08/2022,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,Short,Physical,,30/06/2017,11:00,Europe/London,Receive,GBP,1000,03/06/2017,,,,,,,,,,,,,,,,,,,,,