I am looking for some materials for profiling all options sensitivities for Asian options with both geometric averaging and arithmetic averaging . The underlying price $S_t$ follows a standard GBM.
Is there any place to look into?
I am looking for some materials for profiling all options sensitivities for Asian options with both geometric averaging and arithmetic averaging . The underlying price $S_t$ follows a standard GBM.
Is there any place to look into?
For the Geometric Average Asian Option in BS, there is an arithmetic formula for the price - in fact, it is possible to price it using a BS vanilla options calculator, if you adjust the parameters slightly - as discussed in this blog post: http://www.quantopia.net/asian-options-iii-geometric-asian/
As the pricing formula is the same, the Greeks can be derived in the same way as BS, although you need to be a bit careful with chain rule terms (and you can check correctness by bumping the parameters directly and calculating the difference from the pricing formula).
For an arithmetic Asian, you need to use a numerical technique like Monte Carlo to calculate either prices or Greeks. However, these will both be close to the geometric price and Greeks, so these can be used either as a direct approximation or as a control variate in the MC calculation.
-- EDIT --
Adding some QuantLib code here to calculate the deltas. You need to include the long snippet at the bottom to set up the environment, but I've put it at the bottom so not to interrupt the flow.
Firstly, geometric options can be priced analytically, and QL provides the prices and the greeks from the analytic pricer:
asian_geo_analytic_pricer = ql.AnalyticDiscreteGeometricAveragePriceAsianEngine(process_initial)
asian_option_geometric.setPricingEngine(asian_geo_analytic_pricer)
print(asian_option_geometric.NPV())
print(asian_option_geometric.delta())
We can also use MC, but we'll need to use two processes, one with a slightly bumped spot. It's also important to ensure a constant seed, or use low discrepancy numbers, to ensure the pricing happens along the same paths:
rng = "pseudorandom" # could use "lowdiscrepancy"
numPaths = 100000
seed = 43
results = []
for process in [process_initial, process_bumped]:
asian_geo_mc_pricer = ql.MCDiscreteGeometricAPEngine(process, rng, requiredSamples=numPaths, seed=seed)
asian_arith_mc_pricer = ql.MCDiscreteArithmeticAPEngine(process, rng, requiredSamples=numPaths, seed=seed)
asian_option_geometric.setPricingEngine(asian_geo_mc_pricer)
asian_option_artithmetic.setPricingEngine(asian_arith_mc_pricer)
results.append({'geometric': asian_option_geometric.NPV(), 'arithmetic': asian_option_artithmetic.NPV()})
df = pd.DataFrame(results).transpose()
df['delta'] = (df[1] - df[0]) / delta
df
As we can see, the geometric delta matches nicely with the analytic value, and the arithmetic is slightly higher as expected.
Setting up the calculation:
import QuantLib as ql
import numpy as np
import pandas as pd
# World State for Vanilla Pricing
vol = 0.1
rate = 0.0
strike = 100
today = ql.Date(1, 7, 2020)
# Set up the vol and risk-free curves
volatility = ql.BlackConstantVol(today, ql.NullCalendar(), vol, ql.Actual365Fixed())
riskFreeCurve = ql.FlatForward(today, rate, ql.Actual365Fixed())
flat_ts = ql.YieldTermStructureHandle(riskFreeCurve)
dividend_ts = ql.YieldTermStructureHandle(riskFreeCurve)
flat_vol = ql.BlackVolTermStructureHandle(volatility)
# And define the options
past_fixings = 0 # Empty because this is a new contract
asian_fixing_dates = [ql.Date(1, 1, 2021), ql.Date(1, 7, 2021), ql.Date(1, 1, 2022), ql.Date(1, 7, 2022)]
asian_expiry_date = ql.Date(1, 7, 2022)
vanilla_payoff = ql.PlainVanillaPayoff(ql.Option.Call, strike)
european_exercise = ql.EuropeanExercise(asian_expiry_date)
average_geo = ql.Average().Geometric
average_arit = ql.Average().Arithmetic
asian_option_geometric = ql.DiscreteAveragingAsianOption(average_geo, 1.0, past_fixings, asian_fixing_dates, vanilla_payoff, european_exercise)
asian_option_artithmetic = ql.DiscreteAveragingAsianOption(average_arit, 0.0, past_fixings, asian_fixing_dates, vanilla_payoff, european_exercise)
# Set up two vol processes, with the spot bumped, for MC delta calculations
delta = 0.001
spot = 100
process_initial = ql.BlackScholesMertonProcess(ql.QuoteHandle(ql.SimpleQuote(spot)), dividend_ts, flat_ts, flat_vol)
process_bumped = ql.BlackScholesMertonProcess(ql.QuoteHandle(ql.SimpleQuote(spot+delta)), dividend_ts, flat_ts, flat_vol)