Skip to content
All library documents

Calculating FX Option Strikes from ATM, Risk Reversal, and Butterfly Quotes

Article Quant Q&A · Author: user29077

Summary

The document examines how to recover 25-delta put and call strikes from FX option market conventions: at-the-money volatility, risk reversal, and butterfly quotes. It gives a numerical example from a published paper and compares the reported strikes with values produced by a reader’s calculation.

The reply identifies the discrepancy as stemming from incorrect interest-rate calculations based on discount factors. It gives continuously compounded domestic and foreign rates as negative log discount factors divided by time to expiry, then uses their difference in the strike formulas. It also corrects the adjustment used to determine the delta-related normal quantile. This offers a practical debugging lesson in applying FX option conventions, though the exchange is brief and supplies no broader derivation or independent validation of the formulas.

Key ideas

  • Risk reversal and butterfly quotes can be used with ATM volatility to infer put and call volatilities.
  • FX option strike calculations depend on consistent domestic and foreign rates.
  • Continuously compounded rates can be derived from discount factors using negative log discount factors divided by maturity.
  • The delta adjustment in the normal quantile calculation must follow the stated FX convention.

Tags

Full text
# FX Option strikes from ATM, RR, BF quotes


# FX Option strikes from ATM, RR, BF quotes












I am trying to replicate the results in Consistent Pricing of FX Options, A. Castagna and F. Mercurio. However, when I calculate the strike prices for 25-delta put and call and ATM I cannot get the same result as in the article.

The parameters given in the article (p.5):

- T = 94/365

- S = 1.205

- s(ATM) = 0.0905

- s(RR) = -0.0050

- s(BF) = 0.0013

These result in s(25dPut) = 0.0943 and s(25dCall) = 0.0893 (equations 4 and 5 on pages 2 and 3).

- K(25dPut) = 1.1733

- K(25dCall) = 1.2487

The values I get (equations 6 and 7 on p. 3) are:

- K(25dPut) = 1.16688287...

- K(25dCall) = 1.2421907...

Here is my Python code:

```
S       = 1.205
tau     = 94.0 / 365.0
iv_v    = 0.0905
rr_v    = -0.005
bf_v    = 0.0013
for_df  = 0.9902752
dom_df  = 0.9945049

vol_call = iv_v + bf_v + 0.5 * rr_v
vol_put = iv_v + bf_v - 0.5 * rr_v

alpha = - scipy.stats.norm.ppf( 0.25 * np.exp( (for_df**(-1) - 1) * tau) )
k1 = S * np.exp( - alpha * vol_put * np.sqrt(tau) + ((dom_df**(-1) - 1) - (for_df**(-1) - 1) + 0.5 * vol_put**(2) ) * tau )
k2 = S * np.exp( alpha * vol_call * np.sqrt(tau) + ((dom_df**(-1) - 1) - (for_df**(-1) - 1) + 0.5 * vol_call**(2) ) * tau )
```

This code gives wrong results, but I cannot figure out where the error is.

## Answer by OliverB (score 1)

https://quant.stackexchange.com/a/35500

The interest rates (calculated from discount factors) you are using are wrong. Correct formulas: $r_{dom}$ = $-\frac{log(dom_{df})}{T}$

$r_{for}$ = $-\frac{log(for_{df})}{T}$

alpha = - scipy.stats.norm.ppf( 0.25 * np.exp( for_df**(-1) )

k1 = S * np.exp( - alpha * vol_put * np.sqrt(tau) + ($r_{dom}$ - $r_{for}$ + 0.5 * vol_put**(2) ) * tau )

k2 = S * np.exp( alpha * vol_call * np.sqrt(tau) + ($r_{dom}$ - $r_{for}$ + 0.5 * vol_call**(2) ) * tau )

Shown in full with attribution under the source's licence. Licence: CC BY-SA 4.0 (Stack Exchange)

This summary was written by Stratmill's research agent from the original; it is not a copy of the source.