Asset swaps#

Introduction#

This page will show you how to create and work with Matched Maturity Asset Swaps.

Environment#

Setting up your environment takes three steps:

  • Import the relevant internal and external libraries

  • Configure the environment parameters

  • Initialize the environment

import sigtech.framework as sig
from sigtech.framework.instruments.ir_otc import IRSwapMarket

import datetime as dtm
import pandas as pd
import numpy as np
import seaborn as sns

sns.set(rc={'figure.figsize': (18,6)})
env = sig.config.init()

Learn more: Setting up the environment

Asset Swap Structure#

The asset swap structure is formed by two financial instruments, which are referred to as “legs”. One of the legs is a financial asset—in the following example, a government bond—whereas the other leg is an interest rate swap.

Asset Swaps are used to transform cashflow characteristics from fix to floating payments with the intention of hedging credit risk.

Bond leg#

Run this code to select a US government bond, which forms the first leg of the Asset Swap:

bond = sig.obj.get('US 2.5 2025/01/31 GOVT')

View the static data and characteristics related to the bond:

Input:

bond.bond_info()

Output:

{'name': 'US9128283V09',
 'coupon_amount': 0.025,
 'day_count': 'ACT/ACT',
 'maturity': datetime.date(2025, 1, 31),
 'interest_acrrue_date': datetime.date(2018, 1, 31),
 'calculation_type': 1,
 'calendar': 'UST CALENDAR',
 'first_coupon_date': datetime.date(2018, 7, 31),
 'coupon_frequency': 'SEMI_ANNUAL',
 'redemption_amount': 100.0,
 'isin': 'US9128283V09',
 'bond_ticker': 'US 2.5 2025/01/31 GOVT',
 'first_settlement_date': datetime.date(2018, 1, 31),
 'issue_date': datetime.date(2018, 1, 31),
 'days_to_settle': 1}

Asset Swap Building Block#

The AssetSwap class returns a Matched Maturity Asset Swap strategy, which involves buying a fixed-coupon bond and selling a matching receiver swap with the same maturity, coupon (as fixed rate) and currency.

Input:

mm_asw = sig.AssetSwap(bond_name=bond.name,
                currency='USD',
                notional=100,
                trade_date=dtm.date(2019,3,1),
                include_trading_costs=False, # exclude trading cost
                total_return=False, # exclude cash accrual
                reinvest_coupon=True,
                direction='long')

mm_asw.history().plot()

Output:

Run the structure_instruments method to explore the bond and swap constituents:

Input:

mm_asw.structure_instruments()

Output:

[('USD US 2.5 2025/01/31 GOVT 5255CDE1 LONG SBS STRATEGY', 1.0),
 ('USD LIBOR SEMI_ANNUAL3M 0.025 2019-03-01 2019-03-05X2025-01-31 FLT_SPRD 0.003488 FIX_DC ACT/ACT IRS',
  -100.0)]

Custom Asset Swap Structure#

You can build any Asset Swap Structure by using the building block SingleBondStrategy to hold a bond and a swap simultaneously.

In this example, SingleBondStrategy is used to hold the treasury, which is to an investment position in US Treasury securities:

Input:

bond_holding = sig.SingleBondStrategy(
    currency=bond.currency,
    start_date=bond.issue_date,
    bond_name=bond.name,
    reinvest_coupon=False,
    initial_cash=100,
)

bond_holding.history().plot(
    title="NAV of $100 notional of bond with reinvested coupons")

Output:

Swap leg: Constructing a Matching Maturity Swap#

To create a matching swap to replicate the treasury leg cashflows, you need to override a number of default arguments:

overrides = {
    'fixed_day_count': 'ACT/ACT',  # bond.day_count is ACT/ACT
    'float_day_count': 'ACT/ACT',  # bond.day_count is ACT/ACT
    'float_frequency': '6M',  # bond.coupon_frequency is SEMI_ANNUAL
    'forecast_curve': 'USD.F6M CURVE',  # bond.coupon_frequency is SEMI_ANNUAL
    'fixes_index': 'US0006M INDEX',  # bond.coupon_frequency is SEMI_ANNUAL
}

Next, create the swap with the overrides above:

swap = sig.InterestRateSwap(
    currency=bond.currency,
    trade_date=bond.issue_date,
    start_date=bond.issue_date,
    tenor=bond.maturity_date,
    fixed_rate=bond.coupon / 100.,
    spread=bond.asw_spread(bond.issue_date) / 100.,
    overrides=overrides,
)

Verify the swap set up by matching the treasury information:

Input:

swap.swap_info_from_currency(
    env,
    bond.issue_date,
    bond.maturity_date,
    bond.currency,
    bond.coupon / 100,
    bond.asw_spread(bond.issue_date) / 100,
    overrides=overrides,
)

Output:

{'start_date': datetime.date(2018, 1, 31),
 'end_date': datetime.date(2025, 1, 31),
 'fixed_rate': 0.025,
 'fixed_rate_frequency': 'S',
 'fixed_day_count': 'ACT/ACT',
 'fixed_business_convention': 'MOD_FOL',
 'float_tenor': '6M',
 'float_day_count': 'ACT/ACT',
 'float_business_convention': 'MOD_FOL',
 'currency': 'USD',
 'calendar': 'FEDFUND, LONDONB CALENDAR',
 'fixing_object_name_override': 'US0006M INDEX',
 'spread': -0.013583813878239516}

You can now compare the swaps and treasury cashflows to ensure they match:

Input:

swap.swap_details(bond.issue_date)['fixed_flows'], bond.cashflows(bond.issue_date)

Output:

([datetime.date(2018, 7, 31),
  datetime.date(2019, 1, 31),
  datetime.date(2019, 7, 31),
  datetime.date(2020, 1, 31),
  datetime.date(2020, 7, 31),
  datetime.date(2021, 1, 29),
  datetime.date(2021, 7, 30),
  datetime.date(2022, 1, 31),
  datetime.date(2022, 7, 29),
  datetime.date(2023, 1, 31),
  datetime.date(2023, 7, 31),
  datetime.date(2024, 1, 31),
  datetime.date(2024, 7, 31),
  datetime.date(2025, 1, 31)],

 array([[datetime.date(2018, 7, 31), 1.2499999999999956, 0.0],
        [datetime.date(2019, 1, 31), 1.2499999999999956, 0.0],
        [datetime.date(2019, 7, 31), 1.2499999999999956, 0.0],
        [datetime.date(2020, 1, 31), 1.2499999999999956, 0.0],
        [datetime.date(2020, 7, 31), 1.2499999999999956, 0.0],
        [datetime.date(2021, 2, 1), 1.2499999999999956, 0.0],
        [datetime.date(2021, 8, 2), 1.2499999999999956, 0.0],
        [datetime.date(2022, 1, 31), 1.2499999999999956, 0.0],
        [datetime.date(2022, 8, 1), 1.2499999999999956, 0.0],
        [datetime.date(2023, 1, 31), 1.2499999999999956, 0.0],
        [datetime.date(2023, 7, 31), 1.2499999999999956, 0.0],
        [datetime.date(2024, 1, 31), 1.2499999999999956, 0.0],
        [datetime.date(2024, 7, 31), 1.2499999999999956, 0.0],
        [datetime.date(2025, 1, 31), 1.2499999999999956, 100.0]],
       dtype=object))

Asset Swap Structure#

The code below combines the two legs of the asset swap structure. As an Asset Swap buyer, you are long the swap and short the bond.

class AssetSwapStrategy(sig.DailyStrategy):
    def strategy_initialization(self, dt):
        pass

asw = AssetSwapStrategy(
    currency=bond.currency,
    start_date=bond.issue_date,

    # long the swap and short the bond
    additional_initial_holdings=[
        (bond_holding.name, 1.0),
        (swap.name, - bond_holding.initial_cash)
    ],

    initial_cash=0,

    include_trading_costs=False,

    total_return=False,
)

Finally, create a performance report of the asset swap strategy:

Input:

sig.PerformanceReport(asw).report()

Output: