27 minutes reading time (5317 words)

Pricing FX Options in Excel using Risk Reversal and Butterfly Market Quotes. The USD / Indian Rupee Case


Back in 2017 I had shown in a 13-min video titled Option pricing in Excel with Implied Volatility Surface using QuantLib how an option on the EURO STOXX 50 index can be priced using not a single vol quote, but rather a table of market volatilities spanning several option expiries and strikes.

On this post I will turn my attention to the pricing of vanilla European FX options, where the main complexity is that the strikes of the available market volatilities are quoted as delta – or more precisely moneyness – values rather than prices of the underlying currency (i.e. FX rates).

FX options involve two currencies and can indeed be very confusing to keep track of the role of each, especially in contexts where the option holder does not have a natural affiliation with any of them. For example, a US based trader may wish to buy in the OTC markets a call option on the EUR/JPY pair and then track the P&L and sensitivities expressed in USD terms!

The understanding of FX options is greatly facilitated if one adopts a foreign-domestic point of view, whereby one currency is designated as foreign (FOR) and the other as domestic (DOM), even if the trader does not reside in any of the referenced currencies' jurisdictions. In the above example, the US trader may thus choose the association EUR = FOR and JPY = DOM or EUR = DOM and JPY = FOR, as a means to facilitate his/her intuition, although such an association has no impact on the maths and the pricing results.

Thinking of the two involved currencies as FOR and DOM, a European call option on FOR is a contract that grants its holder the right to buy N units of FOR at a certain future time T by paying (at that time T) K units of DOM per one unit of FOR, i.e. a total of NK units of DOM.

N is known as the option's notional and K as its strike.

If you are a US based trader trading JPY versus USD, you may make this definition concrete by thinking of FOR being JPY, DOM being USD and considering a specific option trade with T = 31 Jan 2023, N = 1 billion and K = 1/125 = 0.008.

Then your European call option on JPY would grant you the right to buy 1 billion JPY on 31 Jan 2023 by paying 0.008 USD per JPY, i.e. a total of 8 million USD.

This example makes also apparent the various quoting nuances that often plague the definitions of the various parameters specified in FX option contracts.

For example, the strike K may be quoted in "inverse" terms, i.e. in DOM/FOR rather than the "natural" ratio of FOR/DOM. In the current example the strike K may be quoted as 125 rather than 0.008 and – obviously – referring to the ratio USD/JPY which denotes the number of JPY units per one USD unit.

Furthermore, the notional N may be alternatively quoted by the market participants in DOM terms and thus in need of being converted to FOR terms for calculation purposes because the converted notional owes to indicate the number of units of the option's underlying currency, i.e. the FOR currency.

In the current example, the notional N may be quoted as 8 million USD in a trader's term sheet and would therefore have to be converted to a "working" notional of 1 billion JPY.

Similar confusion may arise in relation to the quoted volatilities, which may be available for one – but not both – of the currency ratios.

In our example, it may happen that market vol data are available only for options on USD/JPY. While it is mathematically true that the black vol of any FX rate equals that of its inverse rate, the fact that FX vols are delta-quoted (see below for explanation) does not allow a straightforward use of a USD/JPY market vol table for pricing a JPY/USD option. The trick here is to make use of the equivalence relationship between calls on USD/JPY and puts on JPY/USD as explained in more detail in the Inverse FX Put-Call Parity section further below.

Currency related ambiguity also occurs when the price or risk of an FX option is reported. Contrary to other option types, such as equity options, in the world of currency options any of the two involved currencies may serve as denomination to numbers that are part of a pricing report.

In our example again, the price of the JPY/USD option may be reported as the number 1,675,300, which, without a currency specifier, could equally refer to JPY or USD units.

In what follows, I will illustrate all these issues through a realistic case of a put option on the Indian currency INR with a USD strike that I have recently worked out with one of my clients. I believe, this will make all concepts much clearer rather than if I had tried to expose the various relations using the abstract currency symbols FOR and DOM. Also, the facts that the USD/INR rate is around 80 and the Indian interest rates are much higher than those in the US help us to avoid confusing one currency for the other. 

Recommended for Deriscope starters: The Overview and Quick Guide pages.  

Constructing a European Put Option on INR/USD 

