In [ ]:
%matplotlib inline
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
import uqer
from uqer import DataAPI as api
from QuantLib import *


plt.style.use('fivethirtyeight')
uqer.Client(token='f1b9bea1d0b4e489c5ab9b69c3e2326a1bee6057af858067dbd1546453f428b2')

0. Market Data



In [ ]:
ru1801 = api.MktFutdGet(ticker='RU1801', beginDate='20170825', endDate='20171130', field='tradeDate,closePrice').set_index('tradeDate')
ru1801['closePrice'] = ru1801['closePrice'].astype(float)
ru1801.plot(figsize=(14, 7))

1. Parameters



In [ ]:
start_date = Date(31, 8, 2017)
maturity_date = Date(30, 11, 2017)
freq = Period(1, Days)
volatility = 0.27
option_type = Option.Put
spot_price = ru1801.loc['2017-08-31', 'closePrice']
strike_price = np.mean(ru1801.loc['2017-08-25': '2017-08-31', 'closePrice'])

risk_free_rate = 0.
dividend_rate = 0.
day_count = Actual365Fixed()
calendar = China(China.SSE)

payoff = PlainVanillaPayoff(option_type, strike_price)
exercise = EuropeanExercise(maturity_date)

fixing_scheduler = Schedule(start_date, maturity_date, freq, calendar, Following, Following, DateGeneration.Backward, False)
fixing_dates = [d for d in fixing_scheduler][1:]

In [ ]:
calculation_date = start_date
Settings.instance().evaluationDate = calculation_date

spot_handle = RelinkableQuoteHandle(SimpleQuote(spot_price))
flat_ts = YieldTermStructureHandle(FlatForward(calculation_date, risk_free_rate, day_count))
dividend_yield = YieldTermStructureHandle(FlatForward(calculation_date, dividend_rate, day_count))
flat_vol_ts = BlackVolTermStructureHandle(BlackConstantVol(calculation_date, calendar, volatility, day_count))

bsm_process = BlackScholesMertonProcess(spot_handle, dividend_yield, flat_ts, flat_vol_ts)

option = DiscreteAveragingAsianOption(Average.Arithmetic, 0., 0, fixing_dates, payoff, exercise)

2. FDM Arithmetic Pricing Engine



In [ ]:
engine = FdBlackScholesAsianEngine(bsm_process, 200, 100, 100)

In [ ]:
option.setPricingEngine(engine)
fdm_price = option.NPV()
fdm_delta = option.delta()
print("BSM ASIAN FDM price is {0:.4f}".format(fdm_price))
print("BSM ASIAN FDM delta is {0:.4f}".format(fdm_delta))

3. MC Arithmetic Pricing Engine



In [ ]:
engine = MCDiscreteArithmeticAPEngine(bsm_process,  'ld', controlVariate=True, requiredSamples=50000)

In [ ]:
%%time
option.setPricingEngine(engine)
mc_price = option.NPV()

price_delta = 0.001 * spot_price
new_quote1 = SimpleQuote(spot_price + price_delta)
new_quote2 = SimpleQuote(spot_price - price_delta)

spot_handle.linkTo(new_quote1)
price_bump_plus = option.NPV()

spot_handle.linkTo(new_quote2)
price_bump_minus = option.NPV()

mc_delta = (price_bump_plus - price_bump_minus) / 2. / price_delta

In [ ]:
print("BSM ASIAN MC price is {0:.4f}".format(mc_price))
print("BSM ASIAN MC delta is {0:.4f}".format(mc_delta))

3. Time Series NPV / Delta Analysis


3.1 FDM Method


In [ ]:
%%time

monitor_dates = [start_date]
fdm_npvs = [fdm_price]
fdm_deltas = [fdm_delta]

for i, date in enumerate(fixing_dates[:-1]):
    past_fixings = i + 1
    running_accumulator = np.sum(ru1801.loc[fixing_dates[0].ISO():date.ISO(), 'closePrice'])
    
    # Model settings
    calculation_date = date
    Settings.instance().evaluationDate = calculation_date

    spot_handle = RelinkableQuoteHandle(SimpleQuote(ru1801.loc[date.ISO(), 'closePrice']))
    flat_ts = YieldTermStructureHandle(FlatForward(calculation_date, risk_free_rate, day_count))
    dividend_yield = YieldTermStructureHandle(FlatForward(calculation_date, dividend_rate, day_count))
    flat_vol_ts = BlackVolTermStructureHandle(BlackConstantVol(calculation_date, calendar, volatility, day_count))

    bsm_process = BlackScholesMertonProcess(spot_handle, dividend_yield, flat_ts, flat_vol_ts)

    option = DiscreteAveragingAsianOption(Average.Arithmetic, running_accumulator, past_fixings, fixing_dates[i+1:], payoff, exercise)
    engine = FdBlackScholesAsianEngine(bsm_process, 200, 100, 100)
    option.setPricingEngine(engine)
    
    monitor_dates.append(date)
    fdm_npvs.append(option.NPV())
    fdm_deltas.append(option.delta())

3.2 MC Method


In [ ]:
%%time

mc_npvs = [mc_price]
mc_deltas = [mc_delta]

for i, date in enumerate(fixing_dates[:-1]):
    past_fixings = i + 1
    running_accumulator = np.sum(ru1801.loc[fixing_dates[0].ISO():date.ISO(), 'closePrice'])
    
    # Model settings
    calculation_date = date
    Settings.instance().evaluationDate = calculation_date

    spot_handle = RelinkableQuoteHandle(SimpleQuote(ru1801.loc[date.ISO(), 'closePrice']))
    flat_ts = YieldTermStructureHandle(FlatForward(calculation_date, risk_free_rate, day_count))
    dividend_yield = YieldTermStructureHandle(FlatForward(calculation_date, dividend_rate, day_count))
    flat_vol_ts = BlackVolTermStructureHandle(BlackConstantVol(calculation_date, calendar, volatility, day_count))

    bsm_process = BlackScholesMertonProcess(spot_handle, dividend_yield, flat_ts, flat_vol_ts)

    option = DiscreteAveragingAsianOption(Average.Arithmetic, running_accumulator, past_fixings, fixing_dates[i+1:], payoff, exercise)
    engine = MCDiscreteArithmeticAPEngine(bsm_process,  'ld', controlVariate=True, requiredSamples=50000)
    option.setPricingEngine(engine)
    
    option.setPricingEngine(engine)
    mc_npvs.append(option.NPV())

    price_delta = 0.001 * spot_handle.value()
    new_quote1 = SimpleQuote(spot_handle.value() + price_delta)
    new_quote2 = SimpleQuote(spot_handle.value() - price_delta)

    spot_handle.linkTo(new_quote1)
    price_bump_plus = option.NPV()

    spot_handle.linkTo(new_quote2)
    price_bump_minus = option.NPV()

    mc_delta = (price_bump_plus - price_bump_minus) / 2. / price_delta
    mc_deltas.append(mc_delta)

3.3 Graph


In [ ]:
dates_series = [d.to_date() for d in monitor_dates]

delta_diff = np.array(fdm_deltas) - np.array(mc_deltas)
df = pd.DataFrame({'FDM NPV': np.array(fdm_npvs),
                   'MC NPV': np.array(mc_npvs),
                   'FDM $\Delta$': fdm_deltas,
                   'MC $\Delta$': mc_deltas},
                  index=dates_series)

In [ ]:
df.plot(figsize=(14, 7), secondary_y=['FDM NPV','MC NPV'], title='RU1801 Asian Option NPV & $\Delta$: 2017-09-01 ~ 2017-11-30')

In [ ]: