FX Options pricing – Plain Vanilla European model (Part I)

Posted by

Part I: Description of FX options pricing basic requirements

1.1 Market data feeds

To be able to price FX options, the model (Garman & Kohlhagen) needs market data feeds: FX volatilities by currency pairs, risk-free (zero-coupon) interest rates and FX spot rates. Other parameters (strike, time to maturity, etc…) directly come from deal options to revalue.

1.2    FX volatilities

In order to price an option, we need to get an implicit volatility associated to the underlying currency pair.

Market’s usages impose to get several points of volatilities per each tenor.

Market’s feeds providers -such as Reuter’s- are providing 5 points of volatilities per each tenor. Each point of volatility is corresponding to a specific delta:

Call option with a delta of 25%

Call option with a delta of 10%

At the money option with a delta of 50%

Put option with a delta of 25%

Put option with a delta of 10%

 

In the FX markets, such points build a concave curve usually called “volatility smile”. On other markets (options on stocks for instance), curves are different (tails, etc…).

1.1.1     Delta to strike

In order to be able to interpolate volatilities corresponding to a given options deal, we have to transform the delta to strike. This transformation process uses a standard Black and Scholes pricing model.

The delta to strike formula given by the Black & Scholes model is:

 

Black and Scholes

 

 

 

 

 

S = FX spot rate of the currency pair.

For a call option, phi = 1 for a put option phi = -1.

sigma = implicit volatility given by Reuters.

Delta takes the 5 various cases: 25, 10, 50, -25, -10 (for a put option, delta is negative).

N-1 = Inverse Normal cumulative distribution.

Ttm = time to maturity e.g. remaining days divided by the basis convention for each currency

(usually 360).

Rf = foreign risk-free interest rate e.g. zero coupon rate interpolated from PERIODIC.INTEREST. Good idea to use a key set in a local ref from DX.PARAMETER .

R = domestic risk-free interest rate e.g. zero coupon rate interpolated from PERIODIC.INTEREST Good idea to use a key set in a local ref from DX.PARAMETER .

 

Notes:

To compute the N-1 = Inverse Normal cumulative distribution, we’re using the algorithm of Peter J. Acklam. Refer to http://home.online.no/~pjacklam/notes/invnorm/index.html

for a description of the algorithm.

Example of routine:

        SUBROUTINE DX.INV.NORM.DIST(INPUT.VALUE, INVERSE.NORMAL.DIST, ERR.MSG)
 IN : 
       INPUT.VALUE (mandatory) is a probability
 OUT : 
       INVERSE.NORMAL.DIST = the inverse standard normal cumulative distribution 
       ERR.MSG when INPUT.VALUE (supposedly a probability) is not in [0,1] interval.
======================================================================
INVERSE.NORMAL.DIST = 0     
ERR.MSG = ''
A1 = -39.6968302866538     
A2 = 220.946098424521     
A3 = -275.928510446969     
A4 = 138.357751867269     
A5 = -30.6647980661472     
A6 = 2.50662827745924     
B1 = -54.4760987982241     
B2 = 161.585836858041     
B3 = -155.698979859887     
B4 = 66.8013118877197     
B5 = -13.2806815528857     
C1 = -7.78489400243029E-03 ; * -0.00778489400243029     
C2 = -0.322396458041136     
C3 = -2.40075827716184     
C4 = -2.54973253934373     
C5 = 4.37466414146497     
C6 = 2.93816398269878     
D1 = 7.78469570904146E-03 ; * 0.00778469570904146     
D2 = 0.32246712907004     
D3 = 2.445134137143     
D4 = 3.75440866190742
dLow  = 0.02425         
dHigh = 1 - dLow
IF (INPUT.VALUE < 0 OR INPUT.VALUE > 1) THEN             
    ERR.MSG = 'INPUT PROBABILITY OUT OF RANGE'             
    RETURN         
END
IF (INPUT.VALUE > 0 AND INPUT.VALUE < dLow) THEN                ;* Rational approximation for lower region                 
    dQ = SQRT(-2 * LN(INPUT.VALUE))                 
    INVERSE.NORMAL.DIST = (((((C1 * dQ + C2) * dQ + C3) * dQ + C4) * dQ + C5) * dQ + C6) / ((((D1 * dQ + D2) * dQ + D3) * dQ + D4) * dQ + 1)         
END ELSE                 
    IF (INPUT.VALUE >= dLow AND INPUT.VALUE <= dHigh) THEN  ;* Rational approximation for central region                         
        dQ = INPUT.VALUE - 0.5                         
        dR = dQ * dQ                         
        INVERSE.NORMAL.DIST = (((((A1 * dR + A2) * dR + A3) * dR + A4) * dR + A5) * dR + A6) * dQ / (((((B1 * dR + B2) * dR + B3) * dR + B4) * dR + B5) * dR + 1)                 
    END ELSE                         
        IF (INPUT.VALUE > dHigh AND INPUT.VALUE < 1) THEN ; * Rational approximation for upper region.                                 
            dQ = SQRT(-2 * LN(1 - INPUT.VALUE))                                 
            INVERSE.NORMAL.DIST = -(((((C1 * dQ + C2) * dQ + C3) * dQ + C4) * dQ + C5) * dQ + C6) / ((((D1 * dQ + D2) * dQ + D3) * dQ + D4) * dQ + 1)                         
        END                 
    END         
END
RETURN
END

 

The base currency of one currency pair is named the foreign currency, and the alternate currency is named the domestic currency. Consequently foreign and domestic interest rates are fetched to respective currencies.

The Delta to strike conversion is launched at the same time as the volatilities import, and resulted strikes are stored for information purpose. If some market data are missing at this stage, interesting to alert key people. During end of day, when prices are re-calculated, a new Delta to Strike conversion is launched, using new FX spot rates, the later will be used in the Garmann & Kohlhagen calculation.

Example of EURGBP volatilities upload from Reuters and where deltas have been
transformed to strikes for each tenors (1week, 2 weeks, etc…):

FX volatility

This article continues with part II.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.