# Valuing a Portfolio of Multi-Currency FX Options and Producing its Value at Risk in Excel using Deriscope

The topic here is not about simple option pricing but rather about dealing with the complexity introduced by the simultaneous existence of several different currencies in the context of calculating the *Price* and *Value at Risk* of a *portfolio* of *European FX options*.

If you are not familiar with the basics of European option pricing in Excel using Deriscope, you may visit this introductory article.

I will show you a spreadsheet with **three** *European FX options*, the currencies of which can be freely set to any custom combinations.

In the simplest and wholly trivial case, all currencies may be set to equal each other. For example, I may set the underlying currency pair of each option to be the pair **USD/USD**, which is a trivial pair of zero *volatility* and a *spot FX rate* that steadily equals **1**. The ensuing options would then have a payoff equaling some fixed amount depending only on their strike and direction (call or put) and therefore would behave like zero bonds.

On the other side of the complexity spectrum, all currencies could be set to be unique and distinct from each other, which would give rise to **six** different currencies to cope with.

As a matter of fact, the number of currencies could increase to **seven** if I also require that the price of my portfolio is expressed in a still different seventh currency.

The same observation applies to the *VaR* (*Value at Risk*) report, which can be expressed in any desired currency, not necessarily in one of the currencies already referenced by the options.

The spreadsheet is built in an intelligent way so that the output immediately reflects my currency choices, without the need of any formula adjustments.

While it is not meant for production, I think its simple design – all data in a single sheet for easier view of the dependencies - can serve well the educational purpose of understanding the interplay of the currency markets in calculating the price and risk of the portfolio.

### Input Data Section

This is the driver seat of the spreadsheet.

All blue color data can be edited.

I start with a set of **seven** currencies defined in range **C6:C12** that provide the currency choices in the construction of the **three** *FX options* directly below in range **C16:E20**.

The column to the right (range **D6:D12**) contains the *spot FX rates* for the given currencies against **USD**. I could have used formulas here that return live feeds from a provider such as Bloomberg or even the Deriscope-supplied function *=dsLiveGetSync("YF","ABCUSD=X")* that outputs the real time spot rate of the currency pair **ABC/USD** as received from *Yahoo Finance*.

These rates are then used elsewhere in the spreadsheet to construct the applicable *cross FX rate* between any two currencies.

The third column (range **E6:E12**) contains the effective *flat discount interest rates* that are supposed to apply with respect to each currency. Here I have copied the short term "risk-free" rates from https://tradingeconomics.com.

This is obviously a simplification since the applicable rates will in generally depend on the respective option expiries.

The accurate treatment would have the shown entries replaced with objects of type *Yield Curve* that are produced elsewhere in the spreadsheet with respect to the shown currencies.

The range **C16:E20** defines the static data of my three options – one column per option.

The **Base Ccy** and **Quote Ccy** refer to the numerator and denominator currencies respectively in the currency pair referenced by each option.

I may choose any currencies I want here, by using the in-cell dropdowns, as shown with the cell **D17**.

I have chosen to form three options with the currency pairs **EUR/JPY, AUD/CHF, GBP/BRL** in order to deal with the maximum complexity case where all currencies are different. I do not involve **USD** here because I plan to use it later as my P&L reporting currency.

The **lowest three rows** contain editable entries that define the **expiry**, **direction** and **strike** of the options.

Finally, the **bottom row** supplies the **volatilities** of the respective currency pairs.

Although manually entered here, optimally formulas should provide the vols that are appropriate for each pair and expiry.

### Single Option Pricing Section

Still on top of the sheet and to the right of the INPUT DATA SECTION, I reserve an area for the calculation of any single option I choose to select out of the three already defined options.

I carry out my option selection in cell **H5**, where an in-cell dropdown allows me to select a number from **1** to **3**.

Here I have selected **3**, which refers to my third option, which is an option on the currency pair **GBP/BRL**.

I do not need to display the label "**GBP/BRL**" since the involved currency pair becomes immediately visible as part of the *handle name* **&GBP/BRL Option.1** shown in cell **I9**.

This represents perhaps another great aspect of Deriscope, namely the ability to give custom names to objects that visually indicate the nature of these objects. Choosing well defined names can have a big impact on the production time and maintenance of a spreadsheet!

The option NPV is computed by the formula =*ds(H9:I13)* in cell **H8** as **0.125525867**.

The dependency arrows show the relationship between this formula and the other two formulas in cells **H15** and **H21** that produce the required *Model* and *Market* inputs.

At the very bottom, the required *Market* objects are shown in **green color**.

Their *handle names* reveal their identity without the need to look up the spreadsheet section where these objects are created.

So, the first object named **&GBP Int Crv.1** refers to the interest rate yield curve associated with the currency **GBP**.

The object named **&GBP/BRL Vol Crv.1** refers to the volatility curve associated with the currency pair **GBP/BRL**.

The object named **&GBP/BRL Spot.1** refers to the *spot FX rate* associated with the currency pair **GBP/BRL**.

The spreadsheet is so designed that all these objects are automatically adjusted if I change either the options' underlying currencies or the currently treated option through the number in cell **H5**.

### Portfolio Pricing Section

Further to the right comes the PORTFOLIO PRICING SECTION, where the object **&My Pfolio.1** of type *Portfolio* is created in cell **L5** with the formula =*ds(L6:M8,L10:M13).*

The pricing formula in cell **L18** is designed to return the object **&Variant_L18:1.1** thanks to its input **Output= Full**.

Alternatively, I could have set **Output= Price** to get the price directly as a numerical output, but the **Full** choice is here more powerful because it makes the returned **&Variant_L18:1.1** object to also contain the breakdown of the portfolio value in its constituent single options, which I display below over the range **L28:P31** with the help of the array formula

=*ds("ObjectTools::Show","Reference=",$L$18,"Key=","Breakdown","ExpandFinal=",TRUE)*.

As usually, the later formula has been conveniently created with the wizard.

Both the portfolio price and the set of single option prices shown at the bottom are denominated in the report currency **USD** chosen with the help of an in-cell dropdown in cell **M16**.

If I click on cell **M16** and choose another report currency, for example **JPY**, I get the following:

### Value at Risk Section

The setup here is very similar to that used in the calculation of the portfolio price.

Given the already constructed *Portfolio* object **&My Pfolio.1**, its local function **VaR** is invoked by entering **VaR** in cell **S8** next to the *key* named **Function=**.

Precise details over how this *VaR* formula can be created using the wizard and what the meaning of its various inputs and outputs is, may be found at the *Value at Risk* article at the *Risk Management Guru* site.

I am still using the same inputs for the *keys* **Reference=, Models=** and **Markets=**, as in the pricing case.

The only new input is the pair **VaR Spec= &VaRSpec_R31:1.1** because it is required by the function **VaR**.

The object **&VaRSpec_R31:1.1** is created further below in cell **R31** and contains all specifications needed by the **VaR** algorithm. It includes the object **&SimMdl_R14:1.1**, which is created in cell **R14** and describes how the *Monte Carlo* simulation is carried out.

My most important simulation setting is the usage of a **Pseudo Random** number generator in cell **S18** and the number of **1,000** scenarios in cell **S19**.

In cell **S38** I choose a slightly elevated **Report Level** setting of **Level** **1** so that the *VaR* output appears as the object **&VaRRep_R6:1.1** of type *VaR Rep* in cell **R6**, instead of the usual single numerical result.

You can see the contents of the object **&VaRRep_R6:1.1** inside the wizard, which are automatically produced as soon as the cell **R6** gets selected.

The main result - the *VaR* itself – is shown as **0.019623385** just above the *VaR Rep* output object in cell **R5** through the simple formula (not shown in the image):

=*ds("ObjectTools::Show","Reference=",$R$6,"Key=","Report VaR")*

Note I have used only **1,000 scenarios** rather than the usual **10,000** in order to keep the calculation time short for the purpose of this demonstration.

As you see in the wizard, the calculation time here has reached **36 seconds**, which means that **10,000** scenarios would have taken around **360 seconds**, or **6 minutes**.

One possible way of improving the efficiency of the *VaR* calculation could be to switch over to a *Sobol* *quasi random* number generator by setting **Low Discrepancy** in cell **S18**.

If you read my article on *Pricing Derivatives using Quasi Monte Carlo and Parallel Processing*, you will notice that by using **Low Discrepancy** one may achieves with only **1,000 scenarios** comparable numerical accuracy as when one uses **Pseudo Random** with **10,000 scenarios**.

Just like with the portfolio *NPV*, you can compute the *VaR* denominated in any other currency.

For example, setting **JPY** in the cell **M16** that controls the chosen report currency of the portfolio *NPV*, the **Reference** currency in cell **S9** changes to **%JPY** because that latter cell is linked to **M16**.

After recalculation, the result appears as below.

It is worth to note that although the numerical *VaR* changes as expected, the percentage expressions **Report VaR%**= and **Actual VaR%**= change only minimally from **0.0753** to **0.07653**.

### Controlling the Diffusion Parameters

The most critical aspect of the *Monte Carlo*-based *VaR* calculation is the assumption regarding the number and kind of risk factors that are assumed to be stochastic and therefore are responsible for the uncertain character of the future portfolio *NPV* as of the *VaR* horizon date and thus the commensurate emergence of the *Value at Risk* concept.

In Deriscope, this fundamental assumption is part of the input *Var Spec* object **&VaRSpec_R31:1.1** and comprised by the two tables shown below:

It is up to my discretion on how to setup these two tables.

Usually – but not always - each row corresponds to one risk factor, identified by the **green color** object shown at the leftmost column.

Deriscope only requires the existence of at least one risk factor.

This means, I could have setup my two tables so that they consist of a **one** **single row** – excluding the top title row -, for example the existing shown top row linked to the *Yield Curve* object **&EUR Int Crv.1**.

If I had done that, the simulation would have run by diffusing only the **EUR** flat interest rate, while keeping all other market data constant.

Here I have instead chosen to treat all involved market data as being stochastic.

This brings the total number of risk factors to **16**.

The handle names make the identity of these **16** risk factors quite transparent.

So, the top **7 rows** clearly correspond to the *interest rates* associated with my **7** currencies.

The next **3 rows** correspond to the *volatility curves* of my 3 currency pairs.

The bottom **6 rows** correspond to the required *FX spot rates*, which obviously constitute the biggest determinants of the portfolio's risk.

In other words, all independent *FX spot rates* (**6** in total), the **7** *interest rates* and the *vols* of the involved **3** currency pairs are assumed here to be stochastic and undergo diffusions with the specified *volatilities* and *pairwise correlations*.

The entry **Parallel** on the **second column** means that the respective market data is to be diffused in a parallel sense, which means that during diffusion the whole curve is shifted up or down in a parallel fashion, and thus controlled by a single risk factor.

Deriscope supports more complex diffusions where the curve is diffused in a manner that is maturity dependent.

If I had chosen a non-parallel type of diffusion, then I would have had more than one risk factors associated with the market data on the row where the non-parallel treatment would have applied. But it is better to keep things simple for now, so that all second column entries are set to **Parallel**.

What is really important here, is the **#Vol column**, where the *volatility* of the respective diffusion is defined.

For this demonstration I have entered **0.2** (i.e. **20%**) everywhere, but in a real application I should enter the historical-based estimates of the respective volatilities.

Finally, the correlations among my **16** risk factors are specified in the *square symmetrical matrix* on the right.

Right now, this matrix is set as a *unit diagonal square matrix* because I am too lazy to search for the historical correlations among my factors. But again, in a real application the *upper-diagonal* part of this matrix should be populated with reasonable market values.

### Probability Density of Portfolio Loss

As I have described in utmost detail in the links provided above, Deriscope is capable of producing various charts, such as that of the *probability density* of the portfolio loss realized at the horizon date. This latter chart is particularly important because it relates to the essence of the *VaR* definition as the loss amount that corresponds to a specific quantile of the *loss distribution*.

All I need to do to produce the chart is to set **Report Distribution= TRUE** in the construction of my *Model[Simulation]* object in order for the *VaR* output object to include the **two-column array** that contains the **x** and **y** **coordinates** that form the source data of the *probability density* chart.

Then I simply paste – using the wizard – this array on the spreadsheet in the form of a dynamic formula linked to the source *VaR* output object and finally I use Excel's native chart facilities to create the chart.

Below you see the very simple array formula

=ds("ObjectTools::Show","Reference=",$R$6,"Key=","LossDensity","ExpandFinal=",TRUE)

which links to only one cell, the cell **R6** that contains the *VaR* output object.

This formula effectively extracts the **two-column array** associated with that object's key "**LossDensity**".

Even though this formula is self-explained and intuitive, I created it using the wizard, which is much simpler than typing the whole formula by hand.

The chart looks somewhat bumpy due to the low number (**1,000**) of scenarios.

It would have looked substantially smoother if I had used the industry standard of **10,000 **scenarios.

Click on **FxOptionAndVaR.xlsx** to download the spreadsheet produced with the above steps.

Feel free to contact me if you want to share any thoughts with regard to this product or if you want to request any particular features. Contact info and social media links are available at my web site https://www.deriscope.com