The ratio INR/USD in the expression "Put Option on INR/USD" means that the option's underlying is the INR currency, and the strike is the USD currency. Had it been the inverse ratio USD/INR, the underlying would have been the USD and the strike the INR.

While several important details are still missing – such as the expiry, notional, strike etc – the "picture" of the financial product points to a contract that grants its holder the right to deliver INR in exchange for USD at a fixed ratio of INR units per USD unit.

The image below shows all the input parameters to the Deriscope Function in cell C4 that constructs a corresponding Deriscope Object

of Deriscope Type FX Option, uniquely identified by the returned handle name &Put on INR.1. 

The shown data pertain to the option's so-called "static" or "term sheet" data, the job of which is to define the terms of the financial contract. They do not contain the other two classes of data that are also needed in the calculation of the option price, namely the "dynamic" market data and the "subjective" model data.

The formula =ds(C5:D16) in cell C4 takes as input a two-column range that contains all static data in the form of key-value pairs.

Exceptionally the keys FX= and FX Payoff= take as values the handle names &USDINR.1 and &Put Payoff.1, which refer to the objects created in cells C19 and C30. While not shown on the image, the latter two cells contain the formulas =ds(C20:D27) and =ds(C31:D36) that return the handle names shown in red.

Starting with the object &USDINR.1 created in cell C19, its type is identified in cell D20 as FX and represents the ratio USD/INR because the base currency is declared to be the USD and conventionally the base currency is regarded as the numerator in a currency ratio.

As a small digression here, the ratio of two currency units is not different than the ratio of any two comparable units, such as – for example – metric units. So, just like to the ratio kg/g (kilogram/gram) may be ascribed a number (here 1000) that represents the number of g corresponding to 1 kg, so to the ratio USD/INR may be ascribed a number (for example 78) that represents the number of INR corresponding to 1 USD.

But while the ratio kg/g points always to the fixed number 1000, the same does not hold for the ratio USD/INR, to which a different numerical value is ascribed almost every second due to active FX trading.

This fact leads to the important conclusion that while the ratio kg/g can be safely assumed identical with its ascribed value of 1000, when it comes to USD/INR, it is much better to keep things separately and distinguish the definition of USD/INR in terms of an object of type FX from its ascribed numerical value, which value changes randomly over time.

The package consisting of the FX object together with a certain ascribed numerical value exists as a separate object of type FX Value and will be used later on as the conveyor of the market spot FX rate.

This conceptual distinction between the types FX and FX Value corresponds to a usage distinction, as follows:

An object of type FX is part of the static data that define the option, while an object of type FX Value is part of the dynamic (market) data that are needed in order to price the option.

It turns out that the order of the USD and INR currencies in the &USDINR.1 object does not affect the option constructed in cell C4. This is due to a few keys of which the purpose is to fix the referenced currencies regardless of how these currencies appear in &USDINR.1.

First comes the key Underl Ccy= , which sets the currency that serves as the option's underlying, which is the currency that must be delivered (since the option is a Put) at expiry, or more precisely on the payment date that is set to 2 Feb 2023, i.e. 2 business days after the option's expiry of 31 Jan 2023. Here it is assigned the value %INR, which is the handle name of a trivial object that essentially represents the currency INR.

Next comes the key Strike in FX Terms= that expects a Boolean value (TRUE or FALSE) that allows the correct interpretation of the numerical strike of 80 entered in cell D36 as part of the Payoff object &Put Payoff.1. Here it is assigned the value TRUE, which means that the number 80 ought to be understood in terms of the FX rate defined in &USDINR.1, which is the rate of the ratio USD/INR. Had that Boolean been FALSE, the given strike of 80 would have referred to the rate INR/USD, which would have made the Put extremely deep in the money since it is inconceivable that INR would appreciate relative to USD so much by 31 Jan 2023 that 1 INR unit would equal 80 USD units! Of course, Deriscope would happily process a TRUE value and without complain treat the Put option as a perfectly normal, albeit deep in the money, option.

Next in row comes the key Notional Ccy= that sets the denomination currency of the numerical amount specified under the key FX Notional=. The current setting of %USD indicates that the specified notional of 100,000,000 means 100,000,000 USD units. Note, this is contrary to the way the notional is specified in non-FX option markets, where the notional typically refers to the number of units of the underlying asset. Consistency with this latter convention here would have required the notional to have been set as 8,000,000,000 INR since the INR currency is the underlying asset. But as mentioned earlier, FX markets are flexible when it comes to choosing the preferred currency in quoting various financial parameters. One only needs to know the applicable convention and supply that convention as input to the Deriscope function.

Finally, the key Payoff Ccy= is relevant only when the payment date differs from the expiry date. Then there is a difference between treating the option as physically or cash settled. Deriscope silently assumes cash settlement, which means the option's payoff amount is first determined on the expiry date based on the then realized FX rate and subsequently paid on the designated payment date. If the latter date coincides with the expiry date, it makes no difference if the numerical payoff amount established on expiry is paid in USD or INR, provided the FX rate observed on expiry is used for the currency conversion between the two amounts. But if the payment date occurs after expiry, the currency in which the amount is actually paid does make a difference in the valuation of the option because then the vanilla option price must be multiplied with the forward discount factor from expiry to payment date as implied by the curve relative to that currency. By default, the currency entry here is set to the one of the currencies defined in the referenced FX rate that happens to differ from the already specified underlying currency. 

Displaying the Option's Terminal Payoff Amount as a Function of Terminal FX Rates

It is by now apparent that the existence of so many switches in the function that creates the FX Option object makes it a bit tricky to get everything right on the first try.

In order to build confidence that the constructed object truly represents the intended option, it is advisable to plot the implied payoff amount as a function of the FX rate realized at expiry and ensure that it indeed fits the expected profile.

In that regard, the special Deriscope function Terminal Payoff is indispensable and works as shown below: 

The formula =ds(H6:I13) in cell H5 returns an object with handle name &Put in USD vs INR/USD.1 that contains a two-column table with several terminal INR/USD FX rates along with their corresponding terminal payoff amounts as implied by the supplied option &Put on INR.1.

The data of the contained table may then be displayed on the spreadsheet with the usual Show Function, as below: 

Finally, the two columns shown above lead to the following chart:  

This chart corresponds to what one would expect from the payoff of a Put option and therefore confirms the correctness of the &Put on INR.1 object, at least with regard to its implied payoff profile.

The Terminal Payoff function has switches that allow the user to specify a different payoff currency or terminal FX rate currency ratio.

In total, there exist four possible combinations. Below are the charts corresponding to the remaining three of them: 

It is important to realize that all four charts above represent the payoff profile of the same option. The fact that they look so different from each other pays tribute to the confusion surrounding all FX related financial instruments. Only the first chart mimics what one would expect from a Put option. The last chart points to a Call option profile (more on that later) and the two remaining charts even display a non-linear payoff!  

Inverse FX Put-Call Parity 

In full generality, let s(t) be the spot FX rate FOR/DOM observed at any time t. For concreteness and easier understanding, one may think that FOR = INR and DOM = USD so that s(t) represents the INR/USD rate at time t.

Then let s΄(t) = 1/s(t) be the inverse FX rate.

If at some time t, s(t) = 0.0125 (meaning 1 INR = 0.0125 USD) then s΄(t) = 1/0.0125 = 80 (meaning 1 USD = 80 INR).

As s(t) evolves stochastically through time, s΄(t) also does, but in an inverse fashion.

For example, if s(t) happens to increase over time, s΄(t) will decrease.

Further on, if s(t) is assumed to follow a lognormal diffusion in the sense that the future and thus not-yet-realized random values of ln[s(t)] appear to an observer (market participant) at any time t₁ < t to be normally distributed (i.e. locally normally distributed), then s΄(t) will also follow a lognormal diffusion and – as a matter of fact - with the exact same volatility. The latter stems from the mathematical property that ln(1/x) = -ln(x), which means that ln[s΄(t)] = - ln[s(t)] and it should be obvious that simply changing the signs of all future random numbers cannot have any effect on the variability and thus the volatility of these numbers.

A Call option on one unit of the foreign currency INR with a certain strike K in INR/USD terms (for example K = 0.0125) establishes the USD-denominated payoff amount:

max[s(T) - K , 0] USD

that the option holder will receive at the option's expiry T.

