FX Forward Valuation

I would like to calculate the value of an FX Forward trade at a specific point in time after the trade date. Can someone point me to an example?

I have read the correct statement that an FX Forward is a simpler case of an FX Swap. The difference is that in an FX Forward only one trade is made (whereas a Swap consists of several payments at different points in time).

I have also read that the example from the Test-Class CalibrationZeroRateUsdEur2OisFxTest can be used for that purpose. I have tried and rebuilt this example, but to me it is not clear how or where I can define the valuation date, that is, the date for which I want to calculate the present value.

Some guidance, hints, and maybe a complete working example would be greatly appreciated.

Edit: Another quick question. I took a look at the examples and wonder why in the following two lines of code two different dates are used:
14.09.2014 at Line 104
15.09.2014 at Line 111

Shouldn’t both dates represent the same, that is, the settlement date of the trade?

FWIW, I have an example calculation of the present value of a trade. The example is an EUR/USD FX Forward trade and to calculate the NPV it uses an interpolated EUR-LIBOR Zero Rate and an interpolated USD-Libor Zero Rate. As interpolation points the reference interest rates for 2M and 3M are used.

Is there an example of an NPV calculation with a similar methodology in Strata?

An FX forward is a trade where the two counterparties exchange the same amount in two different currencies at a date in the future. If the date is today, it is known as an FX spot. In Strata, the two are modelled together as FxSingle.

An FX swap involves two exchanges, one at the start of the contract and one at the end. There are no intermediate exchanges. In Strata this is modelled using FxSwap.

A Cross-Currency swap is a general purpose swap in more than one currency, which typically has multiple payments on a regular schedule. In Strata this is modelled using Swap.

In FxPricingExample you note that the two dates are different. This doesn’t actually matter as the settlement date is not used in the pricing calculation. It is only used in the output table.

FxPricingExample does contain a complete example for pricing an FxSingle in the future, where the trades are created in code and the market data passed in from elsewhere.

The class CalibrationXCcyCheckExample is our closest example for calibrating the curves you describe. As you examine the code, you’ll see that it reads the curve setup from CSV files. To begin with, you can edit the CSV files and see how it affects the curve calibration and PV.

Hope this helps
Stephen

Thanks for the detailed reply which helps a lot. I am currently implementing, adapting and playing around with the CalibrationXCcyCheckExample example and I am more and more grasping it.

One question, though: What is the purpose of the curve-calibrations (served by the file calibrations-xccy.csv in the example)?
Or put differently: Why isn’t it enough to just provide the quotes served by quotes-xccy.csv?
Or again differently: Can the example work without using the curve calibrations? If yes, what would be the difference in the results?

