Class AsianOption

java.lang.Object
com.quantfinlib.pricing.AsianOption

public final class AsianOption extends Object
Asian (average-price) options — the corporate hedger's option: paying off on the average of n fixings instead of one closing print kills both the expiry-day manipulation incentive and most of the vol (an average is smoother than its endpoints), which is why commodity and FX hedging programs default to them. Two averages, two methods:
  • Geometric average: exact. A product of lognormals is lognormal, so the geometric Asian has a Black-Scholes-style closed form (Kemna-Vorst 1990, discrete-fixing version). For n fixings equally spaced at t_i = i T / n (last fixing at expiry):
            E[ln G]   = ln S + (r - q - vol^2/2) * T (n+1)/(2n)
            Var[ln G] = vol^2 * T * (n+1)(2n+1)/(6 n^2)
          
    and the price is the Black-76 form on the lognormal G: discount E[G] N(d1) - K N(d2). As n grows, Var goes to vol^2 T / 3: continuous averaging cuts the variance to a third. At n = 1 both moments collapse to the terminal price and the formula is vanilla Black-Scholes (tested exact).
  • Arithmetic average: Turnbull-Wakeman (1991) moment matching. A sum of lognormals is not lognormal and has no closed form; TW computes the arithmetic average's first two moments exactly under GBM,
            M1 = (S/n) sum_i e^{g t_i}                          g = r - q
            M2 = (S/n)^2 sum_i sum_j e^{g(t_i + t_j) + vol^2 min(t_i, t_j)}
          
    then prices Black-76 style on the lognormal with those moments (Var[ln A] = ln(M2/M1^2)). The approximation error is the distance of the true density from lognormal — small at practical vols, growing with vol^2 T; the moments themselves are exact. The double sum is evaluated in O(n) with suffix sums.

AM-GM guarantees A >= G pathwise, so an arithmetic call is always worth at least the geometric call (tested), and the geometric price is the standard control variate for Monte Carlo on the arithmetic. Rates and vol are annualized and continuously compounded; carry is the dividend/foreign yield exactly as BlackScholes. Fixings strictly after inception (t_1 = T/n > 0) in the two methods above.

Seasoned and general schedules. turnbullWakemanSeasoned(BlackScholes.OptionType, double, double, double, double, double, double[], double, double, int) and curranPrice(BlackScholes.OptionType, double, double, double, double, double, double[], double, double, int) take arbitrary future fixing times plus the sum and count of fixings already struck. With n fixings in total, m still to come and observed sum A_obs, the payoff (A - K)^+ equals (m/n) (A_rem - K*)^+ with K* = (n K - A_obs)/m (Haug 2007, The Complete Guide to Option Pricing Formulas, 2nd ed., section 4.20.1). When K* <= 0 the call is certain to finish in the money and is priced exactly as the discounted forward of A - K; the put is 0. curranPrice(BlackScholes.OptionType, double, double, double, double, double, double[], double, double, int) conditions on the geometric average (Curran 1994, "Valuing Asian and portfolio options by conditioning on the geometric mean price", Management Science 40(12)); levyPrice(BlackScholes.OptionType, double, double, double, double, double, double, double, double) is the continuous average lognormal approximation of Levy (1992, "Pricing European average rate currency options", J. Int. Money and Finance 11).

