Skip to content
All library documents

Building Swap Legs with Different Coupon Frequencies in QuantLib

Article Quant Q&A · Author: John83

Summary

The document describes a request to value a Chilean peso fixed floating swap in QuantLib when the fixed leg pays as a single coupon through the first eighteen months and semiannually afterward. The question includes code for constructing a discount curve from dates and discount factors, creating an overnight index, and building swap schedules. A proposed response splits the fixed leg into an initial zero-coupon period and a later semiannual schedule, then adds the net present values of two swap objects.

The example illustrates how a schedule can be divided at a coupon-frequency change, but the suggested code is explicitly unverified. It does not demonstrate that combining the two swap valuations reproduces the intended contractual cash flows or correctly handles the floating leg. The snippet also contains inconsistent names and inputs, and it does not show a valuation result or validation against a reference calculation. Users would need to check schedule dates, leg conventions, and instrument construction against the swap terms before relying on it.

Key ideas

  • A swap leg with a frequency change can be represented using schedules split at the change date.
  • The example uses a one-coupon initial period followed by semiannual periods.
  • The proposed approach adds the NPVs of two separately constructed swap objects.
  • The code is unverified and contains inconsistencies, so pricing and cash flows require independent validation.

Tags

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


# 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)

swaps = pd.read_csv(xyz.csv)

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

## Answer by robin (score 1)

https://quant.stackexchange.com/a/77774

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)

swaps = pd.read_csv(xyz.csv)

## Process a swaps file
for idx, row in swaps.iterrows():
    combined_results = makeSwap(row)
npv = combined_results
```

Shown in full with attribution under the source's licence. Licence: CC BY-SA 4.0 (Stack Exchange)

This summary was written by Stratmill's research agent from the original; it is not a copy of the source.