Formally substituting s(T) with its equal 1/s΄(T) leads to:

max[1/s΄(T) - K , 0] USD.

This may be written as:

K/s΄(T) max[1/K - s΄(T) , 0] USD.

But at time T, 1 unit of USD equals s΄(T) units of INR, which allows us to substitute the currency unit of USD at the end with s΄(T)INR and get (after cancelling out the s΄(T) that appears in both the numerator and denominator):

K max[1/K - s΄(T) , 0] INR

In the prime (inverse FX rate) world, the last expression is that of the INR-denominated payoff amount of a Put option on K units of USD currency with strike equal to 1/K.

It has been thus established that a Call option on INR with strike K and notional N is equivalent to a Put option on USD with strike 1/K and notional kN.

By swapping the roles of s and s΄, the following statement holds as well:

A Put option on INR with strike K and notional N is equivalent to a Call option on USD with strike 1/K and notional kN.

The above options are equivalent in the sense that they produce the same payoff amount at expiry and as such they must also have the same price. This is not enough to also imply equality of their respective vols since the strikes are different. But the discussion above about the relation between s and s΄ leads to the conclusion that the vols are equal as well.

As an example, consider a US based trader who perceives INR as a foreign currency and buys a Put on INR from an Indian based trader with strike K = 0.0125 USD/INR and notional N = 10,000 INR.

Assume the spot FX rate at expiry T happens to be s(T) = 0.01 USD/INR.

Then the American trader will receive a net payoff amount of:

Amount received by the US trader = N max[ K - s(T) , 0 ].

After substituting the assumed values:

Amount received by the US trader = 10,000 INR ( 0.0125 USD/INR – 0.01 USD/INR ) = 10,000 INR ( 0.0025 USD/INR ) = 25 USD.

The Indian counterparty may see this transaction as if he had sold a Call on USD to a US based trader with strike K΄ = 80 INR/USD and notional N΄ = 125 USD.

At expiry, he would observe the spot FX rate s΄(T) = 100 INR/USD and would be called to pay a net payoff amount of:

Amount paid by the Indian trader = N΄ max[ s΄(T) - K΄ , 0 ].

After substituting the assumed values:

125 USD max[ 100 INR/USD - 80 INR/USD , 0 ] = 125 USD ( 20 INR/ USD ) = 2,500 INR

Note, the amount of 2,500 INR paid on T has the same worth as 25 USD paid on the same date as can be seen by dividing the 2,500 with the spot FX rate of 100.

Deriscope makes available a function named Get Equivalent Tradable that can be applied to any object of type Tradable and return another Tradablethat is deemed equivalent to the original one in a well-defined sense.

Below this function is invoked in cell AK4 and returns a new object under the handle name &Call on USD.1 that represents the Call option equivalent to the &Put on INR.1 that references the inverse FX rate USD/INR.

The contents of the new option object are identical with those of &Put on INR.1 except of the key-value pair shown in red circle that indicates that its underlying currency is now the USD rather than the INR. 

To verify the construction has indeed built the intended equivalent Call option, the Terminal Payoff function can be used to create the payoff chart, which comes out as shown below:  

Quite interestingly - but also expectedly - this plot coincides with the last of the four plots displayed above, even though the involved option is completely different.  

Collecting the Market Data: Spot FX Rate 

In order to price the Put option represented by the object &Put on INR.1, four distinct pieces of data are required:

  • 1.The spot FX rate
  • 2.The interest rate curve wrt USD
  • 3.The interest rate curve wrt INR
  • 4.The volatility surface

The first item is the simplest as it consists of essentially one number plus a few parameters that define various conventions.

Below, the formula =ds(C10:D15) in cell C9 creates an object of type FX Value (see related comments at the beginning of this post) that binds together the FX object &USDINR.1 with the number of 75.9 and the trade date of 31 Mar 2022.

The number 75.9 has been entered manually in cell D15 and equals the spot FX rate for USD/INR as of 31 Mar 2022, the date regarded as our trade date (or valuation date) and on which the price of the Put option must be produced. 

Collecting the Market Data: Interest Rate Curves 

Options on non-currency underlying assets require only the interest rate curve associated with the payoff currency. The curve then is used a) to imply the discount factor as of the date the option's payoff amount is paid, which discount factoris needed in the calculation of the discounted value of the payoff amount and b) to imply the discount factor as of the date the option is exercised, which discount factor is needed in the calculation of the forward value of the underlying asset as of that date.

In the case of currency options these two curves are different.

In our Put option on INR example, the payoff amount is paid in USD, which means the USD interest rate curve is needed to imply the corresponding USD discount factor according to a) above.

But the underlying is the INR currency, the forward value of which (relative to USD) as of the expiry date depends on both the USD and INR discount factors for that date.

From the point of view of a US based trader, it would make sense to build the required USD interest rate curve using US traded OIS and the INR interest rate curve using offshore traded NDFs (Non-Deliverable Forwards) on the USD/INR FX rate.

Below is a Bloomberg screen with the USD OIS market rates as of 31 Mar 2022: 

Below is a Bloomberg screen with the USD/INR NDF market quotes as of 31 Mar 2022:  

These market quotes are then entered in the spreadsheet as input to the Deriscope formulas in order to create the respective objects of type Yield Curve in cells C4 and K4, as shown below:  

Regarding the construction of the USD curve out of OIS rates, detailed information can be found in my post titled How to build a SOFR Yield Curve in Excel using QuantLib and Deriscope.

Regarding FX NDFs and their use in building a curve of interest rates can be found in my post titled FX Spots, Forwards, Swaps and Curves in Excel.

Collecting the Market Data: Volatility Surface 

The volatility information is the last of the market data that is required to price the Put option.

In fact, a single number – the Black vol for the given expiry of 31 Jan 2023 and strike of 80 INR/USD - would suffice to fulfil the task, but the problem is that this "magic" number is not available, as the market is not in the habit of quoting option volatilities for all conceivable expiries and strikes!

The situation is far worse as there is not even a single strike for which the corresponding vol is quoted. Typically, the market FX option vol quotes consist of three – sometimes more – columns, one of which provides the ATM (At-The-Money) volatilities and the other two provide not vols, but vol related quotes referred as RR (Risk Reversal) and BF (Butterfly) quotes.

The links here provide the respective definitions and explanations of these two quote types.

Here it suffices to provide the bare formulas that define the RR and BF quotes in relation to some pre-agreed delta level Δ (typically set to 0.25), as follows:

RR quote = σʳʳ = σᶜ - σᵖ

BF quote = σᵇᶠ = (σᶜ + σᵖ)/2 - σᵃᵗᵐ


σᶜ is the implied volatility of a European Call that has delta equal to Δ

σᵖ is the implied volatility of a European Put that has delta equal to -Δ

These two equations can be solved for σᶜ and σᵖ, to give:

σᶜ = σᵃᵗᵐ + σᵇᶠ + ½ σʳʳ

σᵖ = σᵃᵗᵐ + σᵇᶠ - ½ σʳʳ

A first step in building the vol surface consists of finding out the three strikes Kᵃᵗᵐ , Kᶜ , Kᵖ that correspond to these vols so that the three pairs (Kᵃᵗᵐ , σᵃᵗᵐ) , (Kᶜ , σᶜ) , (Kᵖ , σᵖ) become available for further processing.

Regarding my data source, I will be using the data shown below, acquired from FIMMDA:

The STR in the last column refers to Strangle, which is another term for Butterfly.

It is important to note that these data pertain to USD/INR, i.e. the ATM, Call and Put options underlying the definitions of the shown quotes are options on USD regarded as the foreign currency. This distinction makes no difference with regard to the ATM quotes since an ATM USD/INR option is also an ATM INR/USD option, at least for most ATM definitions. But the RR and BF quotes do not carry over to their inverse FX counterparts without adjustment.

Putting everything together, the vol surface for the FX rate USD/INR is created as an object named &DeltaVolCrv.1 of type Vol Curve in cell C4 below:

The Vol Curve type is generic and designed to represent single volatilities, but also volatility curves, surfaces or cubes for diverse types of financial variables, such as equity prices, swap rates and – as in the case here – FX rates.

Deriscope "understands" that this particular Vol Curve deals with FX rates because of the key-value input Vol Input= ATM-RR-BF.