EDIT:
Since I am making more and more progress and enjoy working with Strata more and more, I may add another question: I want to calculate the NPV for trades that already exist. Hence, I assume that I don’t want to create trades at the CurveNodes (as is done in CalibrationXCcyCheckExample with the line node.trade(1d, marketData, refData)). Instead I assume I want to create the trades as is done in FXPricingExample. In combination with my initially described example above (that is, the calculation of the NPV of an EUR/USD FX Forward trade with an interpolated EUR-LIBOR Zero Rate and an interpolated USD-LIBOR Zero Rate), I wonder which Curves I really need to replicate my simple example, because in contrast to that, the example CalibrationXCcyCheckExample uses five curves (1 EUR Discount curve, 1 USD discount curve, and 3 different Forward curves (1 USD-Fed-Fund, 1 USD-LIBOR 3M, 1 EURIBOR 3M).
I assume that I can get rid of the Forward Curves because the trades for which I want to calcualate the NPV already have a fixed forward rate.

Thanks for your help. Greatly appreciated.

The file calibrations-xccy.csv is one of three files needed to calibrate curves. All three are needed:

The “groups” CSV file defines the overall group of curves that are calibrated together. Each group has a unique name (and there is often only one group). Within the group, this file defines the purpose of each curve, such as whether it is used for discounting or forward rates.

The “settings” CSV file defines each curve in more detail, including how it is interpolated/extrapolated, the value it contains (such as zero rates) and the day count

The “curve nodes” CSV file such as calibrations-xccy.csv defines the actual curve nodes together with the piece of market data needed to provide the quote.

In addition to these three files, the market data quotes are also needed. BTW, these files simply get converted to Java objects, so you can write your own code to produce those objects if desired.

It is important to understand that the trades in the curve nodes are simply sample trades that correspond to the available market data. When you want to price your own trades, they need to be passed in separately. CalibrationXCcyCheckExample is misleading in this case, as it uses the trades from the curve nodes to prove that the calibration worked correctly. See FxPricingExample for a better example of creating trades and passing them in to be priced.

In general, for FX trades you only need to provide a discount curve for each currency. Strata will work out the rest. So yes, no need for forward curves unless you are pricing swaps for example.

Thanks for your reply. As you maybe can read from the “EDIT” of my last post, most of the info I already found out. I know that I have to create and price trades on my own as is dones in FxPricingExample.

My next question would just be: As I’ve said, I have this example on paper, where the NPV of an EUR/USD FX Forward trade is calculated by using interpolated LIBOR zero rates for EUR and USD, respectively. I think, that this corresponds to the discounting curves provided via the CSV file quotes-xccy.csv. I also think, that for my example, I do not need the forward curves.

Hence, my question is: Can the calculation of the NPV, as is done in my example, also be done without the forward curves (that are provided in CalibrationXCcyCheckExample)?

Thanks for your help. I think I am already there, just need to figure out some final things.

Yes, to price FX single/swap trades you only need discount curves, not forward curves.

Okay, thanks. I just tried to reverse-engineer the behavior of the pricing and manipulated the quotes of the forward curves. Interestingly, the NPV of the manually created FX Forward Trade changed. Above, you said that forward curves wouldn’t be needed in this case. Hence, I’d assume that changing the quotes of the forward curves wouldn’t influence the pricing of an FX Forward/Single trade. But it seems it does.

Can you explain this?

This is how I create the trade (similar to FxPricingExample):

    FxSingle fx = FxSingle.of(CurrencyAmount.of(EUR, 100), FxRate.of(EUR, USD, 1.72), LocalDate.of(2016, 9, 2));
Trade FXSingleTrade = FxSingleTrade.builder()
	.product(fx)
	.info(TradeInfo.builder()
		.id(StandardId.of("example", "1"))
		.addAttribute(AttributeType.DESCRIPTION, "EUR 1,000/USD @ 1.72 fwd")
		.counterparty(StandardId.of("example", "BigBankA"))
		.settlementDate(LocalDate.of(2016, 3, 2))
		.build())
	.build();

    // add trade to list of trades
    trades.Add(FXSingleTrade);

The pricing then is done like this (as in CalibrationXCcyCheckExample):

    // the columns, specifying the measures to be calculated
    List columns = ImmutableList.of(
        Column.of(Measures.PRESENT_VALUE));

    // the configuration that defines how to create the curves when a curve group is requested
    MarketDataConfig marketDataConfig = MarketDataConfig.builder()
        .add(CURVE_GROUP_NAME, curveGroupDefinition)
        .build();

    // the complete set of rules for calculating measures
    CalculationFunctions functions = StandardComponents.calculationFunctions();
    RatesMarketDataLookup ratesLookup = RatesMarketDataLookup.of(curveGroupDefinition);
    CalculationRules rules = CalculationRules.of(functions, ratesLookup);

    // calibrate the curves and calculate the results
    MarketDataRequirements reqs = MarketDataRequirements.of(rules, trades, columns, refData);
    MarketData calibratedMarketData = marketDataFactory().create(reqs, marketDataConfig, marketData, refData);
    Results results = runner.calculate(rules, trades, columns, calibratedMarketData, refData);

When you calibrated your curve, I presume you included some OIS or LIBOR type instruments in the definition of your discount curve? When you change the quotes of those, the curves will necessarily change, and thus the valuation will change.

The other factor to consider is that Strata performs multi curve calibration see the book by Henrard. This means that all the curves, discount and forward, are calibrated together. Thus a change in any input can in theory affect all the output curves.

That sounds reasonable, thanks.

If I only want to price one ‘manually’ created trade, that I create as in the FXPricingExample, I will only use discount curves, as you noted. Do the instruments provided in the type column of the discount curve calibrations have any influence on the pricing?

For instance, in the CalibrationXCcyCheckExample example the discount curve definitions (see here) contain the instruments OIS, FXS, and XCS.

My questions are:

  • Do these instruments influence the pricing of an FX Forward? If yes, how (no need to go into detail)? What value should I provide, when the curves are used to price an FX Forward / FX Single?
  • Is there a list of possible values for these instruments?
  • A more general question: Can an FX Forward be priced without curve calibration, that is, with just providing market quotes?
    • Or in other words: What is the difference between simply loading discount curves without calibration (see this file) and loading data for curve calibration?

Thank you!

I tried to calculate the NPV for an EUR/USD FX Forward trade and 2 discount curves. Unfortunately I get the following error:

An unhandled exception of type 'java.lang.IllegalStateException' occurred in StrataNet.dll

Additional information: Unable to get a value from a failure result: Failed to converge in backtracking, even after a Jacobian recalculation.Final position:[0.00937838500036448,  [and a lot of numbers follow]

My curve definitions are as follows.

groups.csv

Group Name,Curve Type,Reference,Curve Name
USD-EUR-XCCY,Discount,USD,USD-DSC
USD-EUR-XCCY,Discount,EUR,EUR-DSC

settings.csv

Curve Name,Value Type,Day Count,Interpolator,Left Extrapolator,Right Extrapolator
USD-DSC,Zero,Act/365F,Linear,Flat,Flat
EUR-DSC,Zero,Act/365F,Linear,Flat,Flat

calibrations.csv > see pastebin link here.

quotes.csv > see pastebin link here.

The trade including calibration of the curves, etc. is done as follows:

//create another trade
FxSingle fx = FxSingle.of(CurrencyAmount.of(EUR, 100), FxRate.of(EUR, USD, 1.72), LocalDate.of(2016, 9, 2));
Trade FXSingleTrade = FxSingleTrade.builder()
    .product(fx)
    .info(TradeInfo.builder()
        .id(StandardId.of("example", "1"))
        .addAttribute(AttributeType.DESCRIPTION, "EUR 1,000/USD @ 1.72 fwd")
        .counterparty(StandardId.of("example", "BigBankA"))
        .settlementDate(LocalDate.of(2016, 3, 2))
        .build())
    .build();

trades.Add(FXSingleTrade);

// the columns, specifying the measures to be calculated
List columns = ImmutableList.of(
    Column.of(Measures.PRESENT_VALUE));

// the configuration that defines how to create the curves when a curve group is requested
MarketDataConfig marketDataConfig = MarketDataConfig.builder()
    .add(CURVE_GROUP_NAME, curveGroupDefinition)
    .build();

// the complete set of rules for calculating measures
CalculationFunctions functions = StandardComponents.calculationFunctions();
RatesMarketDataLookup ratesLookup = RatesMarketDataLookup.of(curveGroupDefinition);
CalculationRules rules = CalculationRules.of(functions, ratesLookup);

// calibrate the curves and calculate the results
MarketDataRequirements reqs = MarketDataRequirements.of(rules, trades, columns, refData);
MarketData calibratedMarketData = marketDataFactory().create(reqs, marketDataConfig, marketData, refData);
Results results = runner.calculate(rules, trades, columns, calibratedMarketData, refData);
return Pair.of(trades, results);

What is going wrong here? Sorry for taking your time. I think not much is missing and I’m almost there, so your help would be greatly appreciated. Thanks!

That error occurs in calibration when the input is ill defined such that bumping the values up and down never results in a coherent set of curves. In your case, I think it is probably because you only have FX swaps and no OIS - there isn’t anything for the calibrator to meaningfully change. (with FX swaps and OIS, there is a linkage where changing one changes the other. When everything is an FX swap, that linkage doesn’t exist.) I suspect you would need to change the USD-OIS curve nodes back to being OIS trades, but unfortunately I don’t have the time to investigate fully.

Given your other questions, perhaps all you want is to create a curve rather than calibrate it. It is perfectly possible to obtain the values of a curve from elsewhere and directly create a curve as you discovered. That way you don’t need to do calibration. However, you would need to turn your quotes, which are in fact FX rates, into discount factors. (because the FX parts of Strata need discount factor curves, not FX rates)

HTH

Thanks for taking the time to reply, stephen. Your explanation makes sense to me and is really helpful. Greatly appreciated.

Just a quick question regarding your final remark: Can you point me to an example (probably in the example or test code of Strata) where ‘discount factor curves’ are used?

Thank you!

See DiscountFxForwardRates. It uses the current FX rate and the ratio of the two discount factor curves to predict the future FX rate