1
$\begingroup$

I'm trying to price a snowball payoff in quantlib and would like to create a payoff like:

$$Coupon = PreviousCoupon + FloorPayoff$$

Would the payoff class be able to reference the previous coupon? How could I do that? Could anyone point me to an example of implementing the Payoff class to create a payoff script?

I had a look at these slides: https://www.quantlib.org/slides/qlum17/schlenkrich.pdf

$\endgroup$
2
$\begingroup$

Here is an attempt to code it without using the payoff class but I'm sure there is a more efficient way:

import QuantLib as ql
import numpy as np

# global data
todaysDate = ql.Date(31, ql.August, 2018);
ql.Settings.instance().evaluationDate = todaysDate
settlementDate = ql.Date(2, ql.September, 2018)

# Setup the yield termstructure
rate = ql.SimpleQuote(0.03)
rate_handle = ql.QuoteHandle(rate)
dc = ql.Actual365Fixed()
yieldCurve = ql.FlatForward(todaysDate, rate_handle, dc)
yieldCurve.enableExtrapolation()
yieldCurveHandle = ql.YieldTermStructureHandle(yieldCurve)

# HW1F Fixed Params
sigma = 0.003
a = 0.03
timestep = 17
length = 4.25 # in years
forward_rate = -0.0026
day_count = ql.Thirty360()
hw_process = ql.HullWhiteProcess(yieldCurveHandle, a, sigma)
rng = ql.GaussianRandomSequenceGenerator(ql.UniformRandomSequenceGenerator(timestep, ql.UniformRandomGenerator()))
seq = ql.GaussianPathGenerator(hw_process, length, timestep, rng, False)

# Generate Paths
def generate_paths(num_paths, timestep):
    arr = np.zeros((num_paths, timestep+1))
    for i in range(num_paths):
        sample_path = seq.next()
        path = sample_path.value()
        time = [path.time(j) for j in range(len(path))]
        value = [path[j] for j in range(len(path))]
        arr[i, :] = np.array(value)
    return np.array(time), arr
num_paths = 2000
time, paths = generate_paths(num_paths, timestep)

# Derivative Details
effective_date = ql.Date(13, 6, 2018)
termination_date = ql.Date(13, 12, 2022)
notionals = np.array([100])

tenor = ql.Period(ql.Quarterly)
calendar = ql.TARGET()

business_convention = ql.ModifiedFollowing
termination_business_convention = ql.Following
date_generation = ql.DateGeneration.Forward
end_of_month = False
schedule = ql.Schedule(effective_date,
                    termination_date,
                    tenor,
                    calendar,
                    business_convention,
                    termination_business_convention,
                    date_generation,
                    end_of_month)

days = schedule.__len__()
dcf = np.array([ql.Actual360().yearFraction(schedule[x], schedule[x+1]) for x in range(days-1) ])

last_rate = 124.574 / 100
multi = 2
floor_strike = 0.02

snowball_rate = np.empty([num_paths, 18])

for i in range(18):
    if i == 0:
        snowball_rate[:, 0] = last_rate
    else:
        snowball_rate[:, i] = snowball_rate[:, i - 1] + multi * np.maximum((floor_strike - paths[:, i]), 0)

discountDates = [ (d - settlementDate)/365 for d in schedule]
discountRates = np.array([yieldCurve.discount(d) for d in discountDates[1:]])
cf = notionals * dcf * snowball_rate * discountRates
cf.mean(0).sum()
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.