166 lines
4.0 KiB
Python
166 lines
4.0 KiB
Python
import QuantLib as ql
|
|
|
|
|
|
# ============================================================
|
|
# Global defaults (override via parameters if needed)
|
|
# ============================================================
|
|
|
|
CALENDAR = ql.TARGET()
|
|
BUSINESS_CONVENTION = ql.ModifiedFollowing
|
|
DATE_GEN = ql.DateGeneration.Forward
|
|
|
|
FIXED_DAYCOUNT = ql.Thirty360(ql.Thirty360.European)
|
|
FLOAT_DAYCOUNT = ql.Actual360()
|
|
|
|
|
|
# ============================================================
|
|
# Yield curve factory
|
|
# ============================================================
|
|
|
|
def make_flat_curve(
|
|
evaluation_date: ql.Date,
|
|
rate: float,
|
|
day_count: ql.DayCounter = ql.Actual365Fixed()
|
|
) -> ql.YieldTermStructureHandle:
|
|
"""
|
|
Flat yield curve factory.
|
|
"""
|
|
ql.Settings.instance().evaluationDate = evaluation_date
|
|
curve = ql.FlatForward(evaluation_date, rate, day_count)
|
|
return ql.YieldTermStructureHandle(curve)
|
|
|
|
|
|
# ============================================================
|
|
# Index factory
|
|
# ============================================================
|
|
|
|
def make_euribor_6m(
|
|
curve_handle: ql.YieldTermStructureHandle
|
|
) -> ql.IborIndex:
|
|
"""
|
|
Euribor 6M index factory.
|
|
"""
|
|
return ql.Euribor6M(curve_handle)
|
|
|
|
|
|
# ============================================================
|
|
# Schedule factory
|
|
# ============================================================
|
|
|
|
def make_schedule(
|
|
start: ql.Date,
|
|
maturity: ql.Date,
|
|
tenor: ql.Period,
|
|
calendar: ql.Calendar = CALENDAR
|
|
) -> ql.Schedule:
|
|
"""
|
|
Generic schedule factory.
|
|
"""
|
|
return ql.Schedule(
|
|
start,
|
|
maturity,
|
|
tenor,
|
|
calendar,
|
|
BUSINESS_CONVENTION,
|
|
BUSINESS_CONVENTION,
|
|
DATE_GEN,
|
|
False
|
|
)
|
|
|
|
|
|
# ============================================================
|
|
# Swap factory
|
|
# ============================================================
|
|
|
|
def make_vanilla_swap(
|
|
evaluation_date: ql.Date,
|
|
curve_handle: ql.YieldTermStructureHandle,
|
|
notional: float,
|
|
fixed_rate: float,
|
|
maturity_years: int,
|
|
pay_fixed: bool = False,
|
|
fixed_leg_freq: ql.Period = ql.Annual,
|
|
float_leg_freq: ql.Period = ql.Semiannual
|
|
) -> ql.VanillaSwap:
|
|
"""
|
|
Vanilla fixed-for-float IRS factory.
|
|
|
|
pay_fixed = True -> payer swap
|
|
pay_fixed = False -> receiver swap
|
|
"""
|
|
|
|
ql.Settings.instance().evaluationDate = evaluation_date
|
|
|
|
index = make_euribor_6m(curve_handle)
|
|
|
|
start = CALENDAR.advance(evaluation_date, 2, ql.Days)
|
|
maturity = CALENDAR.advance(start, maturity_years, ql.Years)
|
|
|
|
fixed_schedule = make_schedule(
|
|
start, maturity, ql.Period(fixed_leg_freq)
|
|
)
|
|
float_schedule = make_schedule(
|
|
start, maturity, ql.Period(float_leg_freq)
|
|
)
|
|
|
|
swap_type = (
|
|
ql.VanillaSwap.Payer if pay_fixed else ql.VanillaSwap.Receiver
|
|
)
|
|
|
|
swap = ql.VanillaSwap(
|
|
swap_type,
|
|
notional,
|
|
fixed_schedule,
|
|
fixed_rate,
|
|
FIXED_DAYCOUNT,
|
|
float_schedule,
|
|
index,
|
|
0.0,
|
|
FLOAT_DAYCOUNT
|
|
)
|
|
|
|
swap.setPricingEngine(
|
|
ql.DiscountingSwapEngine(curve_handle)
|
|
)
|
|
|
|
return swap
|
|
|
|
|
|
# ============================================================
|
|
# Swaption helper factory (for HW calibration)
|
|
# ============================================================
|
|
|
|
def make_swaption_helpers(
|
|
swaption_data: list,
|
|
curve_handle: ql.YieldTermStructureHandle,
|
|
index: ql.IborIndex,
|
|
model: ql.HullWhite
|
|
) -> list:
|
|
"""
|
|
Create ATM swaption helpers.
|
|
|
|
swaption_data = [(expiry, tenor, vol), ...]
|
|
"""
|
|
|
|
helpers = []
|
|
|
|
for expiry, tenor, vol in swaption_data:
|
|
helper = ql.SwaptionHelper(
|
|
expiry,
|
|
tenor,
|
|
ql.QuoteHandle(ql.SimpleQuote(vol)),
|
|
index,
|
|
index.tenor(),
|
|
index.dayCounter(),
|
|
index.dayCounter(),
|
|
curve_handle
|
|
)
|
|
|
|
helper.setPricingEngine(
|
|
ql.JamshidianSwaptionEngine(model)
|
|
)
|
|
|
|
helpers.append(helper)
|
|
|
|
return helpers
|