# QuantLib: Latin American FixedFloat Swap pricing with multiple payment frequency specification

With reference to the post of latin american swap, I am valuing the FixedFloat CLP swap.The specifications of this swaps has payment frequency upto 18 months as Zero coupon(1T) and after that Semiannual(6M). I want to apply this logic in my current code as mentioned below. I made a function for curve construction using discount factors, discount curve and constructed swap. Please help me to apply the aforesaid logic and schedules to get the pricing done.

df = [1, 0.955, 0.9786]  # discount factors
dates = [
ql.Date(1, 1, 2021),
ql.Date(1, 1, 2022),
ql.Date(1, 1, 2023),
]  # maturity dates of the discount factors

#curve construction
def CurveConstruction(key):
curve_data = raw_dta[raw_data.Curve == key]
curve_data["Maturity Date"] = pd.to_datetime(curve_data["MaturityDate"])
dates = list(map(ql.Date().from_date, curve_data["Maturity Date"]))
curve_data['Df'] = curve_data['Df'].astype(float)
dfs = list(curve_data["Df"])
day_counter = ql.Actual360()
calendar = ql.JointCalendar(ql.UnitedStates(), ql.UnitedKingdom())
yieldcurve = ql.DiscountCurve(dates, dfs, day_counter, calendar)
yieldcurve_handle = ql.YieldTermStructureHandle(yieldcurve)
return yieldcurve_handle

def SwapConstruction(row):
effectiveDate = ql.Date(s_day, s_month, s_year)
terminationDate = ql.Date(m_day, m_month, m_year)
fixedRate = row["Fixed_Rate"]
notional = row["Notional"]
floatindex = row["Float_Index_Name"].lower()
fixed_leg_tenor = ql.Period('6M')
original_tenor = terminationDate - effectiveDate
fixed_leg_daycount = ql.Actual360()
float_leg_daycount = ql.Actual360()
index = ql.OvernightIndex('CLICP', 0, ql.CLPCurrency(), ql.WeekendsOnly(), ql.Actual360(), yieldcurve_handle)
fixingCalendar = index.fixingCalendar()
fixed_schedule = ql.MakeSchedule(EffectiveDate, terminationDate, ql.Once)
float_schedule = ql.MakeSchedule (EffectiveDate, terminationDate, ql.Once, calendar, ql.ModifiedFollowing, False)

#using overnightindexed swap class for fixedfloat
swap = ql.OvernightIndexedSwap(swapType, nominal, schedule, 0.0, dayCount, index)
engine = ql.DiscountingSwapEngine(yieldcurve_handle)
swap.setPricingEngine(engine)
return swap

curves = {}
for key in zeros.Curve.unique():
curves[key] = CurveConstruction(key)

## Process a swaps file
for idx, row in swaps.iterrows():
swap = SwapConstruction(row)
npv = swap.NPV()

• If I have understood it correctly, in reference to this source, the specific swap you are referring to will act as a zero coupon swap up to the 18-month tenor and then pay a semiannual coupon. Does this not mean that you can create a zero coupon swap starting today for up to 18 months and then combine it with a vanilla interest rate swap after the 18-month period, which will pay a semiannual coupon? Commented Dec 1, 2023 at 19:01
• @ Xiarpedia, in reference to the post, he computed the CLP swap using a single class without combining the two classes (vanilla + zero coupons). For complex problems, I think it's good to have a structured curve and then apply it to the swap using a single class. However, it's just my thought. Also, I don't know how to combine it or how accurate it will be using combination. Commented Dec 1, 2023 at 21:12
• You might get better answers if you provide some examples as to the input and output of the exact code you included in your post and why you thought they may not be correct. For details see the Stack Overflow article named "How to create a Minimal, Reproducible Example". Commented Dec 21, 2023 at 9:28
• @Alper, I have posted a very straight question, and the detailed code. If I have discount factors with maturity dates, how am I suppose to price CLP swap having payment frequency upto 18 months as Zero coupon(1T) and after that Semiannual(6M). I have shared my code and if you have any suggestion, please share. Commented Dec 21, 2023 at 20:39

Based on suggestion by @Xiarpedia, I have modified the schedule to capture zero coupon till 18 months and the semi annual after 18 months. Dont know if it works. Please check.

def SwapConstruction(row):
effectiveDate = ql.Date(s_day, s_month, s_year)
terminationDate = ql.Date(m_day, m_month, m_year)
fixedRate = row["Fixed_Rate"]
notional = row["Notional"]
floatindex = row["Float_Index_Name"].lower()
float_leg_tenor = ql.Period('6M')
original_tenor = terminationDate - effectiveDate
fixed_leg_daycount = ql.Actual360()
float_leg_daycount = ql.Actual360()
index = ql.OvernightIndex('CLICP', 0, ql.CLPCurrency(),
ql.WeekendsOnly(), ql.Actual360(), yieldcurve_handle)
fixingCalendar = index.fixingCalendar()

#zero coupon settings
zero_coupon_end_date = effectiveDate +ql.Period(18, ql.Months)

fixed_schedule_zero_coupon = ql.MakeSchedule(EffectiveDate,
zero_coupon_end_date, ql.Once)
fixed_schedule_semiannual_coupon =
ql.MakeSchedule(zero_coupon_end_date, terminationDate, ql.Period('6M'))
float_schedule = ql.MakeSchedule (zero_coupon_end_date,
terminationDate, float_leg_tenor, calendar, ql.ModifiedFollowing,
False)

#using overnightindexed swap class for fixedfloat
zero_swap = ql.OvernightIndexedSwap(swapType, nominal,
fixed_schedule_zero_coupon, 0.0, dayCount, index)
semi_swap = ql.OvernightIndexedSwap(swapType, nominal, float_schedule,
0.0, dayCount, index)

engine = ql.DiscountingSwapEngine(yieldcurve_handle)
zero_swap.setPricingEngine(engine)
semi_swap.setPricingEngine(engine)

combined_results = semi_swap.NPV() + zero_swap.NPV()
return combined_results

curves = {}
for key in zeros.Curve.unique():
curves[key] = CurveConstruction(key)