Skip to content

Commit f2e2ca6

Browse files
committed
add AssetSwap
1 parent 6ce977d commit f2e2ca6

File tree

5 files changed

+171
-0
lines changed

5 files changed

+171
-0
lines changed
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
from libcpp cimport bool
2+
from quantlib.types cimport Real, Spread
3+
from quantlib.time._schedule cimport Schedule
4+
from ._bond cimport Bond
5+
from quantlib.handle cimport shared_ptr
6+
from quantlib.time._date cimport Date
7+
from quantlib.time._daycounter cimport DayCounter
8+
from .._cashflow cimport Leg
9+
from ._swap cimport Swap
10+
from quantlib.indexes._ibor_index cimport IborIndex
11+
12+
cdef extern from "ql/instruments/assetswap.hpp" namespace "QuantLib" nogil:
13+
cdef cppclass AssetSwap(Swap):
14+
AssetSwap(bool payBondCoupon,
15+
shared_ptr[Bond] bond,
16+
Real bondCleanPrice,
17+
const shared_ptr[IborIndex]& iborIndex,
18+
Spread spread,
19+
Schedule floatSchedule,
20+
const DayCounter& floatingDayCounter,
21+
bool parAssetSwap, # = true
22+
Real gearing, # 1.0
23+
Real nonParRepayment, # = Null<Real>(),
24+
Date dealMaturity) # = Date()
25+
Spread fairSpread() except +
26+
Real floatingLegBPS() except +
27+
Real floatingLegNPV() except +
28+
Real fairCleanPrice() except +
29+
Real fairNonParRepayment() except +
30+
31+
bool parSwap()
32+
Spread spread()
33+
Real cleanPrice()
34+
Real nonParRepayment()
35+
const shared_ptr[Bond]& bond()
36+
bool payBondCoupon()
37+
const Leg& bondLeg()
38+
const Leg& floatingLeg()

quantlib/instruments/api.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from .assetswap import AssetSwap
12
from .bonds import FixedRateBond, ZeroCouponBond, FloatingRateBond
23
from .bondforward import BondForward
34
from .credit_default_swap import CreditDefaultSwap, PricingModel

quantlib/instruments/assetswap.pxd

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
from .swap cimport Swap
2+
3+
cdef class AssetSwap(Swap):
4+
pass

quantlib/instruments/assetswap.pyx

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
from cython.operator cimport dereference as deref
2+
from libcpp cimport bool
3+
from quantlib.types cimport Real, Spread
4+
from quantlib.handle cimport shared_ptr, static_pointer_cast
5+
from quantlib.indexes.ibor_index cimport IborIndex
6+
from quantlib.indexes cimport _ibor_index as _ib
7+
from quantlib.time.schedule cimport Schedule
8+
from quantlib.time.date cimport Date
9+
from quantlib.time.daycounter cimport DayCounter
10+
from quantlib.utilities.null cimport Null
11+
from quantlib.cashflow cimport Leg
12+
from quantlib._cashflow cimport Leg as QlLeg
13+
from . cimport _assetswap as _asw
14+
from .bond cimport Bond
15+
from ._bond cimport Bond as QlBond
16+
17+
cdef class AssetSwap(Swap):
18+
def __init__(
19+
self, bool pay_bond_coupon, Bond bond, Real bond_clean_price,
20+
IborIndex ibor_index, Spread spread, Schedule float_schedule=Schedule.__new__(Schedule),
21+
DayCounter floating_day_counter=DayCounter(), bool par_asset_swap=True,
22+
Real gearing=1.0, Real non_par_repayment=Null[Real](), Date deal_maturity=Date()
23+
):
24+
self._thisptr.reset(
25+
new _asw.AssetSwap(pay_bond_coupon,
26+
static_pointer_cast[QlBond](bond._thisptr),
27+
bond_clean_price,
28+
static_pointer_cast[_ib.IborIndex](ibor_index._thisptr),
29+
spread,
30+
float_schedule._thisptr,
31+
deref(floating_day_counter._thisptr),
32+
par_asset_swap,
33+
gearing,
34+
non_par_repayment,
35+
deal_maturity._thisptr
36+
)
37+
)
38+
39+
@property
40+
def fair_spread(self):
41+
return (<_asw.AssetSwap*>self._thisptr.get()).fairSpread()
42+
43+
@property
44+
def floating_leg_BPS(self):
45+
return (<_asw.AssetSwap*>self._thisptr.get()).floatingLegBPS()
46+
47+
@property
48+
def floating_leg_NPV(self):
49+
return (<_asw.AssetSwap*>self._thisptr.get()).floatingLegNPV()
50+
51+
@property
52+
def fair_clean_price(self):
53+
return (<_asw.AssetSwap*>self._thisptr.get()).fairCleanPrice()
54+
55+
@property
56+
def fair_non_par_repayment(self):
57+
return (<_asw.AssetSwap*>self._thisptr.get()).fairNonParRepayment()
58+
59+
@property
60+
def bond_leg(self):
61+
cdef Leg leg = Leg.__new__(Leg)
62+
leg._thisptr = (<_asw.AssetSwap*>self._thisptr.get()).bondLeg()
63+
return leg
64+
65+
@property
66+
def floating_leg(self):
67+
cdef Leg leg = Leg.__new__(Leg)
68+
leg._thisptr = (<_asw.AssetSwap*>self._thisptr.get()).floatingLeg()
69+
return leg

test/test_assetswap.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import unittest
2+
3+
from quantlib.time.api import Date, Period, Annual, TARGET, Unadjusted, Schedule, DateGeneration, Actual365Fixed, Semiannual, ActualActual, Following
4+
from quantlib.instruments.api import FixedRateBond, AssetSwap
5+
from quantlib.pricingengines.api import DiscountingBondEngine, DiscountingSwapEngine
6+
from quantlib.termstructures.yields.api import HandleYieldTermStructure
7+
from quantlib.indexes.api import Euribor
8+
from .utilities import flat_rate
9+
10+
class TestMarketASWSpread(unittest.TestCase):
11+
def setUp(self):
12+
self.term_structure = HandleYieldTermStructure()
13+
self.today = Date(24, 4, 2007)
14+
self.ibor_index = Euribor(Period(Semiannual), self.term_structure)
15+
self.term_structure.link_to(flat_rate(0.05, Actual365Fixed(), self.today))
16+
self.spread = 0.0
17+
self.face_amount = 100.0
18+
self.settlement_days = 2
19+
20+
def test_market_vs_par_asset_swap(self):
21+
"""Testing relationship between market asset swap and par asset swap..."""
22+
23+
pay_fixed_rate = True
24+
par_asset_swap = True
25+
mkt_asset_swap = False
26+
fixed_bond_schedule1 = Schedule.from_rule(Date(4, 1, 2005),
27+
Date(4, 1, 2037),
28+
Period(Annual),
29+
TARGET(),
30+
Unadjusted, Unadjusted,
31+
DateGeneration.Backward, False)
32+
fixed_bond1 = FixedRateBond(self.settlement_days, self.face_amount, fixed_bond_schedule1,
33+
[0.04], ActualActual(ActualActual.ISDA), Following,
34+
100.0, Date(4, 1, 2005))
35+
bond_engine = DiscountingBondEngine(self.term_structure)
36+
swap_engine = DiscountingSwapEngine(self.term_structure)
37+
fixed_bond1.set_pricing_engine(bond_engine)
38+
fixed_bond_mkt_price1 = 89.22 # market price observed on June 7th 2007
39+
fixed_bond_mkt_full_price1 = fixed_bond_mkt_price1 + fixed_bond1.accrued_amount()
40+
fixed_bond_par_asset_swap1 = AssetSwap(pay_fixed_rate,
41+
fixed_bond1, fixed_bond_mkt_price1,
42+
self.ibor_index,
43+
self.spread,
44+
floating_day_counter=self.ibor_index.day_counter,
45+
par_asset_swap=True)
46+
fixed_bond_par_asset_swap1.set_pricing_engine(swap_engine)
47+
fixed_bond_par_asset_swap_spread1 = fixed_bond_par_asset_swap1.fair_spread
48+
fixed_bond_mkt_asset_swap1 = AssetSwap(pay_fixed_rate,
49+
fixed_bond1,
50+
fixed_bond_mkt_price1,
51+
self.ibor_index,
52+
self.spread,
53+
floating_day_counter=self.ibor_index.day_counter,
54+
par_asset_swap=False)
55+
fixed_bond_mkt_asset_swap1.set_pricing_engine(swap_engine)
56+
fixed_bond_mkt_asset_swap_spread1 = fixed_bond_mkt_asset_swap1.fair_spread
57+
58+
self.assertAlmostEqual(fixed_bond_mkt_asset_swap_spread1,
59+
100 * fixed_bond_par_asset_swap_spread1 / fixed_bond_mkt_full_price1)

0 commit comments

Comments
 (0)