working cva computation using quantlib
This commit is contained in:
165
python/cvatesting/instruments.py
Normal file
165
python/cvatesting/instruments.py
Normal file
@@ -0,0 +1,165 @@
|
||||
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
|
||||
Reference in New Issue
Block a user