The link stated here provides detailed information on how the vol surface is constructed using ATM, RR and BF market quotes.

The object &VolSpec.1 created in cell J15 conveys to the vol surface construction routine the user's choices regarding how the ATM and Delta concepts are defined.

Deriscope supports the following ATM definitions:

Delta 50

Delta Neutral


Gamma Max


Vega Max

And the following Delta definitions:


PA Fwd

PA Spot


It was mentioned above that a critical step in the construction of the vol surface is the determination of the three strike-vol pairs:

(Kᵃᵗᵐ , σᵃᵗᵐ) , (Kᶜ , σᶜ) , (Kᵖ , σᵖ)

The Deriscope function Strikes And Vols returns these pairs, as shown below: 

Generating the Implied Volatility Smile 

What is commonly known as volatility smile is nothing else but a graphical plot of the implied volatility against the strike for some fixed expiry date.

The Deriscope function Implied Value returns just that, as shown below: 

The formula =ds(C4:D7,C8,C9:C24) resides in cell D9 and returns the implied vols (shown in red) corresponding to the manually entered strikes (shown in blue) in column C.

Here is the respective chart: 

If one were to replace the strikes shown on the horizontal axis with their inverse values, the exact same curve would represent the implied volatility of the inverse options on INR/USD due to the Inverse FX Put-Call Parity discussed above.  

Implied Volatility Dependence on ATM and Delta Definitions 

The implied vol smile has been generated out of the &DeltaVolCrv.1 object, which object represents a vol surface built with certain ATM and Vol definitions.

It would be interesting to know how much of an effect these definitions have on the implied volatility, all other things assumed equal.

In the screenshot below, a table is first constructed using the Deriscope Clone function in each cell.

Shown is the formula in the selected cell E9 that returns an object of type Fx Vol Spec cloned out of the initial &VolSpec.1 object, albeit with its values associated with the ATM Def= and Delta Def= keys reset to the shown entries in the top row and left column respectively. 

The next step is to produce a similar table containing objects of type Vol Curve that correspond to the objects shown above:

The final step is to use the Implied Value function to calculate the corresponding implied volatilities for expiry = 31 Jan 2023 and strike = 80:

The selected cell D25 that shows the implied vol of 6.14%, corresponds to ATM Def= Fwd and Delta Def= PA Fwd, which are the values chosen for our main vol surface object &DeltaVolCrv.1.

Had we chosen alternative definitions, the implied vol would have varied in a range from 6.12% to 6.86%. 


Putting everything together, the formula =ds(C5:D11) in cell C4 below returns the price of our Put option expressed in USD terms as 1,315,148.

The cell H4 contains a similar formula that references the option &Call on USD.1 seen earlier to represent the equivalent Call on the inverse FX rate USD/INR faced by the assumed India-based counterparty trader. It returns – as it should – the exact same price. 

Pricing based on Indian OIS Market Rates

It would not be unreasonable to assume that the counterparty trader in India would rather rely on domestic Indian OIS for funding trading positions stemming from this and other options in his trading book.

In that case, a more accurate procedure for calculating the option's NPV would be to use the INR interest rate curve implied from the OIS traded in India and also use the offshore FX NDF quotes, but this time for implying the USD rather than the INR interest rates.

Below is a Bloomberg screen with the onshore Indian OIS market rates as of 31 Mar 2022: 

As was done before, these market quotes are entered in the spreadsheet as input to the Deriscope formulas to create the respective objects of type Yield Curve in cells S4 and AA4, as shown below:  

Regarding the second curve created in cell AA4, the FX NDF quotes are the same as before, but the parameters in red circles have been set so that the produced curve corresponds to the USD rather than the INR currency.

Below is shown the result of this alternative option pricing alongside the original pricing for easier comparison: 

The little table on the right computes the differences between the two NPVs.

The cell S6 shows that the difference represents only a 0.02% proportion of the option's notional of 100,000,000 USD, so that we can talk about a 2 bp price discrepancy between these two alternative calculations. 

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

At https://www.deriscope.com you can find more information about Deriscope and download the Excel Add-In required to run some of the formulas in the spreadsheet. 

Using the Bootstrapped Market SOFR Caplet Normal V...
Sonia OIS Relative Carry and Roll-Down in Excel. H...