Research lane.

  • Method Summary

    Modifier and Type
    Method
    Description
    static double
    arithmeticPrice(BlackScholes.OptionType type, double spot, double strike, double rate, double carry, double vol, double timeYears, int averagingPoints)
    Arithmetic-average Asian price via Turnbull-Wakeman two-moment lognormal matching (see class doc; O(n) in the fixing count).
    static double
    curranPrice(BlackScholes.OptionType type, double spot, double strike, double rate, double carry, double vol, double[] fixingTimes, double timeYears, double observedSum, int observedCount)
    Curran (1994) arithmetic-average price by conditioning on the geometric average, for arbitrary (possibly seasoned) fixing schedules.
    static double
    geometricPrice(BlackScholes.OptionType type, double spot, double strike, double rate, double carry, double vol, double timeYears, int averagingPoints)
    Exact discrete geometric-average Asian price (Kemna-Vorst).
    static double
    levyPrice(BlackScholes.OptionType type, double spot, double strike, double rate, double carry, double vol, double timeYears, double averagingPeriod, double realisedAverage)
    Levy (1992) continuous-average lognormal approximation with seasoning, as printed in Haug (2007, section 4.20.2).
    static double
    turnbullWakemanSeasoned(BlackScholes.OptionType type, double spot, double strike, double rate, double carry, double vol, double[] fixingTimes, double timeYears, double observedSum, int observedCount)
    Turnbull-Wakeman two-moment price for an arithmetic average over arbitrary fixing times, some of which may already be struck.

    Methods inherited from class Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Method Details

    • geometricPrice

      public static double geometricPrice(BlackScholes.OptionType type, double spot, double strike, double rate, double carry, double vol, double timeYears, int averagingPoints)
      Exact discrete geometric-average Asian price (Kemna-Vorst).
      Parameters:
      averagingPoints - number of equally spaced fixings n ≥ 1 at t_i = i T / n; n = 1 is vanilla BS
    • arithmeticPrice

      public static double arithmeticPrice(BlackScholes.OptionType type, double spot, double strike, double rate, double carry, double vol, double timeYears, int averagingPoints)
      Arithmetic-average Asian price via Turnbull-Wakeman two-moment lognormal matching (see class doc; O(n) in the fixing count).
    • turnbullWakemanSeasoned

      public static double turnbullWakemanSeasoned(BlackScholes.OptionType type, double spot, double strike, double rate, double carry, double vol, double[] fixingTimes, double timeYears, double observedSum, int observedCount)
      Turnbull-Wakeman two-moment price for an arithmetic average over arbitrary fixing times, some of which may already be struck.
      Parameters:
      fixingTimes - remaining fixing times in years, strictly ascending, in (0, timeYears]; may be empty when everything is fixed
      timeYears - payment time (expiry), at or after the last fixing
      observedSum - sum of the fixings already struck (0 if none)
      observedCount - number of fixings already struck (0 if none)
    • curranPrice

      public static double curranPrice(BlackScholes.OptionType type, double spot, double strike, double rate, double carry, double vol, double[] fixingTimes, double timeYears, double observedSum, int observedCount)
      Curran (1994) arithmetic-average price by conditioning on the geometric average, for arbitrary (possibly seasoned) fixing schedules. With mu_i = ln S + (r - q - vol^2/2) t_i, s_i^2 = vol^2 t_i, mu = mean(mu_i), s_x^2 = vol^2/m^2 sum_ij min(t_i, t_j), s_xi = vol^2/m sum_j min(t_i, t_j) (Curran 1994; Haug 2007, section 4.20.3):
        K^ = 2K - (1/m) sum_i exp(mu_i + s_xi (ln K - mu)/s_x^2 + (s_i^2 - s_xi^2/s_x^2)/2)
        C  = e^{-rT} [ (1/m) sum_i e^{mu_i + s_i^2/2} N((mu - ln K^)/s_x + s_xi/s_x) - K N((mu - ln K^)/s_x) ]
      

      applied to the remaining average and reduced strike. The put follows from parity on the average. When K^ <= 0 (strike far below the forward average) the conditioning region is the whole space and the call is priced as the discounted forward of A - K.

      Parameters as in turnbullWakemanSeasoned(BlackScholes.OptionType, double, double, double, double, double, double[], double, double, int).

    • levyPrice

      public static double levyPrice(BlackScholes.OptionType type, double spot, double strike, double rate, double carry, double vol, double timeYears, double averagingPeriod, double realisedAverage)
      Levy (1992) continuous-average lognormal approximation with seasoning, as printed in Haug (2007, section 4.20.2). The average runs over averagingPeriod years and ends at expiry; timeYears remain, and the average realised so far is realisedAverage. With b = rate - carry, T the averaging period and T2 the time left:
        S_E = S/(T b) (e^{(b-r)T2} - e^{-r T2})
        M   = 2 S^2/(b + vol^2) [ (e^{(2b+vol^2)T2} - 1)/(2b + vol^2) - (e^{b T2} - 1)/b ]
        D   = M / T^2,   V = ln D - 2 (r T2 + ln S_E),   X* = K - (T - T2)/T S_A
        d1  = (ln(D)/2 - ln X*)/sqrt V,   d2 = d1 - sqrt V
        C   = S_E N(d1) - X* e^{-r T2} N(d2),   P = C - S_E + X* e^{-r T2}
      

      Removable singularities at b = 0 and b + vol^2 = 0 are evaluated by their limits. When X* <= 0 the call is the discounted forward S_E - X* e^{-r T2} and the put is 0.

      Parameters:
      averagingPeriod - total averaging length T, at least timeYears
      realisedAverage - average of the path so far (ignored when nothing has elapsed)