School of Education, Culture and Communication Division of Applied Mathematics

MASTER THESIS IN MATHEMATICS / APPLIED MATHEMATICS

Yield curve estimation models with real market data implementation and performance observation

by

Penny Andersson

Masterarbete i matematik / tillämpad matematik

DIVISION OF MATHEMATICS AND PHYSICS MÄLARDALEN UNIVERSITY SE-721 23 VÄSTERÅS, SWEDEN School of Education, Culture and Communication Division of Applied Mathematics

Master thesis in mathematics / applied mathematics

Date: 2020-02-10

Project name: estimation models with real market data implementation and performance obser- vation

Author: Penny Andersson

Supervisor(s): Jan Röman

Co-supervisor(s): Milica Ranciˇ c´

Reviewer:

Examiner: Anatoliy Malyarenko

Comprising: 30 ECTS credits Abstract

It always exists different methods/models to build a yield curve from a set of observed market rates even when the curve completely reproduces the price of the given instruments. To create an accurate and smooth interest rate curve has been a challenging all the time. The purpose of this thesis is to use the real market data to construct the yield curves by the bootstrapping method and the Smith Wilson model in order to observe and compare the performance ability between the models. Furthermore, the extended Nelson Siegel model is introduced without implementation. Instead of implementation I compare the ENS model and the traditional bootstrapping method from a more theoretical perspective in order to perceive the performance capabilities of them. Contents

1 Introduction6 1.1 Structure...... 7 1.1.1 Purpose...... 7 1.1.2 Target Audience...... 7

2 Theoretical background8 2.1 Relevant terminology...... 8 2.1.1 Forward rates from zero- bonds and zero-coupon rates....8 2.1.2 Forward rates from coupon bonds...... 11 2.1.3 Par rate and par yield...... 13 2.1.4 Market instruments...... 14 2.1.5 Interbank rate...... 18

3 Implementation with market data(excl. the ENS model) 20 3.1 Bootstrapping method...... 20 3.1.1 Bootstrapping the OIS Eonia curve...... 20 3.1.2 Bootstrapping 3-months Euribor and 6-months Euribor...... 23 3.2 The Smith–Wilson model...... 31 3.2.1 Smith-Wilson technique for zero coupon prices as input.... 38 3.2.2 Smith-Wilson technique for a set of general inputs...... 40 3.2.3 Important parameters...... 42 3.3 The extended Nelson-Siegel model...... 53 3.3.1 The original model...... 57 3.3.2 The extended version of Svensson...... 59

4 Conclusion 63 4.1 Comparing the bootstrapping method with the Smith Wilson technique.... 63 4.2 Comparing the bootstrapping method with the extended Nelson and Siegel model...... 64

Appendices 68

A The calculation of OIS discounting with bootstrapping method in Python 69

2 B The calculation of 3-months Euribor with the bootstrapping method in Python 81

C The calculation of 6-months Euribor with the bootstrapping method in Python 104

D The calculation of Eonia with the Smith Wilson model in Python 126

E The calculation of 3-months Euribor with the Smith Wilson model in Python 150

F The calculation of 6-months Euribor with the Smith Wilson model in Python 191

G Criteria for a Masters Thesis 224 G.1 Objective 1: Knowledge and understanding...... 224 G.2 Objective 2: Methodological knowledge...... 224 G.3 Objective 3: Critically and Systematically Integrate Knowledge...... 224 G.4 Objective 4: Ability to Critically, Independently and Creatively Identify and Carry out Advanced Tasks...... 225 G.5 Objective 5: Ability in both national and international contexts, Present and Discuss Conclusions and Knowledge...... 225 G.6 Objective 6: Scientific, Social and Ethical Aspects...... 225

3 List of Figures

2.1 The par rate rpar is the constant rate that equalizes the value of the floating leg (dotted arrows) to the fixed leg over the lifetime of the [19, p.23].... 13 2.2 The par yield is the yield that equals the coupon rate cpar so that the price of the bond is equal to its face value, nominal amount, here set to 100 [19, p.23] 14 2.3 Microsoft and Intel use the swap to transform a liability [13, p.155])..... 18

3.1 The bootstrapped discount curve for Eonia at 2020-04-14 (Table 3.2)..... 26 3.2 The bootstrapped yield curve for Eonia at 2020-04-14 (Table 3.2)...... 26 3.3 The bootstrapped discount curve for 3-months Euribor at 2020-04-14 (Table 3.4)...... 33 3.4 The bootstrapped yield curve for 3-months Euribor at 2020-04-14 (Table 3.4) 33 3.5 The bootstrapped discount curve for 6-months Euribor at 2020-04-14 (Table 3.6)...... 36 3.6 The bootstrapped yield curve for 6-months Euribor at 2020-04-14 (Table 3.6) 36 3.7 The yield curve for Eonia by Smith-Wilson at 2020-04-14 (Table 3.8).... 52 3.8 The discount factors for Eonia by Smith-Wilson technique at 2020-04-14 (Table 3.8)...... 52 3.9 The yield curve for 3-months Euribor by Smith-Wilson at 2020-04-14 (Table 3.9)...... 53 3.10 The discount factors for 3-months Euribor by Smith-Wilson at 2020-04-14 (Table 3.9)...... 55 3.11 The yield curve for 6-months Euribor by Smith-Wilson at 2020-04-14 (Table 3.10)...... 55 3.12 The yield curve for 6-months Euribor by Smith-Wilson at 2020-04-14 (Table 3.10)...... 57 3.13 Yield curve shapes, parameter a spans from 6 to 12 with equal increments [16, p.476]...... − 59 3.14 Components of the forward rate curve [16, p.477]...... 60 3.15 Forward rate curve and components [21]...... 61

4.1 Plot of fitted yield curves for 3M Euribor rates, together with actual market rates 64 4.2 3M Forward Curves for EONIA rates by linear interpolation and NSS model 65 4.3 Discount Curves for 6M Euribor rates built by linear interpolation and NSS model...... 65

4 List of Tables

3.1 EONIA rates at 2020-04-14...... 24 3.2 The discounted OIS curve at 2020-04-14...... 25 3.3 3-months Euribor rates at 2020-04-14...... 28 3.4 The bootstrapped 3-months Euribor curve at 2020-04-14...... 32 3.5 The 6-months Euribor rates at 2020-04-14...... 34 3.6 The bootstrapped 6-months Euribor curve at 2020-04-14...... 35 3.7 Application of Smith–Wilson method for different input instruments..... 43 3.8 The yield curves and discount factors for Eonia by Smith–Wilson technique at 2020-04-14...... 51 3.9 The yield curves and discount factors for 3-months Euribor by Smith–Wilson technique at 2020-04-14...... 54 3.10 The yield curves and discount factors for 6-months Euribor by Smith–Wilson technique at 2020-04-14...... 56

5 Chapter 1

Introduction

The values of interest rate derivatives are always difficult to estimate, and the pricing approach relies on modelling the future dynamics of the yield curves. Yield curves are used to estimate cash-flows, discount rates and to calculate the theoretical values of interest rate derivatives. But there are many different methods to construct a yield curve. Every method gives a slightly different yield curve and no one of them is perfect.

Banks need algorithms as accurate as possible since e.g. only a small change in a dis- count curve can have drastically changes in values of interest rate instruments. There are two main methods to estimate yield curves. Both methods, bootstrapping and parameterization use traded (or quoted) instruments on the market to predict the future interest rate. There are mainly two kinds of yield curves; curves from bonds (usually Government bonds) represent- ing the and swap curves, representing the interbank market. Corporate bonds are valued as a spread above the Government curve.

Bootstrapping is a method where we use liquid, trades instrument by starting with the shortest to maturity and moving forward in time. If we use bonds, bills and notes, we need to strip their coupons (if any) by using linear interpolation and/or extrapolation. The swap curve includes in bootstrapped from deposits, future/forwards and swaps with different maturities.

In parameterization I use the same instruments as for the bootstrapping. But in this method I try to optimize a best fit of the market prices with a pre-determined function with some unknown constants. This function can be a stochastic process or a specified function. The two most common parameter-models are Smith Wilson (SW) and Nelson Siegel (NS). Many central banks prefer one of these models since they result in smooth forward rate curves. This is often not the case in bootstrapping.

In this master thesis I will compare the SW model and the extended Nelson-Siegel (ENS) model with Bootstrapping. Advantages and disadvantages of analyzed methods are discussed based on the obtained results.

6 1.1 Structure

1.1.1 Purpose There are two main purposes in this thesis. Firstly, to find a better method to construct yield curves as accurate as possible as well as smooth as possible, in order to derive interest rate instruments and predict the future interest rate. Since a slight changing of yield curves can cause a huge changing of values of interest rate instruments. Furthermore, if the current term structure is incorrect it will indeed lead to mispricing. Hence, to construct the right current term structure for quoted market data is extremely important. Secondly, to discover how yield curves influence interest rate risk. The interest rate risk is often calculated by shifting the curve and studying how the price of financial instruments is affected. Usually, such shifts are made in "time buckets" in order to calculate the risk between two time nodes on the curve. Most often people divide the curve into several "time buckets" and shift them one by one. The most common problem with parameterized curves is desire of smoothness. If we make such shifts (in "time buckets") the risk is affected along the whole or most parts of the curve, which is not desirable as we want. Thus I want to study the risk only on the selected "time buckets". In addition, when we use linear interpolation or extrapolation, only the part of the curve what we shift will be affected. Unfortunately, linear interpolation or extrapolation makes curves bumpy or zigzag shape, especially for the forward rate curves [14]. Anyway what we actually want is the curve without . To achieve these purposes I will use two methods, namely the bootstrapping method and the SW model on swap curves which consists of Deposits, FRA (Forward Rate Agreement) and IRS (Interest Rate Swaps). Furthermore, a theoretical introduction of the ENS model will be included. At the end I will analyze the result of those case studies and make a conclusion.

1.1.2 Target Audience The target audience of this thesis are people who work or study within financial mathemat- ics and/or financial engineering areas on advanced level. Therefore knowledge of advanced mathematics and finance are required.

7 Chapter 2

Theoretical background

To estimate values of complex interest rate derivatives, it usually requires modelling the fu- ture dynamics of the yield curve term structure. There are two approaches to achieve this, bootstrapping and parameterization. Sometimes they are called as "exact fit" and "best fit" respectively [19]. Forward interest rate has been widely used and its use has been standard long time in financial analysis, especially for pricing new financial instruments and in discovering arbitrage possibilities. In followed section, I will interpret some topic relevant terminologies, especially related to forward rates, yields to maturity and spot rates. There is a number of methods to estimate forward rates both for financial analysis and monetary police analysis. For financial analysis, some of those methods are quite complex in order to achieve sufficient precision. Whereas the requirement of precision is a less disputable in analysis of monetary police. In this section, theoretical background of those three meth- ods, the SW, the ENS model and the bootstrapping method, will be presented. This includes histories, definitions and models which will be used in practical section later.

2.1 Relevant terminology

2.1.1 Forward rates from zero-coupon bonds and zero-coupon rates

In some literature, forward rate has been described as a risk-less interest rate which is related to a forward contract. A forward contract which is traded in the over-the-counter market (OTC) is an agreement between a buyer and a seller for trading an asset with agreed price at a certain future time [13]. At this certain future time an interest rate will be adopted. In other words, a future interest rate which is calculated from the zero-coupon rates (spot rates) or a yield curve and will be used between two future dates. In this subsection all forward rates what I talk about are forward rates from yields to maturity on zero-coupon bonds, namely spot rates or zero-coupon rates. Forward rates from yields to maturity on coupon bonds will be presented in the next subsection. I can quote a couple of equations from Jan Röman’s [19, p.25] book, Analytical Finance

8 Volumne II, to describe the relationship between forward rate and spot rate. 1 rspot t1 1 r f orward t2 t1 1 rspot t2 (2.1) ( + t1 ) ( + t2 t1 ) − = ( + t2 ) , − = ⇒ 1 spot t t t (1 + r ) 2 2− 1 r f orward t2 1 (2.2) t2 t1 = spot . − t1 − (1 + rt1 ) ! Equation (2.1) and (2.2) tell us that at time t, t < t1 < t2, we have made a contract guaran- teeing a risk-less rate of interest over the future interval [t1,t2]. Such an interest rate which is over a future period is called a forward rate. In other words, we can discount a future value with the future spot rate r for period [t1,t2] to obtain the current price for purchasing a zero- coupon bond at time t1 with maturity t2, t2 > t1. We call this future spot rate as forward rate as well. Therefore, there exists an easy way to represent the forward rate, namely via the discount function [19, p.25]: p(0,t1) p(t1,t2) = p(0,t2), (2.3) · = ⇒ p(0,t2) p(t2) p(t1,t2) = , (2.4) p(0,t1) ≡ p(t1) where p is discount factor, also called as zero-coupon bond’s price. In terms of continuous compounding the discount function can be displayed as:

r(t1) t1 f (t1,t2) (t2 t1) r(t2) t2 e− · e− · − = e− · , (2.5) · where f (t1,t2) is forward rate over future period [t1,t2], r(t1) and r(t2) are spot rates at t1 and t2 respectively. Moreover, from eq.(2.3) we can obtain:

1 f orward p(0,t1) = 1 + rsimp (t2 t1) = . (2.6) p(t1,t2) − p(0,t2)

Thus, we can define simple forward rate over future period [t1,t2] with a contract time at t (t < t1 < t2) as: f orward p(t,t2) p(t,t1) rsimp (t,t1,t2) = − . (2.7) − p(t,t2)(t2 t1) − And for continuous compounding, according to eq.(2.5) we can have: er(t2) t2 p t t f (t1,t2) (t2 t1) · ( , 1) e · − = = . (2.8) r(t1) t1 e · p(t,t2) Thereby we can define continuously compounded forward rate over future period [t1,t2] with a contract time at t (t < t1 < t2) as:

f orward ln(p(t,t2)) ln(p(t,t1)) rcomp (t,t1,t2) = − − t2 t1 − (2.9) ln(p(t ,t )) = 1 2 . − t2 t1 −

9 The instantaneous forward rate with start at S and maturity at T contracted at t (t < S < T) can be defined as [19, p.294]:

∂[ln p(t,T)] f T (t) = f (t,T) = lim r(t,S,T) = (2.10) S T − ∂T → , = ⇒ T p(t,T) = exp f (t,u)du . (2.11) − t  Z  Eq.(2.11) can be interpreted as, at contract time t as agreed to pay 1 cash unit (CU) at maturity T is equivalent to receive e f (t,T) ∆T at time t. Or simply it is the price of a pure discount bond as the final cash flow discounted· by the instantaneous forward rate. However zero-coupon rate are called as spot rate or short rate due to that it is defined as the theoretical profit obtained by a zero-coupon bond. Usually this rate is used to estimate how much we can gain in the future (time t1) if we invest X amount CU today (time t0). The following equation explains this relationship (Röman, 2017, P.24):

t1 Xt1 = (1 + rspot)) Xt0 . (2.12) If we invert this equation we can get the discounted present value as [19, p.24]:

1 PV(Xt1 ) = t Xt1 , (2.13) (1 + rspot) 1

1 where t is called as discount factor which shows the relation between the spot rate and (1+rspot ) 1 the discount function. It is easy to see that this rate is the same as the annual effective rate, denoted as rannual. For the term of continuous compounding, the discount function becomes:

rspot (t) t p(t) = e− · , (2.14)

= ⇒ p(t,T) = exp r(t,T) (T t) . (2.15) {− · − } According to the previous equation and eq.(2.11) we can also define the spot rate as the continuous average of forward rate:

1 T rspot(t,T) = f (t,u)du . (2.16) T t t − Z  Therefore, the instantaneous spot rate at t is given as:

rspot(t) = f (t,t). (2.17)

10 2.1.2 Forward rates from coupon bonds In the previous subsection I interpreted implied forward interest rates based on yields to matur- ity on zero-coupon bonds, spot rate. Because a coupon bond can be considered as a portfolio which is consisted by zero-coupon bonds with different maturities (each zero-coupon bond corresponding to a particular coupon payment). We notice that yields to maturity on coupon bonds are not same as yields to maturity on zero-coupon bonds of the same maturity. Furthermore, to compute implied forward interest rates from yields to maturity on zero- coupon bonds is easier than to compute implied forward interest rates from on coupon bonds. This is because that "yields to maturity on coupon bonds are a kind of average of yields to maturity on zero-coupon bonds of maturities from the time of the first coupon payment to the time of the payment of the face value and last coupon" [21, p.2]. Whereas, we have to discover the approach of estimating forward rates from coupon bonds since almost all bonds with time to maturity over 12 months are coupon bonds rather than zero-coupon bonds. Lars Svensson [21] proposed a two steps approach of estimating forward rates from coupon bonds. First step: to estimate implied spot rate from yields to maturity on coupon bonds. Second step: to calculate implied forward rates from implied spot rates. To understand this more precisely, we can start with discount functions with different interest rate types. Especially, for annual rates, if we receive interest, we have to ask us how often we get payments. That is why we have [19, p.19]:

f t r f · (1 + r )t = 1 + . (2.18) annual f   In continuous compounding this will turn to [19, p.19]:

r f t f · t rc t lim 1 + ,= (1 + rannual) = e · , (2.19) f ∞ f ⇒ →   where f denotes the number of annual payments, r f is interest rate paid f times every year and rc is continuous compounding interest rate. Actually the right side of the equation above is same as the discount function eq.(2.14). We find that there is conversion between the annually compounded interest rate and continuously compounded interest rate. According to eq.(2.19) we can also obtain [19, p.20]: r f rc = f ln 1 + , (2.20) · f   and rc r f = f exp 1 . (2.21) · f −     The relation between the annually compounded interest rate and continuously compoun- ded interest rate showed above is the same as Lars Svensson [21] in his research paper ex- plained 1. Thus we can present discount function as [21, p.3]:

1The expressions from a research paper of Frage [21, p.2] to explain the relation between the continuously compounded spot rate and the annually compounded spot rate:

11 i(t,T) d(t,T) = exp (T t) , (2.24) − 100 −   where d(t,T) denotes the price at time t of a zero-coupon bond that pays 1 UC at the maturity date T, i(t,T) (measured in percent per year) is the continuously compounded spot rate for a zero coupon bond traded at t and matured at T, T > t. Regarding to coupon bonds, if we consider a coupon bond with coupon rate c percent per year, and assume the time to maturity m = T t is integer, unit in year. Then the present value P(t,t + m) at the trade date t of a coupon payment− made in year k, k = 1,2,...,m will equal to [21, p.3]:

m P(t,t + m) = ∑ cd(t,t + k) + 100d(t,t + m), (2.25) k=1 where d( ) is discount functions and 100 is face value. Since· yields to maturities are often used to discount cash flows. We reform the previous equation in term of yield to maturity [21, p.3]:

m y(t,t + m) y(t,t + m) P(t,t + m) = cexp k + 100exp m , (2.26) ∑ − 100 − 100 k=1     where y(t,t + m) denotes yield to maturity. Here yield to maturity which is considered as internal rate of return for the coupon bond is constant interest rate that makes the present value of the coupon payments and the face value equal to the price of the bond. Nevertheless, yield curves based on the yield to maturity on coupon bonds for different maturities are an inaccurate expression of the term structure of interest rates. Svensson [21] listed two reasons for this. One is that a given yield to maturity can be seen as an average of the spot rates up to the time to maturity. The corresponded spot rates in eq.(2.24) which also affect eq.(2.25) are generally vary with the maturity. On the other hand, the yield to maturity, y(t,t +m), in eq.(2.26) is constant and can be seen as a somewhat complex average of the spot rates. The second reason is two coupon bonds with same maturity date usually have different yields to maturity if they have different coupon rates. This is easy to see if we take everything else equal, that is, P(t,t + m) doesn’t change, when coupon rate c increases, y(t,t + m) will decrease. Hence, we shouldn’t use yield curves for coupon bonds as direct expression of term structure of interest rates. Instead, we should use spot rates. It is easy to compute implied forward rates from spot rates if we readjust a forward in- vestment by a sale and a buy of zero-coupon bonds. A better explanation is that to sell a

i i = 100 exp 1 , (2.22) 100 −     and i i = 100ln 1 + , (2.23) 100   where i is continuously compounded spot rate, i is annually compounded spot rate and both measured in percent- age. Here all rates are assumed to be continuously compounded.

12 zero-coupon bond with maturity at t0 which is also the settlement date of a forward contract and to buy a same market value zero-coupon bond with same maturity date as the forward contract’s maturity date, T. Let f (t,t0,T) (measured in percent per year) be the continuously compounded (implied) forward rate for the forward contract with the trade date, t. Then in relation with the spot rate, the forward rate equals to [21, p.4]:

(T t)i(t,T) (t t)i(t,t ) f (t,t ,T) = − − 0 − 0 , (2.27) 0 T t − 0 where t < t0 < T, t,t0 and T denote the trade date, the settlement date and the maturity date respectively. i( ) is spot rate. For example, if this investment is 1-year forward contract with · settlement in 4 years from now (t0 t = 4) and mature in 5 years (T t = 5). Then the forward rate for this investment equals to 5− times 5-year spot rate subtract 4 times− 4-year spot rate. This is exactly as eq.(2.27) expressed. Then the instantaneous forward rate can be presented as [21, p.4]:

f (t,t0) = lim f (t,t0,T). (2.28) T t → 0 And according to the definition of spot rate and eq.(2.16), we obtain the spot rate i(t,T) is hence defined as the continuous average of forward rate [21, p.4]:

T f (t,τ)dτ i(t,T) t (2.29) ≡ T t R − 2.1.3 Par rate and par yield

The par rate rpar is the fixed rate which makes value of its payments same as a number of opposite floating rate payments. This means that their total values sum up to zero as Figure 2.1 below shows. The typical instrument with the par rate is a plain vanilla IRS.

Figure 2.1: The par rate rpar is the constant rate that equalizes the value of the floating leg (dotted arrows) to the fixed leg over the lifetime of the swap [19, p.23]

The par yield cpar is the coupon rate which values the total (discounted) value of an instru- ment, included the nominal value, equals to its nominal value as Figure 2.2 shows.

13 Figure 2.2: The par yield is the yield that equals the coupon rate cpar so that the price of the bond is equal to its face value, nominal amount, here set to 100 [19, p.23]

Thereby the par rate for a swap can be calculated as [19, p.23]:

ti ti 1 ∑i(p(0,ti) r − − ) ti ti 1 · f orward ∑(p(0,ti) rpar) = ∑(p(0,ti) r f− orward− ) = rpar = , (2.30) i · i · ⇒ ∑i(p(0,ti)

where p(0,ti) what is the discount factor at time ti is the price of a zero-coupon bond with ti ti 1 maturity at ti. The rate r f− orward− expresses the floating rate and is given by the forward rate between time ti and ti 1. Subsequently, the− par rate of a bond can be calculated as [19, p.24]:

n 100 (1 p(0,tn)) 100 = ∑(p(0,ti) cpar) + (p(0,tn) 100) = cpar = · n − . (2.31) i · · ⇒ ∑i (p(0,ti)

2.1.4 Market instruments In this section, I will briefly introduce some market instruments which will be used in practical section later. In the current market situation, due to similar instruments may present very different price levels, liquidity and even may also cause unreliable forward rates. Thus it is necessary to select the corresponding sets of instruments carefully in order to construct multiple yield curve. Market instruments nearly cover different maturities and overlap in major areas. That is why we should choose those with more liquid ones, namely ones with a tighter bid/ask spread.

Bonds As fixed-income securities bonds are issued by the seller who will pay a series of cash flows in the future in order to receive bond price. There are two kinds of bonds, namely zero coupon bonds and coupon bonds.

14 Zero coupon bonds what are also called as pure discount bonds only have one single cash flow at maturity. The payment equals to one unit of currency (also called principal or notional amount). On the contrary, coupon bonds have a sequence of coupons in special coupon payment dates in addition to the principal.

Deposits A deposit is zero-coupon contract which is a standard loan arrangement between two banks and traded in over-the-counter (OTC) market. In more details, the party that place the deposit has a credit that can be used in various ways, such as for purchases or to transfer it to another party. The rate for a loan is referred as a deposit rate [19]. Deposits start at a reference date t0 Depo (today or spot) and pay a given fixed interest rate accrued until maturity Ti. Let Rx (t0,Ti) be the quoted rate associated to the i:th deposit with maturity Ti and underlying rate tenor x = t0 months. Then implied discount factor at time Ti is displayed as [19, p.547]: 1 p(t0,Ti) = Depo , t0 < Ti, (2.32) 1 + Rx (t0,Ti) τF (t0,Ti) · where τF is time interval.

Forward rate agreements FRAs are forward starting deposit contracts. In more details, FRA is a contract between two counter parties that agree during a time t to exchange interest rate payments in a future time T (where T > t). FRA contracts have many different expressions. For example in Euribor, the 3x9 FRA is a 6 months deposit starting 3 months forward. In some markets such as in Sweden FRAs are quoted between IMM days2. Usually the underlying forward rate is determined two working days before the forward start date. Together with deposits market FRAs can be used to construct the short-term yield curve. For instance, let FX (t,Ti 1,Ti) be the i:th Euribor forward rate resetting at time Ti 1 with tenor − − x = Ti Ti 1 months related to the i:th FRA with maturity Ti. Then according to eq.(2.6) the − − implied discount factor at time Ti can be expressed as [19, p.548]:

px(t0,Ti 1) px(t0,Ti) = − , t0 < Ti 1 < Ti. (2.33) 1 + Fx(t0,Ti 1,ti) τF (Ti 1,Ti) − − · − According to the definition of the instantaneous forward rate as eq.(2.10) showed, when the forward starting date of the FRA Ti 1 gets closer to the current date t0, each FRA rate gets closer to the matching spot deposit rate− as the following equation shows [19, p.548]:

depo lim Fx(t0,Ti 1,Ti) = Rx (t0,Ti). (2.34) Ti 1 t0 − − → 2IMM is abbreviation of International Monetary Market days that is the third Wednesday in March, June, September and December [19, p.6].

15 Interest rate futures

There is another instrument which is often traded in stock market. It is called as interest rate future which is a futures contract with an interest-bearing instrument as the underlying asset. A common misconception as many believe that buying an interest rate futures contract allows the buyer of the contract to lock in a future borrowing rate. Actually buying the contract is equivalent to lending money. Conversely selling equivalent to borrowing money. For instance, being long involved in an interest rate future indicates that the buyer has agreed to receive a rate at a certain period in the future [19]. The underlying asset of interest rate futures is an underlying security which is a debt obligation and its value changes as interest rates change. Typical interest rate futures are EuroDollar3 futures and Euribor futures. A single future is closer to a FRA, which means to borrow or lend a nominal amount for a time, typcally 3 months, in the future. The future contracts are contracts with delivery at IMM4 and settled in cash5 on the second London business day before the IMM days. This indicates that its interest rate underlying is the interest rate for 91-day period [19]. Furthermore, the future contracts what are quoted in price6 are based upon rate7 at maturity and can be used to hedge future interest rate exposures. The futures price what depends on the final marking to market equals to 100 R, where R is the interest rate expressed with quarterly compounding and an actual/360 day-count− convention [19].

Swaps

Swaps are OTC agreements and are one of the most popular fixed-income derivatives which are contractual agreements that two counter parties agree to exchange cash flows during a specific period in the future, for instance a floating interest rate cash flows, usually a Libor rate cash flows, against a fixed rate cash flows. In a swap agreement the dates when the cash flows are to be paid and the way in which they are to be calculated will be defined. It is common that the future value of an interest rate, an exchange rate, or other market variable will be used for calculating the cash flows. A forward contract what has the exchange of cash flows on just one future date can be seen as a simple example of a swap. However, swaps typically lead to cash flow exchanges on several future dates.

3EuroDollars are USD deposited in banks outside the United States, which implies they are not under the jurisdiction of the Federal Reserve. Euribor futures are similar contracts in Euro [19]. 4The actual interest rate for the contract period is known on IMM [19]. 5"The settlement price of a contract is defined to be 100.00 minus the official British Banker’s Association (BBA) fixing of 3-month LIBOR/Euribor on the day the contract is settled" [19, p.73] 6"A quoted price of 95.00 means an interest rate of 100.00–95.00, or 5 percent" [19, p.73]. 7"LIBOR reflects the average rate at which banks can obtain unsecured funding in the London inter-bank market for a particular currency and a particular time period" [19, p.32]. Before 1 February 2014 the administrator of LIBOR was the BBA. Regarding to the finding of the attempted manipulation of LIBOR, a new administrator of LIBOR, Intercontinental Exchange (ICE), took over LIBOR. However its era of influence is slated to end by 2022 [12].

16 Plain vanilla interest-rate swap is an agreement that two counter parties agree to exchange fixed against floating rate cash flows. In this agreement, notional amount or face value of the swap, the payment frequency, maturity, , the coupon, that is the fixed rate, and the floating rate have to be specified. In most cases, swaps are arranged so that their net value is zero at the starting date. In other words, the value of the fixed leg should equal to the value of the floating leg. Generally for IRSs, two counter parties only exchange interest rate payments not the face value. There are several purposes to be involved in a swap for counter parties. One of the most common application is to hedge against interest rate risk. The theory of comparative ad- vantages can explain motivation of this application. The comparative advantages means that counter parties often has different abilities for borrowing in capital markets. This could hap- pen in regard to differences in credit rating or tax treatment, or for accounting reasons. One explanation of the popularity of swaps concerns comparative advantage can be considered as the use of an IRS to transform a liability. Some companies might have a comparative ad- vantage when borrowing in fixed-rate markets, whereas other companies have a comparative advantage when borrowing in floating-rate markets. To achieve this goal, it makes sense for companies to search a new opportunity in the market where it has a comparative advantage. Swaps become good choice for those companies, for example, to transform a fixed-rate loan into a floating-rate loan, and vice versa. To understand aforementioned contents well I take a simple example. I assume Microsoft and Intel both want to enter in a swap. Suppose that Microsoft has arranged to borrow $100 million at LIBOR plus 10 basis points8. After Microsoft has entered into the swap, it has the following three sets of cash flows [13, p.155]:

1. It pays LIBOR plus 0.1% to its outside lenders.

2. It receives LIBOR under the terms of the swap.

3. It pays 5% under the terms of the swap.

The net of these three cash flows will be an interest rate of 5.1 percent. For Intel, the swap could have the effect of transforming a fixed-rate loan into a floating- rate loan. Suppose that Intel has a 3-year $100 million loan remaining which it pays 5.2 percent. After it has entered into the swap, it has the following three sets of cash flows [13, p.156]):

1. It pays 5.2% to its outside lenders.

2. It pays LIBOR under the terms of the swap.

3. It receives 5% under the terms of the swap.

The net of these three cash flows will be an interest rate of Libor plus 20 basis points. We also can use one figure 2.3 to explain those transforms.

8One basis point is one-hundredth of 1%.

17 Figure 2.3: Microsoft and Intel use the swap to transform a liability [13, p.155])

In this swap, Microsoft pays a fixed rate at 5% to Intel while Intel pays a Libor rate to Microsoft. The swap helps Microsoft transform borrowings at a floating rate of Libor plus 10 basis points into borrowings at a fixed rate of 5.1%. Meanwhile, the swap helps Intel transform borrowings at a fixed rate of 5.2% into borrowings at a floating rate of Libor plus 20 basis points. Regarding to the comparative advantages there is another use of the swap, namely using the swap to transform an asset. But this is not the concern in this writing.

Overnight indexed Swap (OIS) are IRSs based on a specific currency that a fixed rate (OIS rate) for a period (e.g., 1 month or 3 months) is swapped for the geometric average of the overnight rates during the period [13]. However, it is not perfectly risk-free since a default on an overnight loan or the swap is always possible. For swaps based on the Euro (EUR), the referenced floating rate is termed the euro overnight index average (EONIA) which will be discuss more later. In the US, the weighted average of the rates in brokered transactions (with weights proportional to transaction size) is termed the effective federal funds rate and in the UK the average of brokered overnight rates is termed the sterling overnight index average (SONIA). Other popular overnight indices are TONAR (Tokyo Over-Night average rate) and SARON (Swiss Average Rate Overnight). The choice of a risk-free discount rate has become one of the most important issues in derivatives markets since the credit crisis of 2007. Prior to the credit crisis, LIBOR/swap rates were used as proxies for risk-free rates. After the credit crisis, most banks have changed their risk-free proxy from the LIBOR rate to the OIS rate—at least for collateralized derivatives transactions. This change indicates that the discount rate used by a bank for a collateralized derivative is not a true risk-free rate since it should correspond to the average funding costs for this collateralized derivative. For a non-collateralized derivative, its average funding costs should be equal or higher than Libor [13]. OIS rates have been considered as a suitable rate which can provide an estimate of the funding costs for these transactions.

2.1.5 Interbank rate

The interbank rate is the average rate which banks can borrow from each other. Some of the in- terbank rates are LIBOR-London Interbank Offer Rate, Euribor-Euro Interbank Offered Rate and STIBOR-Stockholm Interbank Offer rate, etc. The following contents will be focused on two interbank rates which are needed in practice sections.

18 Euribor is a daily reference rate which is published by the European Money Markets Institute (EMMI) and is based on the averaged interest rates at which euro-zone banks offer to lend and borrow unsecured funds from each in the euro interbank market [19]. It is the rate which is contributed by the panel of banks. Prior to September 2012, the panel of banks contributing Euribor consisted of 44 banks. Whereas nowadays the panel of banks contributing to Euribor consists of 18 banks which provide daily quotes of the rate that each panel bank believes one prime bank is quoting to another prime bank for interbank term deposits within the Euro zone [3]. The Euribor rates is used as a reference rate for euro-denominated FRAs, short-term interest rate futures contracts and IRSs. For IRSs, Euribor rate quoted as x-months Euribor is standard plain vanilla swap which begins at spot date with annual fixed leg against floating leg. Here index x-months indicates interests are paid with x-months frequency. For example, 3-months Euribor and 6-months Euribor. Such swaps can be seen as portfolios of FRA contracts (the first one being actually a deposit) [19]. The day count convention for this swap is act/360. Swaps are selected to contribute medium-long term structure section of the yield curve.

Eonia is the other widely used reference rate in the euro-zone and it refers to Euro Over-Night Index Average which is computed as a daily weighted average of all overnight unsecured lending transactions in the interbank market within euro-zone [19]. It is necessary to point out that Eonia differs with Euribor as it is an average of actual transactions that has taken place between banks. Moreover, the panel of banks contributing to Eonia consists of 28 banks [2](EMMI, 2020). However, it has the same day count convention as Euribor, namely act/360. It is used by most banks as OIS discount rate. Note that "Overnight" means from 1 day to next bussiness day, until the interbank payment system TARGET9 closes. On each day when the TARGET system is open, each Panel Bank should send the total volume of unsecured lending transactions that day and the weighted average lending rate for these transactions calculated by the respective Panel bank itself to the European Central Bank (ECB) no later than 6:30 p.m.. Based on those information contributed by panel banks ECB calculates Eonia and publish it between 6:45 p.m. and 7:00 p.m. on the same evening.

9"The Trans-European Automated Real-time Gross settlement Express Transfer system" [19, p.39]

19 Chapter 3

Implementation with market data(excl. the ENS model)

3.1 Bootstrapping method

In financial markets there are two types of yield curves, i.e., market curves and implicit curves. While the market curves are constructed from the market quotations (e.g., swap curves), the implicit curves are constructed through transformations (e.g., zero-coupon yield curves). As we all know that without the yield curves we are not able to value financial instrument such as cash-flow instruments, equities, commodities and derivatives. For this reason, many researchers have developed methods and models to construct and forecast yield curves from prices of traded assets. One of the most popular methods is bootstrap method with linear interpolation to create the term structure of interest rate. Bootstrap method in finance is a method for obtaining zero-coupon rates from a series of market prices of coupon bearing instruments such as bonds and swaps in order to build a yield curve. This method involves starting with short-term instruments and moving progressively to longer-term instruments. The generic methodology to construct a curve of zero-coupon instruments is the following:

1. During the first step, a set of yielding products (e.g., coupon-bearing bonds).

2. In the second step, discount factors are derived.

3. In the third step, the zero-coupon curve is bootstrapped.

In the following subsections I will explain algorithm and procedure of bootstrap method for some instruments in detail.

3.1.1 Bootstrapping the OIS Eonia curve Different kind of curves created by banks are used for different kinds of trades. The discount rate should reveal the cost of funding for a bank, which we have discussed in the aforemen- tioned section of OIS. The market standard discount curve now consists of OIS rates.

20 In euro-zone, Eonia represents OIS curve. Hull [13] argued that it is necessary for the rates being bootstrapped to be the same as the rates being used for discounting in order to define a series of par yield bonds for the swap rates. To get OIS discounting we have to bootstrap Eonia curve first. However, in some systems of market participants annually compounded discount 1 function, p(t) = (1+r(t))t , is adopted to calculate OIS discount factors. The data of Eonia rates was obtained from Bloomberg on 2020-04-14. Note that here we are not going to discuss how the market quotes are estimated. The quotes are set by the market-makers as prices (some instruments are quoted with yield) they agree to be used when buying or selling the specific swaps on the interbank market. In this section I aim to describe the basics of discount curve bootstrapping. The compre- hensive description of the standard techniques will be introduced when extracting discount factors from market data. Now we will focus on the extraction of discount factors from European OIS, called Eonia swaps. Notes that here we assume that the collateral and the pay currency are the same, both are Euro. Let us consider a "riskless" asset B with value process B(t) t 0,B(0) = 1, then we get [9, p.2]: { } ≥

nt OIS r j d j B(t) = ∏ 1 + , t 0, (3.1) j=1 360 ! ≥ where nt is the number of business days in the considered period from today 0 until t and r j the reference rate fixed on day j relevant for the next d j days (usually one day as it is an overnight rate, except for weekends and holidays). The existence of such an asset is always implicitly assumed. However, it is central assumption of bootstrap. Since the discount factors what we need are based on the assumption that one is able to borrow/lend at the given reference rate on every date. For this reason we also can interpret why using Euribor rates with longer tenor is difficult as it does not seem reasonable to receive those rates on a riskless, respectively default free, asset [9]. "For an OIS the floating rate is a daily compounded O/N rate and the market quotes" [19, p.563]. The Eonia curve we have typically quotes given by O/N, 1W, 1M, 2M, 3M for short- term of the curve. 6M, 9M, 1Y...30Y for medium- and long-term of the curve. The maturities of Eonia is a set, Ti O/N,1W,1M,2M,3M..., and T1 < T2 < ... < Tn, respectively, the cor- ∈ responding par swap rates si. We assume that a swap with maturity Ti exchanges payments at the dates T1 < T2 < ... < Ti, which at Tj is a fixed payment of si(Tj Tj 1) versus a floating − − payment of f (Tj 1,Tj)(Tj Tj 1). The floating payment is linked to the reference rate by [9, p.3]: − − −

nTj OIS r j d j f (Tj 1,Tj)(Tj Tj 1) = 1 + 1, (3.2) − − − ∏ 360 − j=nTj 1 +1 ! − OIS where r j is OIS rate (fixed rate) at time Tj and f (Tj 1,Tj) is floating rate at interval (Tj 1,Tj). Then the fixed leg will be [9, p.3]: − −

21 i FixedLegi = si ∑ D(0,Tj)(Tj Tj 1), (3.3) j=1 − − where si is quoted fixed rate, namely swap rate. There is an obvious connection between both aforementioned properties of swaps that the value of the fixed leg equals to the value of the floating leg, we obtain [9, p.3]:

B(Tj) f (Tj 1,Tj)(Tj Tj 1) = 1. (3.4) − − − B(Tj 1) − − This reflects the property of swaps that the swaps are structured in a way that the floating payments equal the interest earned on the reference rate. Eq.(3.4) indicates that an investment of 1 in B at t =0 can yield all the required floating payments plus an additional fixed payment of 1 at the last payment date. According to eq.(2.6) we get

1 B(Tj 1) f (Tj 1,Tj)(Tj Tj 1) = − 1 − − − 1 − B(Tj) D(0,Tj 1) (3.5) = − 1 D(0,Tj) − D(0,Tj 1) D(0,Tj) = − − . D(0,Tj) Hence, the floating leg will be:

i FloatingLegi = ∑ D(0,Tj) f (Tj 1,Tj)(Tj Tj 1) = 1 D(0,Ti). (3.6) j=1 − − − − Similarly, the fixed leg turns to:

i FixedLegi = si ∑ D(0,Tj)(Tj Tj 1) = 1 D(0,Ti). (3.7) j=1 − − − Once again both the aforementioned equations prove that the property of swaps that the value of the floating leg equals the value of the fixed leg. Consequently, solving for D(0,Ti) by [9, p.3]:

i 1 1 si ∑ j−=1(Tj Tj 1)D(0,Tj) D(0,Ti) = − − − , 1 < i < n, (3.8) 1 + si(Ti Ti 1) − − is commonly known as bootstrapping the discount factors. Nevertheless, Röman [19] argued that discount function should be different between ma- turities up to one year and maturities over one year for STINA1. Thus accordingly we infer [19, p.7]:

1STINA means STIBOR (Stockholm Interbank Offered Rate) T/N (Tomorrow-Next) Average [19]

22 i 1 Tj Tj 1 DO/N si ∑ j−=1 −360− D(0,Tj) DT = − , (3.9) Ti Ti 1  1 + si −360− for one year tenors and  

i 1 Tj Tj 1 D si ∑ − − − D(0,Tj) O/N − j=1 360 DT = T T , (3.10)  i− i 1  (1 + si) 360− for tenors longer than a year. And over-night discount factor will be: 1 DO/N = . (3.11) 1 + s d O/N · 360 Table 3.1 shows the data of Eonia rates at 2020-04-14. The calculations of OIS discount factors and OIS forward rates are carried out in Python. The process of implementation is included in AppendixA. According to eq.(2.7) and eq.(3.5) we can obtain forward rates as:

1 D(0,Tj 1) D(0,Tj) f (Tj 1,Tj) = − − . (3.12) − Tj Tj 1 · D(0,Tj) − − As aforementioned the floating rate of OIS is a daily compounded O/N rate and in accord- ance with eq.(2.9) we can interpret the continuously compounded zero rate as:

OIS ln(DT ) ZT = 100 . (3.13) − · (Tj Tj 1)/365 − − Consequently, we get the following table, Table 3.2. The discount curve and the yield curves are illustrated in Figure 3.8 and figure 3.2.

3.1.2 Bootstrapping 3-months Euribor and 6-months Euribor Before and after the financial crisis Before the financial crisis in 2007, people never doubted those sophisticated investment banks’ abilities to value a plain vanilla IRS. The credit crunch was the main reason of the crisis which was based on increase of basis spreads between similar interest rate instruments with different underlying rate tenors, especially for swaps. For instance, basis spreads between Euribor and Eonia OIS swaps diverged significantly from zero and were not negligible anymore [14]. What we have learned from the crisis was that the risk related to unsecured bank lending became apparent and consequently, the longer the tenor of Euribor rates, the higher the risk investors associate with those rates and thus, the higher the rates. Hence, It is not appropriate to value a swap with a different tenor based on the previously bootstrapped discount factors. That’s why there is another procedure so called dual curve stripping or curve cooking which we will present later on.

23 Name Quote From date To date Days EONIA O/N -0.451 2020-04-14 2020-04-15 1 EUR 1W OIS -0.4583 2020-04-14 2020-04-23 9 EUR 1M OIS -0.4606 2020-04-14 2020-05-18 34 EUR 2M OIS -0.4645 2020-04-14 2020-06-16 63 EUR 3M OIS -0.4696 2020-04-14 2020-07-16 93 EUR 6M OIS -0.4841 2020-04-14 2020-10-16 185 EUR 9M OIS -0.4978 2020-04-14 2021-01-18 279 EUR 1Y OIS -0.5077 2020-04-14 2021-04-16 367 EUR 15M OIS -0.5169 2020-04-14 2021-07-16 458 EUR 18M OIS -0.5217 2020-04-14 2021-10-18 552 EUR 21M OIS -0.5242 2020-04-14 2022-01-17 643 EUR 2Y OIS -0.5232 2020-04-14 2022-04-18 734 EUR 27M OIS -0.5261 2020-04-14 2022-07-18 825 EUR 30M OIS -0.5245 2020-04-14 2022-10-17 916 EUR 2Y 9M OIS -0.5205 2020-04-14 2023-01-16 1007 EUR 3Y OIS -0.5149 2020-04-14 2023-04-17 1098 EUR 3Y 3M OIS -0.5095 2020-04-14 2023-07-17 1189 EUR 3Y 6M OIS -0.5037 2020-04-14 2023-10-16 1280 EUR 3Y 9M OIS -0.4973 2020-04-14 2024-01-16 1372 EUR 4Y OIS -0.4902 2020-04-14 2024-04-16 1463 EUR 4Y 3M OIS -0.4823 2020-04-14 2024-07-16 1554 EUR 4Y 6M OIS -0.4736 2020-04-14 2024-10-16 1646 EUR 4Y 9M OIS -0.4645 2020-04-14 2025-01-16 1738 EUR 5Y OIS -0.4549 2020-04-14 2025-04-16 1828 EUR 5Y 3M OIS -0.4453 2020-04-14 2025-07-16 1919 EUR 5Y 6M OIS -0.4353 2020-04-14 2025-10-16 2011 EUR 5Y 9M OIS -0.4251 2020-04-14 2026-01-16 2103 EUR 6Y OIS -0.4147 2020-04-14 2026-04-16 2193 EUR 6Y 3M OIS -0.4042 2020-04-14 2026-07-16 2284 EUR 6Y 6M OIS -0.3934 2020-04-14 2026-10-16 2376 EUR 6Y 9M OIS -0.3821 2020-04-14 2027-01-18 2470 EUR 7Y OIS -0.3714 2020-04-14 2027-04-16 2558 EUR 7Y 3M OIS -0.3602 2020-04-14 2027-07-16 2649 EUR 7Y 6M OIS -0.3486 2020-04-14 2027-10-18 2743 EUR 7Y 9M OIS -0.3373 2020-04-14 2028-01-17 2834 EUR 8Y OIS -0.3258 2020-04-14 2028-04-17 2925 EUR 8Y 6M OIS -0.3032 2020-04-14 2028-10-16 3107 EUR 9Y OIS -0.2806 2020-04-14 2029-04-16 3289 EUR 9Y 6M OIS -0.2584 2020-04-14 2029-10-16 3472 EUR 10Y OIS -0.2361 2020-04-14 2030-04-16 3654 EUR 12Y OIS -0.1477 2020-04-14 2032-04-16 4385 EUR 15Y OIS -0.0444 2020-04-14 2035-04-16 5480 EUR 20Y OIS 0.0225 2020-04-14 2040-04-16 7307 EUR 25Y OIS 0.0071 2020-04-14 2045-04-17 9134 EUR 30Y OIS -0.0368 2020-04-14 2050-04-18 10961

Table 3.1: EONIA rates at 2020-04-14a aSource: Bloomberg at 2020-04-14. 24 Name Quote From date To date Days Discount Forward Spot EONIA O/N -0.451 2020-04-14 2020-04-15 1 1.00001252793472-0.450999999999585-0.457266753162583 EUR 1W OIS -0.4583 2020-04-14 2020-04-23 9 1.00012711604027-0.515580936367857-0.515493400291399 EUR 1M OIS -0.4606 2020-04-14 2020-05-18 34 1.00044769541751-0.461427724142001-0.480506645922278 EUR 2M OIS -0.4645 2020-04-14 2020-06-16 63 1.0008258696548-0.469070282961994-0.478282565742515 EUR 3M OIS -0.4696 2020-04-14 2020-07-16 93 1.00122661312711-0.480303020784519-0.48111766658352 EUR 6M OIS -0.4841 2020-04-14 2020-10-16 185 1.00250434353045-0.498732464755508-0.493482542749158 EUR 9M OIS -0.4978 2020-04-14 2021-01-18 279 1.00387971576616-0.52470260606523-0.506579323897994 EUR 1Y OIS -0.5077 2020-04-14 2021-04-16 367 1.00520412748153-0.538999769137221-0.516234598122799 EUR 15M OIS -0.5169 2020-04-14 2021-07-16 458 1.00661600467764-0.554873777331133-0.525521498946875 EUR 18M OIS -0.5217 2020-04-14 2021-10-18 552 1.00805059208214-0.545028649458078-0.530199459381391 EUR 21M OIS -0.5242 2020-04-14 2022-01-17 643 1.00942662282304-0.539280218371716-0.532597411889658 EUR 2Y OIS -0.5232 2020-04-14 2022-04-18 734 1.01074540674105-0.516170255472784-0.531491971317548 EUR 27M OIS -0.5261 2020-04-14 2022-07-18 825 1.0121509384075-0.54935927469716-0.534347097481486 EUR 30M OIS -0.5245 2020-04-14 2022-10-17 916 1.01345767973635-0.51008801250395-0.532674046186954 EUR 2Y 9M OIS -0.5205 2020-04-14 2023-01-16 1007 1.01469016224648-0.480516631238024-0.528590572308455 EUR 3Y OIS -0.5149 2020-04-14 2023-04-17 1098 1.01585441051151-0.453393445413074-0.522902129681962 EUR 3Y 3M OIS -0.5095 2020-04-14 2023-07-17 1189 1.01699804005016-0.444863072114309-0.517421724564593 EUR 3Y 6M OIS -0.5037 2020-04-14 2023-10-16 1280 1.01810094488266-0.428556718139346-0.511543884644207 EUR 3Y 9M OIS -0.4973 2020-04-14 2024-01-16 1372 1.0191663387116-0.409053185504009-0.505066837835035 EUR 4Y OIS -0.4902 2020-04-14 2024-04-16 1463 1.02015692291336-0.384136455512101-0.49788847789851 EUR 4Y 3M OIS -0.4823 2020-04-14 2024-07-16 1554 1.02107708684452-0.356506771656568-0.489908863706539 EUR 4Y 6M OIS -0.4736 2020-04-14 2024-10-16 1646 1.02193394798843-0.328097027948742-0.481127201322867 EUR 4Y 9M OIS -0.4645 2020-04-14 2025-01-16 1738 1.02272673203556-0.303326230567583-0.471944730672365 EUR 5Y OIS -0.4549 2020-04-14 2025-04-16 1828 1.02342110401107-0.27139247873125-0.462260891980387 EUR 5Y 3M OIS -0.4453 2020-04-14 2025-07-16 1919 1.02407979838881-0.254455162191572-0.452578158870841 EUR 5Y 6M OIS -0.4353 2020-04-14 2025-10-16 2011 1.02467918453885-0.228893501572751-0.442493491309696 EUR 5Y 9M OIS -0.4251 2020-04-14 2026-01-16 2103 1.02521491033727-0.204475990398409-0.432207542589984 EUR 6Y OIS -0.4147 2020-04-14 2026-04-16 2193 1.02566162717677-0.174216068015335-0.42172053863055 EUR 6Y 3M OIS -0.4042 2020-04-14 2026-07-16 2284 1.02606053035214-0.153799746629003-0.411132251765344 EUR 6Y 6M OIS -0.3934 2020-04-14 2026-10-16 2376 1.02639640548717-0.128049357893781-0.400240815360121 EUR 6Y 9M OIS -0.3821 2020-04-14 2027-01-18 2470 1.02666284184119-0.0993894495549893-0.388844442645402 EUR 7Y OIS -0.3714 2020-04-14 2027-04-16 2558 1.02684869331318-0.0740422110185474-0.378050266554918 EUR 7Y 3M OIS -0.3602 2020-04-14 2027-07-16 2649 1.02697447311381-0.0484520728687219-0.366750937068524 EUR 7Y 6M OIS -0.3486 2020-04-14 2027-10-18 2743 1.02704101468862-0.0248130376571004-0.355044888532497 EUR 7Y 9M OIS -0.3373 2020-04-14 2028-01-17 2834 1.027040489208320.000202409073543519-0.343637774947475 EUR 8Y OIS -0.3258 2020-04-14 2028-04-17 2925 1.026964710610070.029191213927227-0.332026071331823 EUR 8Y 6M OIS -0.3032 2020-04-14 2028-10-16 3107 1.026669044881010.0569641515096021-0.309194175615984 EUR 9Y OIS -0.2806 2020-04-14 2029-04-16 3289 1.026137699933330.102424068862824-0.286339650186743 EUR 9Y 6M OIS -0.2584 2020-04-14 2029-10-16 3472 1.025417621854730.138143426609163-0.263867725571704 EUR 10Y OIS -0.2361 2020-04-14 2030-04-16 3654 1.024447884255190.187238639883609-0.24127376998384 EUR 12Y OIS -0.1477 2020-04-14 2032-04-16 4385 1.018350250246630.294882705856612-0.151359849541542 EUR 15Y OIS -0.0444 2020-04-14 2035-04-16 5480 1.006884899150320.374365580474891-0.0457003076200959 EUR 20Y OIS 0.0225 2020-04-14 2040-04-16 7307 0.9953924601538210.2275002162423280.0230688155985353 EUR 25Y OIS 0.0071 2020-04-14 2045-04-17 9134 0.998195077666152-0.05532384563534050.00721909247445399 EUR 30Y OIS -0.0368 2020-04-14 2050-04-18 10961 1.01131960701282-0.255716801992705-0.0374824119929784

Table 3.2: The discounted OIS curve at 2020-04-14

25 Figure 3.1: The bootstrapped discount curve for Eonia at 2020-04-14 (Table 3.2)

Figure 3.2: The bootstrapped yield curve for Eonia at 2020-04-14 (Table 3.2)

26 Bootstrapping Euribor

Now, we move to Euribor which is considered as a set of swaps with floating payments linked to its rates with a given tenor. Note that it is not possible to invest at this rate, especially not riskless. However, if we replicate an investment with an asset at this rate or to model the dynamics of such a system then we also need to consider the related default risk [9]. Those swaps are contracts that two counter parties exchange fixed payments against float- ing payments linked to an exogenous index. Such contracts are usually collateralized swap contracts, which means that the exchanged payments themselves are not exposed to credit risk, especially for the credit risk causing the basis spread. Moreover, based on previous sub- section discount factor from OIS discounting will be used here to price those collateralized contracts. A swap curve is usually consisted of Deposits, FRA and IRS . The basis of this bootstrap- ping method is the assumption that the theoretical price of a bond is equal to the sum of the cash flow discounted at the zero-coupon rate of each flow []Borodovsky.

Deposit I have introduced deposits contracts generally in 1.4.1. In our case, cash deposits include maturities in S/W2, one month, two months and three months. Table 3.3 is 3-months Euribor rates at 2020-04-14. We can begin with calculating the discount factor and zero rate for short-term of the curve.

1 Di = ; i = 1W, 1M, 2M, 3M , (3.14) di { } 1 + qi 360

ln(Di) Zi = 100 ; i = 1W, 1M, 2M, 3M , (3.15) − di { } 365 where Di is discount factors, Zi is zero rates, qi is quoted rates in our case it is Euribor rates or swap rates and di is number of days. Note that day count convention for Euribor is ACT/360 but zero rates are commonly given as continuous compounding, Act/365. In addition, here we don’t need to calculate discount factor for overnight (O/N) and tomorrow next (T/N) since 3-months Euribor doesn’t include them. The table of Euribor rates viewed at 2020-04-14 will show that forward rates started at 2020-04-14 but the measure date was 2020-04-14. This is because 3-months Euribor starts with S/W which is settled in 2 days after the spot.

FRAs The general description of FRAs have been included in section 1.4.2. I will directly go forward to algorithms. There is a so-called stub rate which shall have Maturity the same date as the Start date of the first FRA contract. However we need stub rate only if we have IMM FRA contracts. FRAs within Euribor are not IMM FRA contracts. Thus we neglect stub rate here. Now we can handle the FRA rates as given below [19, p.201]:

2The spot week what means starts on spot (in 2 days) and last a week (7 days).

27 Name Quote Measured date From date To date Days 1Days

EURIBOR S/W -0.518 2020-04-14 2020-04-16 2020-04-23 9 EURIBOR 1M -0.404 2020-04-14 2020-04-16 2020-05-18 34 EURIBOR 2M 0 2020-04-14 2020-04-16 2020-06-16 63 EURIBOR 3M -0.248 2020-04-14 2020-04-16 2020-07-16 93 EUR 1X4 FRA -0.27 2020-04-14 2020-04-16 2020-08-17 125 EUR 2X5 FRA -0.299 2020-04-14 2020-04-16 2020-09-16 155 EUR 3X6 FRA -0.322 2020-04-14 2020-04-16 2020-10-16 185 EUR 4X7 FRA -0.347 2020-04-14 2020-04-16 2020-11-16 216 EUR 1Y IRS 3M -0.347 2020-04-14 2020-04-16 2021-04-16 367 EUR 15M IRS 3M -0.363 2020-04-14 2020-04-16 2021-07-16 458 EUR 18M IRS 3M -0.373 2020-04-14 2020-04-16 2021-10-18 552 EUR 21M IRS 3M -0.377 2020-04-14 2020-04-16 2022-01-17 643 EUR 2Y IRS 3M -0.38 2020-04-14 2020-04-16 2022-04-18 734 EUR 3Y IRS 3M -0.371 2020-04-14 2020-04-16 2023-04-17 1098 EUR 4Y IRS 3M -0.346 2020-04-14 2020-04-16 2024-04-16 1463 EUR 5Y IRS 3M -0.31 2020-04-14 2020-04-16 2025-04-16 1828 EUR 6Y IRS 3M -0.271 2020-04-14 2020-04-16 2026-04-16 2193 EUR 7Y IRS 3M -0.229 2020-04-14 2020-04-16 2027-04-16 2558 EUR 8Y IRS 3M -0.184 2020-04-14 2020-04-16 2028-04-17 2925 EUR 9Y IRS 3M -0.139 2020-04-14 2020-04-16 2029-04-16 3289 EUR 10Y IRS 3M -0.094 2020-04-14 2020-04-16 2030-04-16 3654 EUR 11Y IRS 3M -0.05 2020-04-14 2020-04-16 2031-04-16 4019 EUR 12Y IRS 3M -0.008 2020-04-14 2020-04-16 2032-04-16 4385 EUR 15Y IRS 3M 0.094 2020-04-14 2020-04-16 2035-04-16 5480 EUR 20Y IRS 3M 0.157 2020-04-14 2020-04-16 2040-04-16 7307 EUR 25Y IRS 3M 0.14 2020-04-14 2020-04-16 2045-04-17 9134 EUR 30Y IRS 3M 0.092 2020-04-14 2020-04-16 2050-04-18 10961 EUR 40Y IRS 3M 0.016 2020-04-14 2020-04-16 2060-04-16 14612 EUR 50Y IRS 3M -0.053 2020-04-14 2020-04-16 2070-04-16 18264

Table 3.3: 3-months Euribor rates at 2020-04-14a aSource: Bloomberg at 2020-04-14. 28 i 1 i DFRA− DFRA = i ; i = 1x4 FRA, 2x5 FRA, 3x6 FRA, 4x7 FRA , (3.16) i dFRA { } 1 + qFRA 360

i i where qFRA is quoted FRA rates and dFRA is FRA contracts periods, in this case it is 3 months. Now we can get the zero rate as [19, p.201]:

i i ln(DFRA) ZFRA(T) = 100 i ; i = 1x4 FRA, 2x5 FRA, 3x6 FRA,4x7 FRA . (3.17) − dFRA { } 365 In our case, tenor 1x4FRA means that a forward contract starts in one month from meas- ured date (2020-04-14) and has 3 months contract period. In this sense, tenor 1x4FRA starts at i 1 2020-05-18 and ends up at 2020-08-17. Therefore, according to (3.16), DFRA− should equals to 1.000382. As we see in table 3.3, there is no quoted rate at tenor Euribor 2M, in this situation we have to use linear interpolation method to obtain Euribor 2M discount factor. We can use this case to calculate and show that how linear interpolation works.

D(2020 07 16) D(2020 05 18) D(2020 06 16) = − − − − − (93 63) − − 93 34 · − (3.18) − =1.000509.

Other tenors of FRAs will have same logical algorithm as we just explained above. The completed process of implementation in Python will be showed in AppendixB.

Swaps Euribor is typical standard plain vanilla swaps. Swaps contribute the medium-long term of the yield curve. Since the swaps have no value at the starting date of the contracts. And there is one-to-one relationship between the fixed rates and the floating rates. In some literature researchers recommended to exact the implied value of the [9]. For Euribor with specified tenor, we try to extract a "description" of the additional swap curve/the related Euribor rate which allows us to value arbitrary products linked to those floating payments accordingly [9]. Let’s explain it in a better way. 3M Let L (Tj 1,Tj) denotes Euribor rate for the time period betweem Tj 1 and Tj (in our − − example, the tenor is assumed to be 3 month), which is fixed at Tj 1 and payed at Tj in a swap. As aforementioned the idea would be to iteratively construct− portfolios using the given instruments, which exchange a fixed payment today, PV(0), against a payment of 3M L (Tj 1,Tj)(Tj Tj 1) at Tj. In financial mathematics this can be expressed as [9, p.7]: − − −

3M PV(0) =”Today0s value o f a f uture payment o f L (Tj 1,Tj)(Tj Tj 1)” − − − QT 3M =D(0,Tj)E j [L (Tj 1,Tj)(Tj Tj 1)] (3.19) − − − 3M =D(0,Tj)F (0,Tj 1,Tj)(Tj Tj 1), − − −

29 where QTj denotes the Tj forward measure using risk-neutral valuation. We can use a related 3M forward rate F (0,Tj 1,Tj) presents PV at Tj. In other words, the contract is about a ex- 3M − 3M changing F (0,Tj 1,Tj) against L (Tj 1,Tj) at Tj. In this sense, we can easily find out 3M − − that F (0,Tj 1,Tj) represents floating rate. Those forward rates, respectively the curve of − 3M those forward rates Tj 1 F (0,Tj 1,T j), are the objects we are interested in. − → − As we illustrated early, the net value of the floating leg and the fixed leg should be zero. we conclude with the following set of equations the forwards should satisfy to match market prices [9, p.7]:

ni ni 3M 3M si ∑ (Tj Tj 1)D(0,Tj) = ∑ D(0,Tj)F (0,Tj 1,Tj)(Tj Tj 1), (3.20) j=1 − − j=1 − − −

3M for 1 i n, where ni corresponds to the number of payment dates for the i th swap and si is corresponding≤ ≤ par rate. Note that I use the same assumption again that− floating and fixed leg have equal payment dates for simplicity. Here, this does not make a difference at all. As the previous section mentioned about forward rates, here we can also express forward rate in terms of discount factor [9, p.7]:

3M 3M 1 P (0,Tj 1) − F (0,Tj 1,Tj) = 3M 1 . (3.21) − Tj Tj 1 P (0,Tj) − − −  

This transforms (3.20) to [9, p.8]:

ni ni 3M 3M OIS OIS P (0,Tj 1) si ∑ (Tj Tj 1)P (0,Tj) = ∑ P (0,Tj) M − 1 . (3.22) − − P3 (0,T ) − j=1 j=1  j 

3M 3M Note that here, si is quoted fixed rate for the i th swap ,P (0,Tj) represents discount − 3 OIS factor for Euribor curve which is different with OIS discount factor P (0,Tj) (here we replace D(0,Tj)). Since the two discount curves are different, that is why we call this boot- strapping as dual curve stripping. In our case, to strip a 3 months-Euribor curve we have to mention the frequency of the floating payments is every 3 months. For instance, the tenor "EUR 1Y IRS 3M" what represents 1 year maturity IRS with 3 months as tenor tells us that within one year there are 4 times floating payments or ni equals to 4. They are 2020-07-16, 2020-10-16, 2021-01-18 and 2021-04-16. Discount factor P3M at 2020-07-16 and 2020-10-16 can be obtained via deposit and FRA. Discount factor P3M at 2021-04-16 is what we want. Obviously we can use linear interpolation to get unknown discount factor P3M at 2021-01-18. The right side of (3.22) can be rewritten as:

3The discount factor we obtained in the section 1.1 of Chapter 3.

30 ni 3M ni 3M OIS P (0,Tj 1) P (0,Tj 1) OIS OIS P (0,Tj) − 1 = − P (0,Tj) P (0,Tj) ∑ P3M(0,T ) − ∑ P3M(0,T ) − j=1  j  j=1  j  ni 3M ni P (0,Tj 1) OIS OIS − = ∑ 3M P (0,Tj) ∑ P (0,Tj) j 1 P (0,Tj) − j 1 = = (3.23) ni 1 3M ni − P (0,Tj 1) OIS OIS − = ∑ 3M P (0,Tj) ∑ P (0,Tj) j=1 P (0,Tj) − j=1 3M P (0,Tj 1) OIS − + 3M P (0,Tj). P (0,Tj) According to (3.22) we finally obtain discount factors:

OIS 3M 3M P (0,Tj) P (0,Tj 1) P (0,Tj) = · − , 3M OIS 3M ni OIS ni 1 P (0,Tj 1) OIS P (0,Tj) + s ∑ ∆ jP (0,Tj) ∑ − 3M − 1 P (0,Tj) i · j=1 − j=1 P (0,Tj) −   (3.24) where ∆ j = Tj Tj 1. And the zero rate is calculated as: − − i 3M 365 Z (0,Tj) = 100 lnP (0,Tj) i . (3.25) − · · d (0,Tj) Here I continue use Python to bootstrap 3-months Euribor curve and the detail is included in AppendixB. A new table of 3-months Euribor after bootstrapping is expressed in table 3.4. The bootstrapped discount curve and yield curve are illustrated in Figure 3.3 and Figure 3.4, respectively.

Now let’s look at 6-months Euribor rates, see table 3.5. For example, for FRAs, 1x7 means that the forward contract starts 1 month from now (2020-04-14) and will end up 7 months from now (2020-04-14). And the forward contract will last 6 months long. Furthermore, such as aforementioned here we also have 2020-04-14 as measure date. The algorithm of bootstrapping is same as for 3-months Euribor. The detail will show in AppendixC. All the bootstrapped results are showed in table 3.6. And the bootstrapped discount curve and yield curve are illustrated in Figure 3.5 and Figure 3.6, respectively.

3.2 The Smith–Wilson model

The smoothness possible curve needs an acceptable term structure of interest rates. Moreover, risk-free yield curves are the basic building blocks for the valuation of future financial claims and long-term risk management work. However, measuring and estimating suitable risk-free

31 Name Quote From date To date Days Discount Forward Spot EONIA O/N -0.451 2020-04-14 2020-04-15 1 1.00001252793472-0.450999999999585-0.457266753162583 EUR 1W OIS -0.4583 2020-04-14 2020-04-23 9 1.00012711604027-0.515580936367857-0.515493400291399 EUR 1M OIS -0.4606 2020-04-14 2020-05-18 34 1.00044769541751-0.461427724142001-0.480506645922278 EUR 2M OIS -0.4645 2020-04-14 2020-06-16 63 1.0008258696548-0.469070282961994-0.478282565742515 EUR 3M OIS -0.4696 2020-04-14 2020-07-16 93 1.00122661312711-0.480303020784519-0.48111766658352 EUR 6M OIS -0.4841 2020-04-14 2020-10-16 185 1.00250434353045-0.498732464755508-0.493482542749158 EUR 9M OIS -0.4978 2020-04-14 2021-01-18 279 1.00387971576616-0.52470260606523-0.506579323897994 EUR 1Y OIS -0.5077 2020-04-14 2021-04-16 367 1.00520412748153-0.538999769137221-0.516234598122799 EUR 15M OIS -0.5169 2020-04-14 2021-07-16 458 1.00661600467764-0.554873777331133-0.525521498946875 EUR 18M OIS -0.5217 2020-04-14 2021-10-18 552 1.00805059208214-0.545028649458078-0.530199459381391 EUR 21M OIS -0.5242 2020-04-14 2022-01-17 643 1.00942662282304-0.539280218371716-0.532597411889658 EUR 2Y OIS -0.5232 2020-04-14 2022-04-18 734 1.01074540674105-0.516170255472784-0.531491971317548 EUR 27M OIS -0.5261 2020-04-14 2022-07-18 825 1.0121509384075-0.54935927469716-0.534347097481486 EUR 30M OIS -0.5245 2020-04-14 2022-10-17 916 1.01345767973635-0.51008801250395-0.532674046186954 EUR 2Y 9M OIS -0.5205 2020-04-14 2023-01-16 1007 1.01469016224648-0.480516631238024-0.528590572308455 EUR 3Y OIS -0.5149 2020-04-14 2023-04-17 1098 1.01585441051151-0.453393445413074-0.522902129681962 EUR 3Y 3M OIS -0.5095 2020-04-14 2023-07-17 1189 1.01699804005016-0.444863072114309-0.517421724564593 EUR 3Y 6M OIS -0.5037 2020-04-14 2023-10-16 1280 1.01810094488266-0.428556718139346-0.511543884644207 EUR 3Y 9M OIS -0.4973 2020-04-14 2024-01-16 1372 1.0191663387116-0.409053185504009-0.505066837835035 EUR 4Y OIS -0.4902 2020-04-14 2024-04-16 1463 1.02015692291336-0.384136455512101-0.49788847789851 EUR 4Y 3M OIS -0.4823 2020-04-14 2024-07-16 1554 1.02107708684452-0.356506771656568-0.489908863706539 EUR 4Y 6M OIS -0.4736 2020-04-14 2024-10-16 1646 1.02193394798843-0.328097027948742-0.481127201322867 EUR 4Y 9M OIS -0.4645 2020-04-14 2025-01-16 1738 1.02272673203556-0.303326230567583-0.471944730672365 EUR 5Y OIS -0.4549 2020-04-14 2025-04-16 1828 1.02342110401107-0.27139247873125-0.462260891980387 EUR 5Y 3M OIS -0.4453 2020-04-14 2025-07-16 1919 1.02407979838881-0.254455162191572-0.452578158870841 EUR 5Y 6M OIS -0.4353 2020-04-14 2025-10-16 2011 1.02467918453885-0.228893501572751-0.442493491309696 EUR 5Y 9M OIS -0.4251 2020-04-14 2026-01-16 2103 1.02521491033727-0.204475990398409-0.432207542589984 EUR 6Y OIS -0.4147 2020-04-14 2026-04-16 2193 1.02566162717677-0.174216068015335-0.42172053863055 EUR 6Y 3M OIS -0.4042 2020-04-14 2026-07-16 2284 1.02606053035214-0.153799746629003-0.411132251765344

Table 3.4: The bootstrapped 3-months Euribor curve at 2020-04-14

32 Figure 3.3: The bootstrapped discount curve for 3-months Euribor at 2020-04-14 (Table 3.4)

Figure 3.4: The bootstrapped yield curve for 3-months Euribor at 2020-04-14 (Table 3.4)

33 Name Quote Measured date From date To date EURIBOR 6M -0.195 2020-04-14 2020-04-16 2020-10-16 EUR 1X7 FRA -0.223 2020-04-14 2020-04-16 2020-11-16 EUR 2X8 FRA -0.25 2020-04-14 2020-04-16 2020-12-16 EUR 3X9 FRA -0.269 2020-04-14 2020-04-16 2021-01-18 EUR 4X10 FRA -0.288 2020-04-14 2020-04-16 2021-02-16 EUR 5X11 FRA -0.307 2020-04-14 2020-04-16 2021-03-16 EUR 6X12 FRA -0.316 2020-04-14 2020-04-16 2021-04-16 EUR 7X13 FRA -0.326 2020-04-14 2020-04-16 2021-05-17 EUR 8X14 FRA -0.335 2020-04-14 2020-04-16 2021-06-16 EUR 9X15 FRA -0.337 2020-04-14 2020-04-16 2021-07-16 EUR 10X16 FRA -0.338 2020-04-14 2020-04-16 2021-08-16 EUR 11X17 FRA -0.339 2020-04-14 2020-04-16 2021-09-16 EUR 12X18 FRA -0.336 2020-04-14 2020-04-16 2021-10-18 EUR 2Y IRS -0.294 2020-04-14 2020-04-16 2022-04-18 EUR 3Y IRS -0.287 2020-04-14 2020-04-16 2023-04-17 EUR 4Y IRS -0.262 2020-04-14 2020-04-16 2024-04-16 EUR 5Y IRS -0.227 2020-04-14 2020-04-16 2025-04-16 EUR 6Y IRS -0.191 2020-04-14 2020-04-16 2026-04-16 EUR 7Y IRS -0.154 2020-04-14 2020-04-16 2027-04-16 EUR 8Y IRS -0.114 2020-04-14 2020-04-16 2028-04-17 EUR 9Y IRS -0.075 2020-04-14 2020-04-16 2029-04-16 EUR 10Y IRS -0.036 2020-04-14 2020-04-16 2030-04-16 EUR 11Y IRS 0.003 2020-04-14 2020-04-16 2031-04-16 EUR 12Y IRS 0.04 2020-04-14 2020-04-16 2032-04-16 EUR 13Y IRS 0.075 2020-04-14 2020-04-16 2033-04-18 EUR 14Y IRS 0.105 2020-04-14 2020-04-16 2034-04-17 EUR 15Y IRS 0.13 2020-04-14 2020-04-16 2035-04-16 EUR 16Y IRS 0.15 2020-04-14 2020-04-16 2036-04-16 EUR 17Y IRS 0.164 2020-04-14 2020-04-16 2037-04-16 EUR 18Y IRS 0.174 2020-04-14 2020-04-16 2038-04-16 EUR 19Y IRS 0.18 2020-04-14 2020-04-16 2039-04-18 EUR 20Y IRS 0.182 2020-04-14 2020-04-16 2040-04-16 EUR 21Y IRS 0.181 2020-04-14 2020-04-16 2041-04-16 EUR 22Y IRS 0.178 2020-04-14 2020-04-16 2042-04-16 EUR 23Y IRS 0.172 2020-04-14 2020-04-16 2043-04-16 EUR 24Y IRS 0.165 2020-04-14 2020-04-16 2044-04-18 EUR 25Y IRS 0.156 2020-04-14 2020-04-16 2045-04-17 EUR 26Y IRS 0.146 2020-04-14 2020-04-16 2046-04-16 EUR 27Y IRS 0.135 2020-04-14 2020-04-16 2047-04-16 EUR 28Y IRS 0.124 2020-04-14 2020-04-16 2048-04-16 EUR 29Y IRS 0.113 2020-04-14 2020-04-16 2049-04-16 EUR 30Y IRS 0.102 2020-04-14 2020-04-16 2050-04-18 EUR 40Y IRS 0.02 2020-04-14 2020-04-16 2060-04-16

Table 3.5: The 6-months Euribor rates at 2020-04-14a aSource: Bloomberg at 2020-04-14 34 Name Quote Measured date From date To date TTM Discount Spot Forward EURIBOR 6M -0.195 2020-04-14 2020-04-16 2020-10-16 185 1.00100308851161-0.197807459673595-0.192914438502653 EUR 1X7 FRA -0.223 2020-04-14 2020-04-16 2020-11-16 216 1.00131322080156-0.221764415588068-0.359681286092813 EUR 2X8 FRA -0.25 2020-04-14 2020-04-16 2020-12-16 246 1.00161447736894-0.239353275613068-0.360925175329485 EUR 3X9 FRA -0.269 2020-04-14 2020-04-16 2021-01-18 279 1.00189672477048-0.247902800954785-0.307323348414618 EUR 4X10 FRA -0.288 2020-04-14 2020-04-16 2021-02-16 308 1.00214490264532-0.25391267966221-0.307423485661607 EUR 5X11 FRA -0.307 2020-04-14 2020-04-16 2021-03-16 336 1.00238763867412-0.259062312439148-0.311345798622158 EUR 6X12 FRA -0.316 2020-04-14 2020-04-16 2021-04-16 367 1.00260480538849-0.258724209365126-0.251538395209782 EUR 7X13 FRA -0.326 2020-04-14 2020-04-16 2021-05-17 398 1.00296622057376-0.271625115046424-0.418466692577876 EUR 8X14 FRA -0.335 2020-04-14 2020-04-16 2021-06-16 428 1.00331370060021-0.282126442405014-0.415598861543613 EUR 9X15 FRA -0.337 2020-04-14 2020-04-16 2021-07-16 458 1.00357835969804-0.284665938751935-0.316458514997328 EUR 10X16 FRA -0.338 2020-04-14 2020-04-16 2021-08-16 489 1.00385083560144-0.286882544282976-0.315209808605886 EUR 11X17 FRA -0.339 2020-04-14 2020-04-16 2021-09-16 520 1.00412745684769-0.289119466584625-0.319917132128946 EUR 12X18 FRA -0.336 2020-04-14 2020-04-16 2021-10-18 552 1.00433896399966-0.286285490992975-0.236917569164435 EUR 2Y IRS -0.294 2020-04-14 2020-04-16 2022-04-18 734 1.00601249790032-0.298091370653472-0.329050269592174 EUR 3Y IRS -0.287 2020-04-14 2020-04-16 2023-04-17 1098 1.00879732947157-0.291164237503167-0.273021046551776 EUR 4Y IRS -0.262 2020-04-14 2020-04-16 2024-04-16 1463 1.01071972914625-0.266020387446044-0.187595569561137 EUR 5Y IRS -0.227 2020-04-14 2020-04-16 2025-04-16 1828 1.01162517154884-0.230782998911114-0.0882776651994013 EUR 6Y IRS -0.191 2020-04-14 2020-04-16 2026-04-16 2193 1.01175549531393-0.194515810867922-0.0127045030770779 EUR 7Y IRS -0.154 2020-04-14 2020-04-16 2027-04-16 2558 1.01107898122083-0.1572162426310490.0659935365240105 EUR 8Y IRS -0.114 2020-04-14 2020-04-16 2028-04-17 2925 1.00940900363295-0.1168625762388840.162285569915472 EUR 9Y IRS -0.075 2020-04-14 2020-04-16 2029-04-16 3289 1.00700433052858-0.07746028171982880.236170595607309 EUR 10Y IRS -0.036 2020-04-14 2020-04-16 2030-04-16 3654 1.00381075278975-0.03799346597653820.313787244240596 EUR 11Y IRS 0.003 2020-04-14 2020-04-16 2031-04-16 4019 0.9998274029739810.00156763751552450.392946159332577 EUR 12Y IRS 0.04 2020-04-14 2020-04-16 2032-04-16 4385 0.9953037016420330.03918327535968410.447053727056233 EUR 13Y IRS 0.075 2020-04-14 2020-04-16 2033-04-18 4752 0.9903046668359190.0748329799073850.495169368843121 EUR 14Y IRS 0.105 2020-04-14 2020-04-16 2034-04-17 5116 0.9853278643536480.1054535796277690.499540561387851 EUR 15Y IRS 0.13 2020-04-14 2020-04-16 2035-04-16 5480 0.9805128973319220.1310768258069720.485669827410818 EUR 16Y IRS 0.15 2020-04-14 2020-04-16 2036-04-16 5846 0.9760076846200170.1516243404053160.454028880677632 EUR 17Y IRS 0.164 2020-04-14 2020-04-16 2037-04-16 6211 0.972140893938070.1660425749721820.392311543559092 EUR 18Y IRS 0.174 2020-04-14 2020-04-16 2038-04-16 6576 0.9687254201848340.1763615578216120.347744197824889 EUR 19Y IRS 0.18 2020-04-14 2020-04-16 2039-04-18 6943 0.9658758637317850.1825260671970130.289395909454503 EUR 20Y IRS 0.182 2020-04-14 2020-04-16 2040-04-16 7307 0.9637236215620030.1845766342182320.220871535085679 EUR 21Y IRS 0.181 2020-04-14 2020-04-16 2041-04-16 7672 0.9621571980252260.1835344560310770.160573104195498 EUR 22Y IRS 0.178 2020-04-14 2020-04-16 2042-04-16 8037 0.961050570189530.1804256670361220.113570355622386 EUR 23Y IRS 0.172 2020-04-14 2020-04-16 2043-04-16 8402 0.960680548580080.1742605264202250.0379889882041282 EUR 24Y IRS 0.165 2020-04-14 2020-04-16 2044-04-18 8770 0.9606503313015350.1670792512287680.00307712184356947 EUR 25Y IRS 0.156 2020-04-14 2020-04-16 2045-04-17 9134 0.9612670360272280.157856448105703-0.0634503970099016 EUR 26Y IRS 0.146 2020-04-14 2020-04-16 2046-04-16 9498 0.9623148856859350.14762001079435-0.107691862893115 EUR 27Y IRS 0.135 2020-04-14 2020-04-16 2047-04-16 9863 0.9638208038799720.136370371650788-0.154104286990026 EUR 28Y IRS 0.124 2020-04-14 2020-04-16 2048-04-16 10229 0.965521714554710.125199342213054-0.173276982585149 EUR 29Y IRS 0.113 2020-04-14 2020-04-16 2049-04-16 10594 0.9674375386394780.114056180228678-0.195318027650655 EUR 30Y IRS 0.102 2020-04-14 2020-04-16 2050-04-18 10961 0.9695601547841670.102939120836734-0.214749984092792 EUR 40Y IRS 0.02 2020-04-14 2020-04-16 2060-04-16 14612 0.991623168285030.021013015395495-0.219385961424398

Table 3.6: The bootstrapped 6-months Euribor curve at 2020-04-14

35 Figure 3.5: The bootstrapped discount curve for 6-months Euribor at 2020-04-14 (Table 3.6)

Figure 3.6: The bootstrapped yield curve for 6-months Euribor at 2020-04-14 (Table 3.6)

36 interest rates face challenges. In nowaday’s highly developed markets, or in other words, when financial instruments are traded in deep, liquid and transparent (DLT) markets, it is possible to observe bonds or IRS contracts with maturities of up to 50 years. In less developed markets, liquidity becomes major encumbrance. The techniques of determining yields and thereby discount factors for unavailable maturities has been long under discussion in the past years. The fair evaluation of assets and long-term liabilities had become emphasis among the international insurance community. In addition, the evaluations of both assets and long-term liabilities are directly connecting to the discount factor. To estimate discount factors for unavailable maturities requires extrapolation method. However, different approaches to extrapolating the yield curve can give significantly differ- ent results. Furthermore, there is no obvious prove for which approaches are best. The framework of the Solvency II4 for determination of the term structure of the basic risk- free interest rate has changed over time. The first term structure method is called "Bootstrap" (we discussed in the previous section) which was applied to determine the risk-free interest rate structure for the Committee of European Insurance and Occupational Pensions Supervisors’ (CEIOPS) the fourth Quantitative Impact Study (QIS4) in 2008. However, it didn’t meet the requests from Solvency II for term structure. Thus, a different term structure method, the Smith-Wilson method, had been proposed by the European Authority under CEIOPS’ the fifth Quantitative Impact Study (QIS5) in 2010 [15]. Actually the European Authority was looking for a method which can perfectly fit all DLT markets interest rate while also keep moving smoothly between market points. In other words, the chosen method for fitting the yield curve beyond the current investable universe should include at least three important considerations, namely market consistency at a point in time, liability stability across time and the smoothness of the extrapolated curve []Akinyemi. In general, there are two philosophical approaches for extrapolation of yield curve. One is to emphasize market consistency at a point in time whereas another is to emphasize liability stability across time. To emphasize market consistency means to produce a liability value that is equivalent to the value that would be required to transfer that liability in current market conditions. On the other hand, people who choose the approach with emphasis on liability stability believe that the volatility introduced by requiring market consistent prices at a point in time is not equivalent to the volatility in the future. In this sense, an approach that emphasizes liability stability may underestimate the true economic cost of writing long-term insurance contract. This would lose future interests from the firm’s, policyholders’ or shareholders’ if long-term contracts were issued too cheaply. Furthermore, it maybe be harder to hedge balance sheet risk over the longer term through an artificially stabilized liability valuation. On the other hand, emphasizing market price consistency may add to pro-cyclicality. Hence, the European Authority proposed the Solvency II liability evaluation which is considered as a fair value approach due to it seeks to capture changes in asset and liability values over time [8]. The extrapolation approach what is used for the non-liquid sector is based on forward rate. This is because the forward rate better explains long term market expectations. Dybvig, Ingersoll and Ross [20]illustrated that within any risk-free interest rate model, the long-term

4The Solvency II regime introduces for the first time a harmonised, sound and robust prudential framework for insurance firms in the EU [5].

37 forward rates should converge towards a limiting ’long rate’ assumption which is constant over time. Therefore, Smith and Wilson [][2000 cited][]Smith had issued a model for bond prices which consists linear combinations of exponential spline based optimization functions5 with long-term yield constraints in order to obtain a smooth term structure of interest rates. One of these long-term yield constraints is called as the Ultimate Long-Term Forward Rate (UFR) which is same as a limiting ’long-rate’ as the Dybvig and his partners interpreted. Comparing with linear extrapolation, SW is more sophisticated technique. Next we will discuss the application of SW technique for bonds and swap rates.

3.2.1 Smith-Wilson technique for zero coupon bond prices as input We assume that in the liquid part of the term structure, there are a fixed number of N maturities: u1, u2, u3, up to uN which are known. And the risk-free zero coupon rates for these N liquid maturities are given. Then for continuously compounded rates, the input zero bond prices at maturities u j can be expressed as [17, p.5]:

( ui R˜u ) mi = P(ui) = e − · i , (3.26) ˜ where Rui represents continuously compounded rates. and

ui mi = P(ui) = (1 + Rui )− , (3.27) for annual compounding where Rui denotes annually compounded rates. According to SW technique proposed by Smith and Wilson the pricing function is expressed as [17, p.5]:

N UFR t P(t) = e− · + ∑ ζ j W(t,u j), t 0, (3.28) j=1 · ≥ where W(t,u j) is called the symmetric Wilson functions and is defined as [17, p.6]:

UFR(t+u j) α max(t,u j) α min(t,u j) α min(t,u j) W(t,u j) = e− α min(t,u j) 0.5 e− · (e · e− · ) . · · − · · −  (3.29 ) In this function,

1. N, the number of zero coupon bonds with known price function,

2. mi, i = 1,2,...N, the market prices of zero coupon bonds,

3. u j, j = 1,2,...N, the maturities of the zero coupon bonds with known prices, 4. t, the term to maturity in the price function,

5"Spline functions are regularly used in engineering to create a smooth curve between discrete points that usually represent empirical data" [15, p.12].

38 5. UFR, the ultimate unconditional forward rate, continuously compounded,

6. α, mean reversion, a measure for the speed of convergence to the UFR,

7. ζ j, j = 1,2,...N represents a series of time-varying parameters used to fit the actual yield curve.

The kernel functions, Kj(t), equals to:

Kj(t) = W(t,u j), t > 0 and j = 1, 2, ... ,N. (3.30) Every input bond has its own kernel function. This aims to evaluate the function P(t) as the linear combination of all the kernel functions. In addition, ζ j, j = 1,2,...N are given as solutions of the following linear system of equations [17, p.6]:

N UFR u1 m1 = P(u1) = e− · + ∑ ζ j W(u1,u j) j=1 · N UFR u2 ,m2 = P(u2) = e− · + ∑ ζ j W(u2,u j) j=1 · (3.31) . ,. N UFR uN mN = P(uN) = e− · + ∑ ζ j W(uN,u j). j=1 ·

In vector space notation this becomes:

m = p = µ +Wζ, (3.32) with:

T m = (m1,m2,...... ,mN) , T p = (P(u1),P(u2),...... ,P(uN)) , (3.33) UFR u1 UFR u2 UFR uN T µ = (e− · ,e− · ,...... ,e− · ) , T ζ = (ζ1.ζ2,...... ,ζN) , where the superscript T denotes the transposed vector and [17, p.7]

W = (W(ui,u j))i=1,2,...,N; j=1,2,...,N is a NxN-matrix of certain Wilson functions. (3.34) T The solution ζ = (ζ1,ζ2,...,ζN) is the product of inverted NxN-matrix W and the differ- ence between the p-vector and the µ-vector (i.e. the difference between the market prices of the zero coupon bonds and the asymptotical term), that is:

39 1 1 ζ = W − (p µ) = W − (m µ). (3.35) − − After we get ζ-vector, we can substitute this vector with other known parameters in the pricing function to get the value of the zero coupon bond price for all maturities t. At last, we also obtain spot rates by [17, p.7]: 1 1 R˜t = ln f or continuously compounded rates, (3.36) t · P(t)

1 1 Rt = ( ) t 1 f or annually compounded rates. (3.37) P(t) −

3.2.2 Smith-Wilson technique for a set of general inputs Now we assume N interest related financial instruments as input from the liquid part of the term structure and that J is the number of cash payment dates. Then we have the pricing function as [17, p.7]:

N J UFR t P(t) = e− · + ∑ ζi ( ∑ ci, j W(t,u j)),,t 0, (3.38) i=1 · j=1 · ≥ where [17, p.8]

J Ki(t) = ∑ ci, j W(t,u j),t > 0,i, j = 1, 2, 3, ... N, (3.39) j=1 · is called the kernel functions which is appropriately defined functions of input market data and two input parameters. In this function, 1. N, the number of the interest related instruments with known price function,

2. ci, j represents the jth cash flow on the ith instrument used to calibrate the price function (if no cash payment is due at time t = u j on instrument i, then ci, j is set to zero),

3. u j, j = 1,2,...N represents all cash payment dates for the instruments, 4. t, the term to maturity in the price function,

5. UFR, the ultimate unconditional forward rate, continuously compounded,

6. ζi, i = 1,2,...N represents a series of time-varying parameters used to fit the actual yield curve.

W(t,u j) is called as the symmetric Wilson function which is same as expressed in eq. (3.29). The term structure within SW technique can be fitted to all the different financial instru- ments which may be eligible as basis for assessing the risk-free interest rate curve [17]. Those input instruments are defined by [17, p.10]

40 1. the vector of the market prices (of N instruments) at valuation date,

2. the vector of the cash payment dates (J different dates) up to the last maturity, and

3. the NxJ-matrix of the cash flows on the instruments in these dates.

Furthermore, for an instrument i, all cash payment dates u1,u2,...,uJ, their cash flows ci,1,ci,2,...,ci,J and the discount factors P(u j), j = 1,2,...,J are known. Thus sum of all cash flows’ present values will be [17, p.8]:

J mi = ∑ ci, j P(u j), i = 1, 2, 3, ... N. (3.40) j=1 · Then regarding to eq. (3.38), we obtain:

J J N J UFR u j m1 = ∑ c1, j P(u j) = ∑ c1, j (e− · + ∑ ζl ∑ cl,k W(u j,uk)), j=1 · j=1 · l=1 · k=1 · J J N J UFR u j m2 = ∑ c2, j P(u j) = ∑ c2, j (e− · + ∑ ζl ∑ cl,k W(u j,uk)), j=1 · j=1 · l=1 · k=1 · (3.41) . . J J N J UFR u j mN = ∑ cN, j P(u j) = ∑ cN, j (e− · + ∑ ζl ∑ cl,k W(u j,uk)). j=1 · j=1 · l=1 · k=1 ·

After rearranging, the equations above are expressed as:

J J N J J UFR u j ∑ c1, j P(u j) = ∑ c1, j e− · + ∑( ∑ ( ∑ c1, j W(u j,uk)) cl,k) ζl, j=1 · j=1 · l=1 k=1 j=1 · · · J J N J J UFR u j ∑ c2, j P(u j) = ∑ c2, j e− · + ∑( ∑ ( ∑ c2, j W(u j,uk)) cl,k) ζl, j=1 · j=1 · l=1 k=1 j=1 · · · (3.42) . . J J N J J UFR u j ∑ cN, j P(u j) = ∑ cN, j e− · + ∑( ∑ ( ∑ cN, j W(u j,uk)) cl,k) ζl. j=1 · j=1 · l=1 k=1 j=1 · · ·

Rewriting the expressions above in vector space notation, then we have [17, p.9]:

m = Cp = Cµ + (CWCT )ζ, (3.43) with:

41 T m = (m1,m2,...... ,mN) , T p = (P(u1),P(u2),...... ,P(uJ)) ,

c1 1 c1 2 c1 j c1 J , , ··· , ··· , c2,1 c2,2 c2, j c2,J C =  . . ···. . ···.  the NxJ cash f low matrix, (3.44) ......  ···  cN,1 cN,2 cN, j cN,J  ··· ···  UFR u1 UFR u2 UFR uJ T  µ = (e− · ,e− · ,...... ,e− · ) , T ζ = (ζ1.ζ2,...... ,ζN) , and

wu u wu u wu u wu u 1, 1 1, 2 ··· 1, i ··· 1, J wu2,u1 wu2,u2 wu2,ui wu2,uJ  . . ···. . ···.  ...... W = the JxJ matrix o f certain Wilson f unctions. w w w w···   ui,u1 ui,u2 ui,ui ui,uJ   ···. ···.   .. ..    w······w w··· w···   uJ,u1 uJ,u2 uJ,ui uJ,uJ   ··· ···  (3.45) According to eq. (3.43) we can reach the solution of ζ-vector by inverting the NxN- matrix CWCT and multiplying it with the difference of the market value vector and the vector assessed as product of matrix C with the µ-vector, the asymptotical term [17, p.10]:

T 1 ζ = (CWC )− (m Cµ). (3.46) − Finally we can plug this ζ-vector with other input parameters into the pricing function P(t) in order to get the value of the discount function for all maturities, and thus the term structure for the spot rates. We also generate the overview of how the SW-technique is applied when the term structure is fitted to zero coupon bond rates, coupon bond rates and par swap rates, see table 3.7[7, p.49]:

3.2.3 Important parameters Theoretically the SW technique can be applied to any kind of financial instruments to determ- ine the term structure. But the most appropriate instruments are those that achieve the lowest observed credit risk. This means that those instruments are traded in DLT markets. In the first three Quantitative Impact Studies, the government bonds was considered to be the sole instruments that could meet the requirement of the highest credit quality. From the QIS4 on, IRS contracts were introduced as instruments that meet the credit quality request. This trans- ition from government bonds to swaps was directly caused by the financial crisis. Under the financial crisis, credit quality of swaps is much higher and stable than the credit quality of

42 Table 3.7: Application of Smith–Wilson method for different input instruments

43 government bonds. Thus, IRS contracts become the European Insurance and Occupational Pensions Authority’s (EIOPA) favored financial instruments, but only when traded in DLT markets [15]. So later let’s still take Eonia, Euribor as market input data to see how the spot rate curve is fitted to zero coupon bond rates, to coupon bond rates and to par swap rates.

Credit risk adjustment

In addition, when selecting swap rates to fit the risk-free term structure, an adjustment to allow for the credit risk in swaps has to be made. This adjustment is called as the Credit Risk Adjust- ment (CRA)6. CRA will make the final interest rates smaller or equal to the ones calculated with observable market prices in order to eliminate the inborn credit risk in swap contracts and government bonds. Furthermore, according to Article 45 of the Delegated Regulation (UE) 2015/35, "the adjustment shall be determined on the basis of the difference between rates cap- turing the credit risk reflected in the floating rate of interest rate swaps and rates of the same maturity, where both rates are available from deep, liquid and transpar- ent financial markets. The calculation of the adjustment shall be based on 50 percent of the average of that difference over a time period of one year. The adjustment shall not be lower than 10 basis points and not higher than 35 basis points" [4, p.41]. If we express CRA as a delta credit risk spread7 of ∆cr basis points of swaps above basic risk-free rates. And choose one of two following adjustment [17, p.10]:

1. "Adjust the continuously compounded spot rates with ∆cr basis points. This means that ∆cr basis points are subtracted from the continuously compounded spot rates, which were assessed with the SW technique from the unadjusted swaps. This is equivalent to multiplying the discount factors P(t) (assessed from unadjusted swaps), with an adjust- (∆cr/10000) t ment factor e · .

2. Adjust the input data with ∆cr basis points. This means that ∆cr basis points are sub- tracted from the raw par swap rates. These adjusted rates are then used to assess the spot rates with the SW technique".

In our case, we will select the first adjustment. And ∆cr will be

∑N (r3M r3M ) ∆cr = CRA = i=1 Euribor − OIS , (3.47) EURO 2N where N is the total number of observed instruments in the past year on daily data. It might need interpolation method when there are missing data. But if the missing data is beyond 20%, the market will no longer met the DLT requirement.

6"By definition, the CRA is a non-positive parallel shift to the observed market rates and its value depends on the financial instruments used to construct the curve" [15, p.19] 7In accordance with the Delegated Regulation (EU) 2015/35, in our case, the credit risk spread is based on the difference between rates capturing the credit risk reflected in the floating rate of IRSs and OIS rates of the same maturity [4].

44 The ultimate unconditional forward rate UFR

Before we go into implementation with market data, we have to determine two important input parameters. Let’s look at the constant long term forward rate, the UFR firstly. By definition, "the UFR is the sum of an expected real rate and an expected inflation rate" [6, p.1]. The UFR’s properties, the exogeneity and constancy, have exposed the most weakness of the SW technique since they betray the very first principle on which Solvency II is based: market consistency. In fact, in present financial market, there is no financial instrument which can provide an interest rate in any way related to the UFR. This leads to produce a significantly unrealistic increase in the extrapolated part of the term structure of interest rates. In this sense, the interest rates what we get from the regulator beyond the last liquid point 8 (LLP) lacks a connection to available market instruments and damages market seriously. This indeed weaken the sensitivity to swap rates of the capital requirement of solvency. Thus, the UFR actually initiates a substantial degree of uncertainty. In addition, the subjectivity of the UFR caused by political pressure makes it go farther away from objectivity observed from financial instruments available on the market. This changing of asymptotic forward rate caused by arbitrary introduces indeed regulatory risks which is impossible for insurance company to hedge. To avoid manipulation and to compute a structure that better reflects the behavior of the market, a lower asymptotic rate could be fixed. In other words, a lower discount curve that may lead to higher long term liabilities. However, there are other voices which argue that the cut UFR has prompted assumptions about long-term inflation and would force insurers to buy more long-dated assets, forcing down rates at the long end and setting in motion a pro-cyclical feedback loop of lowering rates and lowering UFR resets [8]. The UFR is defined to be determined under macroeconomic assumptions around the fu- ture development of short-term real rates and expected inflation rates [15]. Due to that the motion of present short rates doesn’t affect the asymptotic level. Therefore the UFR should be stable and consistency. Moreover, in accordance with studies over decades, there are four macroeconomic variables have a substantial effect on the UFR’s value [8, p.11]:

1. "Expected future inflation,

2. Expected real short-term rate, which is the expected nominal short-term rate minus the expected future inflation,

3. Term premia are the additional return an investor may expect as compensation for the longer-term investment and is the difference between the forward rate and the expec- ted future short-term interest rate. The term premium acts as compensation for holding long- term bonds, whose value will fluctuate in the face of interest rate uncertainty, exposing the holder to mark to market losses. Term premia have the following compon- ents:

8The LLP is nothing less than the last observable market price of the selected financial instrument on DLT market [15].

45 (a) Risk premia—investors demand a premium for locking in long-term investments. This acts as compensation for holding long-term bonds, whose value will fluctuate in the face of interest rate uncertainty, exposing the holder to mark to market losses, (b) Term preference—demand for long-term government securities from large insti- tutional investors can drive down long-term forward rates because the long- term bonds offer a closer match to liabilities and are less risky investments to these investors,

4. Convexity effects—fixed-income investments have positive convexity, which can cause longer-term bonds to trade at higher values (lower yields). Convexity adjustment arises because of the nonlinear (convex) relationship between interest rates and bond prices".

The change of one-year forward rate mostly is affected by the change of the expected short rate. For the 10-year forward rate, the change of it mostly is influenced by the term premium. This is due to short-term interest rates are expected to mean revert over time. Or we can say that expectations of future short-term interest rates are relatively determined by at least 10 years’ duration. Plus that the term premium turns up to show little mean reversion. As an independent advisory body to the European Commission, to the European Parlia- ment and to the Council of the European Union, EIOPA has the aim to enhance supervisory convergence, strengthen consumer protection and preserve financial stability for the benefit of economies, business and EU citizens [1]. Additionally, EIOPA is also responsible for calcu- lation and publication of the UFR. Every year, EIOPA analyses and publishes the UFR and its calculation. If they find substantially difference from the previous UFR, they will provide updates. According to EIOPA’s publication of the UFR for 2020, the applicable UFR in 2020 is 3.75% and will be applicable for the calculation of the risk-free interest rates of 1 January 2020 [6]. Here we are not going to discuss the calculating method of the UFR which EIOPA adopts. Instead we will directly use the UFR for 2020 in our implementation later.

α a measure of the speed of convergence to the UFR The other important input parameter what has to be determined is the α (the speed of conver- gence to the UFR). This parameter is based on judgment and historical data, and it could be defined by a simple method. In order to obtain α we have to decide the convergence period which is defined as "a period of time must pass up until the interest rate reaches its long term equilibrium" [15, p.34]. Usually the convergence period is linear from around 15 years through to year 50 [8]. Different currency has different convergence period. For the euro, in accordance with the political agreement of the Omnibus II Directive, a convergence period of 40 years and a LLP of 20 years have been designed [7]. This is equivalent to assuming that the forward rate will be close to its ultimate level from 20+40 = 60 years maturity on wards. For currency except the euro, the convergence point is the maximum of (LLP+40 years) and 60 years meanwhile the convergence period is the maximum of (60-LLP) and 40 years [7]. Moreover, the α decides the smoothness of the curve. A higher α leads to the bigger the weight of the UFR (hence faster convergence), whereas a lower α gives more weight to the market data.

46 In fact, the α is the parameter which regulates the convergence speed and "is set at the lowest value that produces a term structure reaching the convergence tolerance of the UFR by the convergence point. The convergence tolerance is set at 1 bp (0.01%). A lower bound for α is set at 0.05. The convergence criterion is assessed by EIOPA with a scanning procedure with six decimals precision for α. The method for deriving α is illustrated in the Excel tool “Smith-Wilson Risk-free Interest Rate Extrapolation” that can be found on EIOPA’s website" [7, p.40]. In EIOPA’s technical document EIOPA-BoS-20/109 at 20 Aug. 2020, it rewrites SW present value function (or the discount pricing function) as [7, p.44]:

ωu ωu ωu p(u) = e− +W(u,ν)Cb = e− + e− H(u,ν)Qb, (3.48) where 1. ν represents the observed duration to maturity of the present value function. In other words, it corresponds to the duration of the cash-flows to maturity of the present value function, 2. u corresponds to the duration to maturity of the financial instruments,

3. W(u,ν) is Wilson function, 4. ω denotes the ultimate forward intensity and takes the value of log(1 +URF), 5. H(u,ν) is the heart of the Wilson function,

6. Q is an auxiliary matrix Q = d∆C, the subscript ∆ denotes transforming a column vector into a diagonal matrix such that d∆1 = d (See eq. (3.63) and eq. (3.64)), 7. C is an matrix of the cash flows, 8. b is the other auxiliary matrix. Different with eq. (3.29), here Wilson function is rewritten as consisting of H-function [7, p.41]:

ω(u+ν) ωu ων W(u,ν) = e− H(u,ν) = e− H(u,ν)e− . (3.49) And we obtain the heart of the Wilson function through [7, p.41]:

H(u,ν) =α min(u,ν) exp( α max(u,ν)) sinh(α min(u,ν)) − − · e α(u+ν) e α u ν =α min(u,ν) + − − − | − | 2 (3.50) α(u + ν) + e α(u+ν) α u ν e α u µ = − − | − | − − | − | . 2 Derive the heart function with respect to ν and these two derivatives happen to be continu- ous at ν = u [7, p.42]:

47 dH(u,ν) α αe αu cosh(αν), ν u = G(u,ν) = − − ≤ (3.51) dν αe αν sinh(αu), u ν  − ≤ From the SW present value function eq. (3.48) the SW yield intensity function follows as [7, p.45]:

log p(u) log(1 + H(u,ν)Qb) y(u) = − = ω . (3.52) u − u And the forward intensity function follows as:

d log p(u) d log(1 + H(u,ν)Qb) G(u,ν)Qb f (u) = − = ω = ω , (3.53) du − du − 1 + H(u,ν)Qb where the components of the row vector G(ν,u) follow from the differentiation of H-function with respect to ν. When ν min(u) [7, p.45] ≤ G0 (ν,u) = G(u,ν) = α1 α cosh(αν)exp[ αu]. (3.54) − − For ν 0 the following is obtained [7, p.45]: ↓ H0 (0,u) = H(u,0) = 0 G(u,0) = α1 α exp[ αu]. (3.55) − − From this the zero spot intensity follows from the yield intensity function eq. (3.52)[7, p.45]:

y(0) = f (0) = ω α10 Qb + α exp[ αu0 ]Qb. (3.56) − − When ν U = max(u) (U denotes LLP) implies [7, p.45]: ≥ αν H(u,ν) = αu e− sinhh[αu], (3.57) − · and

αν G(u,ν) = αe− sinh[αu]. (3.58) · Then the upper end of the forward intensity function reduces to[7, p.45]: α f (u) = ω + , ν U, (3.59) 1 κ eαu ≥ − · where κ is a quasi-constant that depends on α (and ω) but not on ν [7, p.46]:

1 + αu0 Qb κ = , (3.60) sinh[αu0 ]Qb where u0 is transpose of u-vector. In vector space notation, d-vector and sinh[αu]-vector will displayed as [7, p.42]:

48 ωu1 e− ωu2 e− d = exp[ ωu] =  . , (3.61) − .  ωum  e−    and  

αu1 αu1 e e− αu2 − αu2 1 e e− sinh[αu] =  −. , (3.62) 2 .  αum αum  e e−   −  where m is the number of different dates at which a cash payment has to be made. And ωu1 e− 0 0 ωu2 ··· 0 e− 0 d∆ =  . . ···. . . (3.63) . . .. .  ωum   0 0 e−   ···  Then  

ωu1 e− 0 0 c11 c12 c1n ωu2 ··· ··· 0 e− 0 c21 c22 c2n Q = d∆C =  . . ···. .  . . ···. . , (3.64) ......  ωum    0 0 e− cm1 cm2 cmn  ···  ···  where n is the number of financial instruments.   Now we can rearrange eq. (3.48) as the following [7, p.44]:

p(u) = exp( ωu) +WCb = d +WCb = d + d Hd Cb = d + d HQb. (3.65) − ∆ ∆ ∆ Let discount factor vector p(u) multiplies with the transpose of cash-flow matrix C, it will give n linear equations in b [7, p.44]:

C0 p(u) = C0 d +C0WCb = q + Q0 HQb. (3.66) Let P be the market observable counterpart, then we have [7, p.44]:

p = q + Q0 HQb, (3.67) where q-vector is expressed as [7, p.43]:

q1 q2 q =  .  = Q0 1 = C0 d. (3.68) .   qN    

49 Hence, we obtain the solution of b [7, p.44]:

1 b = (Q0 HQ)− (p q). (3.69) − In accordance with eq. (3.59), when κ = 0 then f (u) = ω + α. If we avoid the value of ν and f (∞) will not approach ω. Moreover, the value of α is depended on requests on the convergence speed and will inevitably be selected in such a way that κ = 0. The concept, the convergence gap, what is at the point of convergence6 T and can be ana- lysed as a function of α [7, p.46]: α g(α) = f (T) ω = . (3.70) | − | 1 κeαT − Hence, the problem of determining α can be formulated as a nonlinear minimization prob- lem. In order to close to market consistency we have to lower α as much as possible. However, α has its lower bound. To get a suitable α we can consider to construct an convex optimization problem. The objective function is [7, p.46]: Minimize α Subjects to two constraints: 1." α a with the lower bound a = 0.05, ≥ 2. g(α) τ". ≤ where τ denotes the convergence tolerance which equals to 1bp. Solve this optimal problem, we can obtain the optimal solution, g(α) τ, when α is at the optimal point, namely α = a. Otherwise, g(α) = τ when α > a. We can≤ absolutely use this issue to test the appropriateness of α. Since the rewritten of the second inequality constraint, namely α τ 1 κeαT , "might favour a false root for α approaching the value 0" [7, p.46]. Therefore≤ | we− need the| lower boundary to α. Notes that T here is the convergence point. If we denote the convergence period equals to S = max(40,60 U) = max(40,60 LLP), then the convergence point equals to T = U + S = max(U + 40,60−) = max(LLP + 40,−60) [7, p.46].

Implementation of Smith-Wilson technique In our case, according to aforementioned we have the UFR which equals to 3.75%. Then we can calculate the ultimate forward intensity ω = log(1.0375) = 0.0368139731227164. For the euro, the convergence period is 40 year, namely S = 40. For Eonia rates we can adopt SW technique for zero coupon bonds as approach.The calculation details is showed in Appendix D. The results gotten from SW technique is illustrated as Table 3.8. The yield curves and discount factors for Eonia by Smith-Wilson at 2020-04-14 are displayed as Figure 3.7 and Figure 3.8, respectively.

α is always a skill part which requires years of experiences. When we come to both 3- months and 6-months Euribor, we met inappropriate α. This means that the initial value of α is not applicable in these cases. We chose a value of α which is adopted by [7].

50 Name Quote From date To date Days TTM Spot Discount Forward EONIA O/N -0,451 2020-04-14 2020-04-15 1 0.00273972602739726-0.3630091571088951.00001008363854-0.363007326899152 EUR 1W OIS -0,4583 2020-04-14 2020-04-23 9 0.0246575342465753-0.367642259668111.00009191478882-0.368206332676363 EUR 1M OIS -0,4606 2020-04-14 2020-05-18 34 0.0931506849315069-0.369095011177461.00034865049724-0.369570569158896 EUR 2M OIS -0,4645 2020-04-14 2020-06-16 63 0.172602739726027-0.3715507488080241.00065042524524-0.374373426620149 EUR 3M OIS -0,4696 2020-04-14 2020-07-16 93 0.254794520547945-0.3747476808787021.0009685669339-0.381400614369367 EUR 6M OIS -0,4841 2020-04-14 2020-10-16 185 0.506849315068493-0.3837484263882341.00197398627523-0.392649874190255 EUR 9M OIS -0,4978 2020-04-14 2021-01-18 279 0.764383561643836-0.3921335040123791.00304365720342-0.408418121782857 EUR 1Y OIS -0,5077 2020-04-14 2021-04-16 367 1.00547945205479-0.3981216918758721.00406687686047-0.416894401505844 EUR 15M OIS -0,5169 2020-04-14 2021-07-16 458 1.25479452054794-0.4036335787486591.00514832339113-0.425633701202068 EUR 18M OIS -0,5217 2020-04-14 2021-10-18 552 1.51232876712329-0.4064892784019751.00625230014073-0.420172561263552 EUR 21M OIS -0,5242 2020-04-14 2022-01-17 643 1.76164383561644-0.4079712020232381.00731343243806-0.416740795488046 EUR 2Y OIS -0,5232 2020-04-14 2022-04-18 734 2.01095890410959-0.4073788771078821.00834059320453-0.402988153949934 EUR 27M OIS -0,5261 2020-04-14 2022-07-18 825 2.26027397260274-0.4090949887967991.00941917733796-0.422711034022157 EUR 30M OIS -0,5245 2020-04-14 2022-10-17 916 2.50958904109589-0.408148784013961.01043923156824-0.399368833522273 EUR 2Y 9M OIS -0,5205 2020-04-14 2023-01-16 1007 2.75890410958904-0.4057766380184111.01141513533749-0.381714498144996 EUR 3Y OIS -0,5149 2020-04-14 2023-04-17 1098 3.00821917808219-0.402439652350161.01235004912053-0.365343985909405 EUR 3Y 3M OIS -0,5095 2020-04-14 2023-07-17 1189 3.25753424657534-0.399204098337531.013272127313-0.360000217316615 EUR 3Y 6M OIS -0,5037 2020-04-14 2023-10-16 1280 3.50684931506849-0.3957093571540981.01416910961528-0.349892476703229 EUR 3Y 9M OIS -0,4973 2020-04-14 2024-01-16 1372 3.75890410958904-0.3918294947219861.01504511259246-0.337702994109398 EUR 4Y OIS -0,4902 2020-04-14 2024-04-16 1463 4.00821917808219-0.3874961188529641.01587205562032-0.322031002748131 EUR 4Y 3M OIS -0,4823 2020-04-14 2024-07-16 1554 4.25753424657534-0.3826381745763861.01665437786868-0.304420191336318 EUR 4Y 6M OIS -0,4736 2020-04-14 2024-10-16 1646 4.50958904109589-0.3772436947326631.01739803299734-0.286019311702574 EUR 4Y 9M OIS -0,4645 2020-04-14 2025-01-16 1738 4.76164383561644-0.3715507487358761.01809949028798-0.269603599904308 EUR 5Y OIS -0,4549 2020-04-14 2025-04-16 1828 5.00821917808219-0.3654885840902421.01873198104961-0.248344323491367 EUR 5Y 3M OIS -0,4453 2020-04-14 2025-07-16 1919 5.25753424657534-0.3593679424235251.01934096712987-0.236346402213657 EUR 5Y 6M OIS -0,4353 2020-04-14 2025-10-16 2011 5.50958904109589-0.352929483204981.0199106578081-0.218570555765567 EUR 5Y 9M OIS -0,4251 2020-04-14 2026-01-16 2103 5.76164383561644-0.3462955885864741.02043543572065-0.201235542823278 EUR 6Y OIS -0,4147 2020-04-14 2026-04-16 2193 6.00821917808219-0.339461587498881.02089415758873-0.179733369880013 EUR 6Y 3M OIS -0,4042 2020-04-14 2026-07-16 2284 6.25753424657534-0.3324893942095281.02131866881704-0.164433014913355 EUR 6Y 6M OIS -0,3934 2020-04-14 2026-10-16 2376 6.50958904109589-0.3252412099238571.02169797012905-0.14527018440574 EUR 6Y 9M OIS -0,3821 2020-04-14 2027-01-18 2470 6.76712328767123-0.3175731928935851.02202816450262-0.123731834459992 EUR 7Y OIS -0,3714 2020-04-14 2027-04-16 2558 7.00821917808219-0.3102320208275311.02228846628242-0.104165404628847 EUR 7Y 3M OIS -0,3602 2020-04-14 2027-07-16 2649 7.25753424657534-0.3024631952474911.02250576812501-0.084073427045893 EUR 7Y 6M OIS -0,3486 2020-04-14 2027-10-18 2743 7.51506849315069-0.2943246560448271.02267925456072-0.064968183700496 EUR 7Y 9M OIS -0,3373 2020-04-14 2028-01-17 2834 7.76438356164384-0.2863053006324411.02279450253115-0.0445765044413642 EUR 8Y OIS -0,3258 2020-04-14 2028-04-17 2925 8.01369863013699-0.2780504370997821.02284872078544-0.0209698455733068 EUR 8Y 6M OIS -0,3032 2020-04-14 2028-10-16 3107 8.51232876712329-0.2615486086839931.022829798221190.00365938184754496 EUR 9Y OIS -0,2806 2020-04-14 2029-04-16 3289 9.01095890410959-0.2446695927818371.022604992537520.0434841005390679 EUR 9Y 6M OIS -0,2584 2020-04-14 2029-10-16 3472 9.51232876712329-0.2277137441936051.022204659401710.0770433384149757 EUR 10Y OIS -0,2361 2020-04-14 2030-04-16 3654 10.0109589041096-0.2102983001936121.021574717483750.121972376300851 EUR 12Y OIS -0,1477 2020-04-14 2032-04-16 4385 12.013698630137-0.1373101169243961.01686578317240.228057375489654 EUR 15Y OIS -0,0444 2020-04-14 2035-04-16 5480 15.013698630137-0.04342874760453051.006632720174070.334212728928754 EUR 20Y OIS 0,0225 2020-04-14 2040-04-16 7307 20.01917808219180.02275503406257460.9953920096847850.222517189354642 EUR 25Y OIS 0,0071 2020-04-14 2045-04-17 9134 25.02465753424660.007125264699739290.998193795161258-0.0553074922556585 EUR 30Y OIS -0,0368 2020-04-14 2050-04-18 10961 30.0301369863014-0.03613111016080331.01106165201641-0.250779790878777

Table 3.8: The yield curves and discount factors for Eonia by Smith–Wilson technique at 2020-04-14 51 Figure 3.7: The yield curve for Eonia by Smith-Wilson at 2020-04-14 (Table 3.8)

Figure 3.8: The discount factors for Eonia by Smith-Wilson technique at 2020-04-14 (Table 3.8)

52 The results of the yield curves and the discount factor of 3-months Euribor are shown in 3.9. And Figure 3.9 and Figure 3.10 display yield curves trend. Because those negative rates make the curves are quite unusual. The details of calculations for Euribor rates by SW tecnique are illustrated in AppendicesE andF.

Figure 3.9: The yield curve for 3-months Euribor by Smith-Wilson at 2020-04-14 (Table 3.9)

And for 6-months Euribor we show the results by SW technique in Table 3.10. Note that in Figure 3.12 is showed monotonous increasing curve for discount factors. Is this reasonable or possible? Since the spot rates gotten by the SW technique are negative, in accordance with property of exponential function, this make sense that the discount factors monotonically increase.

3.3 The extended Nelson-Siegel model

Using forward interest rates as a monetary police guide is validated. Since the forward rates are constructed as implying market expectations of the time-path of future interest rates, future inflation rates, and future currency depreciation rates. Market expectations have been separ- ated into short, medium and long term, which is easier than the standard yield curve [21]. Due to the absence of a full set of forward markets, we have to calculate forward interest rates by using data on existing financial instruments, usually Treasury bills or Government bonds. In this section I will introduce forward rate estimation model, the ENS model. The ENS model sometimes is also called as Nelson-Siegel-Svensson model (NSS). Be- cause that the NS model was firstly introduced by Nelson and Siegel in 1987 to estimate the

53 Name QuoteMeasured date From date To dateDaysDays 1 2TTM Spot Discount Forward EURIBOR S/W -0.518 2020-04-14 2020-04-16 2020-04-23 9 -0.5193462711366871.00012984499692-0.519312557526729 EURIBOR 1M -0.404 2020-04-14 2020-04-16 2020-05-18 34 -0.4048182846591381.00038240147677-0.363542311867566 EURIBOR 2M 2020-04-14 2020-04-16 2020-06-16 63 -0.3278589043200541.00057391771034-0.237607922563115 EURIBOR 3M -0.248 2020-04-14 2020-04-16 2020-07-16 93 0.03380367253598520.9999126776587660.793557357179098 EUR 1X4 FRA -0.27 2020-04-14 2020-04-16 2020-08-17 125 0.03424940987766510.9998810855088130.0355453955595862 EUR 2X5 FRA -0.299 2020-04-14 2020-04-16 2020-09-16 155 0.03429548329197570.9998523497927470.0344879514332929 EUR 3X6 FRA -0.322 2020-04-14 2020-04-16 2020-10-16 185 0.03439602755446210.9998232582568410.0349160142041756 EUR 4X7 FRA -0.347 2020-04-14 2020-04-16 2020-11-16 216 0.034422275475110.9997934876737560.0345794311128991 EUR 1Y IRS 3M -0.347 2020-04-14 2020-04-16 2021-04-16 367 -0.0535263241790311.00054582004374-0.17926616167303 EUR 15M IRS 3M -0.363 2020-04-14 2020-04-16 2021-07-16 458 -0.01400424177652271.000178180948270.145413732204403 EUR 18M IRS 3M -0.373 2020-04-14 2020-04-16 2021-10-18 552 0.01010289742273660.9998451009042890.127582332424994 EUR 21M IRS 3M -0.377 2020-04-14 2020-04-16 2022-01-17 643 0.02409211717897520.9995697805890870.108964805667625 EUR 2Y IRS 3M -0.38 2020-04-14 2020-04-16 2022-04-18 734 0.03224945832488780.9993426855033740.0898989059820682 EUR 3Y IRS 3M -0.371 2020-04-14 2020-04-16 2023-04-17 1098 0.03534207097136960.9989226475966340.0415870144266502 EUR 4Y IRS 3M -0.346 2020-04-14 2020-04-16 2024-04-16 1463 0.02535010070039930.998970330548077-0.00470782353483237 EUR 5Y IRS 3M -0.31 2020-04-14 2020-04-16 2025-04-16 1828 0.01873514740244490.99904912321868-0.00777872850732431 EUR 6Y IRS 3M -0.271 2020-04-14 2020-04-16 2026-04-16 2193 0.01720124871564630.9989527060612360.00951960727349734 EUR 7Y IRS 3M -0.229 2020-04-14 2020-04-16 2027-04-16 2558 0.0203163951596810.9985574487338320.0390406024171313 EUR 8Y IRS 3M -0.184 2020-04-14 2020-04-16 2028-04-17 2925 0.02661742410746480.9978396711678210.070561133825097 EUR 9Y IRS 3M -0.139 2020-04-14 2020-04-16 2029-04-16 3289 0.03311277786496270.9969793511898840.0853443866445621 EUR 10Y IRS 3M -0.094 2020-04-14 2020-04-16 2030-04-16 3654 0.03720575523136230.9962307374152470.0741152389393602 EUR 11Y IRS 3M -0.05 2020-04-14 2020-04-16 2031-04-16 4019 0.0359276978057730.9959971047658380.0231358305214048 EUR 12Y IRS 3M -0.008 2020-04-14 2020-04-16 2032-04-16 4385 0.02784140590491550.996614505838953-0.0609342670098941 EUR 15Y IRS 3M 0.094 2020-04-14 2020-04-16 2035-04-16 5480 -0.01363336555586541.00207745612927-0.179231499583752 EUR 20Y IRS 3M 0.157 2020-04-14 2020-04-16 2040-04-16 7307 -0.03879522952217221.00790543820871-0.113936368389095 EUR 25Y IRS 3M 0.14 2020-04-14 2020-04-16 2045-04-17 9134 -0.02935969065133341.007477020312560.00837908138206061 EUR 30Y IRS 3M 0.092 2020-04-14 2020-04-16 2050-04-18 10961 -0.008216958925701291.00250496794660.0977266730079081 EUR 40Y IRS 3M 0.016 2020-04-14 2020-04-16 2060-04-16 14612 0.03013202880132940.9878442299184040.146338309518741 EUR 50Y IRS 3M -0.053 2020-04-14 2020-04-16 2070-04-16 18264 0.01747611021473630.991172975714985-0.0331057103077976

Table 3.9: The yield curves and discount factors for 3-months Euribor by Smith–Wilson tech- nique at 2020-04-14 54 Figure 3.10: The discount factors for 3-months Euribor by Smith-Wilson at 2020-04-14 (Table 3.9)

Figure 3.11: The yield curve for 6-months Euribor by Smith-Wilson at 2020-04-14 (Table 3.10)

55 Name QuoteMeasuredFrom date date To date Days Spot Discount Forward EURIBOR 6M -0.195 2020-04-142020-04-16 2020-10-16 185 -0.009536112539022931.00004900622354-0.00943389087466435 EUR 1X7 FRA -0.223 2020-04-142020-04-16 2020-11-16 216 -0.009279212715311361.00005567682619-0.00774607502999454 EUR 2X8 FRA -0.25 2020-04-142020-04-16 2020-12-16 246 -0.009006657695206841.00006154738821-0.00704424087477392 EUR 3X9 FRA -0.269 2020-04-142020-04-16 2021-01-18 279 -0.008694666034488961.0000673859321-0.00636889142695273 EUR 4X10 FRA -0.288 2020-04-142020-04-16 2021-02-16 308 -0.008418818900823261.00007203026687-0.00576496584932921 EUR 5X11 FRA -0.307 2020-04-142020-04-16 2021-03-16 336 -0.008156117907845391.00007612666463-0.00526639619925813 EUR 6X12 FRA -0.316 2020-04-142020-04-16 2021-04-16 367 -0.007873057804026081.00008026467143-0.00480504157664905 EUR 7X13 FRA -0.326 2020-04-142020-04-16 2021-05-17 398 -0.007600523918499581.00008403154488-0.00437406613290455 EUR 8X14 FRA -0.335 2020-04-142020-04-16 2021-06-16 428 -0.007348044645757081.00008736390235-0.00399847963238098 EUR 9X15 FRA -0.337 2020-04-142020-04-16 2021-07-16 458 -0.00710716355406621.00009042300202-0.00367058769873389 EUR 10X16 FRA -0.338 2020-04-142020-04-16 2021-08-16 489 -0.006870513501469811.00009332882993-0.00337419491906611 EUR 11X17 FRA -0.339 2020-04-142020-04-16 2021-09-16 520 -0.006646095837840631.00009600377017-0.00310608402225843 EUR 12X18 FRA -0.336 2020-04-142020-04-16 2021-10-18 552 -0.00642681947141831.0000985494209-0.00286357487258975 EUR 2Y IRS -0.294 2020-04-142020-04-16 2022-04-18 734 -0.005388121645171111.00010986384813-0.00223777272269109 EUR 3Y IRS -0.287 2020-04-142020-04-16 2023-04-17 1098 -0.004039175738494371.00012320244882-0.00131903975698123 EUR 4Y IRS -0.262 2020-04-142020-04-16 2024-04-16 1463 -0.003217894356980561.00013078020222-0.000747297123443036 EUR 5Y IRS -0.227 2020-04-142020-04-16 2025-04-16 1828 -0.002671142297298231.00013564386878-0.000479639039777909 EUR 6Y IRS -0.191 2020-04-142020-04-16 2026-04-16 2193 -0.002282094266917221.00013902723915-0.000333655895600513 EUR 7Y IRS -0.154 2020-04-142020-04-16 2027-04-16 2558 -0.001991482561831341.00014151591224-0.000245423436617621 EUR 8Y IRS -0.114 2020-04-142020-04-16 2028-04-17 2925 -0.001765192552571881.00014343218031-0.000187944842051617 EUR 9Y IRS -0.075 2020-04-142020-04-16 2029-04-16 3289 -0.001586276323455531.00014493446943-0.000148556513611396 EUR 10Y IRS -0.036 2020-04-142020-04-16 2030-04-16 3654 -0.001439853272756561.0001461557869-0.000120441106757169 EUR 11Y IRS 0.003 2020-04-142020-04-16 2031-04-16 4019 -0.001318132135119731.00014716563477-0.0000995867781983784 EUR 12Y IRS 0.04 2020-04-142020-04-16 2032-04-16 4385 -0.001215098284846171.00014801667503-0.0000836964889930007 EUR 13Y IRS 0.075 2020-04-142020-04-16 2033-04-18 4752 -0.001126761770179681.0001487436149-0.0000712968483317462 EUR 14Y IRS 0.105 2020-04-142020-04-16 2034-04-17 5116 -0.001050967963981431.000149365379-0.0000614839694547497 EUR 15Y IRS 0.13 2020-04-142020-04-16 2035-04-16 5480 -0.0009847191932550161.00014990737885-0.0000535963462047064 EUR 16Y IRS 0.15 2020-04-142020-04-16 2036-04-16 5846 -0.0009260189459160791.00015038649463-0.0000471190564377452 EUR 17Y IRS 0.164 2020-04-142020-04-16 2037-04-16 6211 -0.0008740528713365921.0001508097702-0.0000417414323852661 EUR 18Y IRS 0.174 2020-04-142020-04-16 2038-04-16 6576 -0.0008276057055210431.0001511874032-0.0000372403645732247 EUR 19Y IRS 0.18 2020-04-142020-04-16 2039-04-18 6943 -0.0007856258789596631.00015152815917-0.0000334205886248721 EUR 20Y IRS 0.182 2020-04-142020-04-16 2040-04-16 7307 -0.0007479923266470881.00015183319024-0.0000301633283552305 EUR 21Y IRS 0.181 2020-04-142020-04-16 2041-04-16 7672 -0.0007137081711529751.00015211070902-0.0000273675531081739 EUR 22Y IRS 0.178 2020-04-142020-04-16 2042-04-16 8037 -0.0006824277966835041.00015236361177-0.000024940032076661 EUR 23Y IRS 0.172 2020-04-142020-04-16 2043-04-16 8402 -0.0006537731656119041.00015259503414-0.0000228217385279286 EUR 24Y IRS 0.165 2020-04-142020-04-16 2044-04-18 8770 -0.0006272193479449081.00015280927641-0.000020955280375196 EUR 25Y IRS 0.156 2020-04-142020-04-16 2045-04-17 9134 -0.0006029935113569851.00015300455769-0.000019310578495954 EUR 26Y IRS 0.146 2020-04-142020-04-16 2046-04-16 9498 -0.0005805689321081351.00015318516824-0.000017859845726219 EUR 27Y IRS 0.135 2020-04-142020-04-16 2047-04-16 9863 -0.0005596968415132531.00015335314483-0.0000165650141765106 EUR 28Y IRS 0.124 2020-04-142020-04-16 2048-04-16 10229 -0.0005402216700194881.00015350976649-0.0000154030446491272 EUR 29Y IRS 0.113 2020-04-142020-04-16 2049-04-16 10594 -0.0005221038840379381.00015365537454-0.0000143591355874368 EUR 30Y IRS 0.102 2020-04-142020-04-16 2050-04-18 10961 -0.0005050718435996191.00015379217141-0.0000134167026164405 EUR 40Y IRS 0.02 2020-04-142020-04-16 2060-04-16 14612 -0.0003813154633681561.0001547836875-9.77514526009667E-06

Table 3.10: The yield curves and discount factors for 6-months Euribor by Smith–Wilson technique at 2020-04-14 56 Figure 3.12: The yield curve for 6-months Euribor by Smith-Wilson at 2020-04-14 (Table 3.10) interest rates, and then in 1994 the model was extended by Svensson. Svensson added a term which can accept an extra lump in the yield curve [14].

3.3.1 The original model Charles R. Nelson and Andrew F. Siegel realized that there is need for a compact model of term structure of the yield curves. In 1987 they introduced firstly their over simple model of the yield curve, see eq.(3.71) below. Although the model was parsimonious it didn’t prevent its capability of capturing shapes of yield curves. Nelson and Siegel [16] even claimed that the model is be able to fit U.S. Treasury bill yields and predict the price of a long-term Treasury bond. The following second-order differential equation for the instantaneous forward rate at ma- turity m was the original model of the NS model [16, p.475]:

f orward r (m) = β0 + β1 exp( m/τ) + β2[(m/τ) exp( m/τ)], (3.71) · − · − where r f orward(m) denote the instantaneous forward rate, τ is positive time constant and de- termines the location of the hump or the trough in the yield curve [14], and β0, β1 and β2 are constants too and determined by initial conditions. The model (3.71) can generate monotonic, humped and S shaped forward rate curves which is given by the solution of the equation for the case of equal roots. Additionally, by expanding in a power series in the difference between the roots it might be taken as an estimation to the solution in the unequal roots without causing problem of overparameterization. Actually the model (3.71) can be divided into two parts. One is constant. And the other one is Laguerre function which consists of a polynomial times an exponential decay term. In

57 accordance with the plot of exponential function, we find that if β1 is positive β1 exp( m/τ) · − is a monotonically decreasing; in contrast, if β1 is negative and β1 exp( m/τ) is a mono- · − tonically increasing. Moreover, the third term, β2[(m/τ) exp( m/τ)], what determines the · − shape of curve, a hump-shape if β2 is positive and a trough-shape if β2 is negative [21]. As we mentioned about the definition of the spot rate, see eq.(2.16), with regarding to the original NS model, see eq.(3.71), we get the following expression for the spot rate [16, p.475]: 1 m rspot(m) = r f orward(x)dx, (3.72) m Z0 where r f orward(x) is instantaneous forward rate. This indicates that the spot rate is average of integration of instantaneous forward rate from 0 to m. Substituting eq. (3.71) in the above formula we have:

m spot 1 r (m) = [β0 + β1 exp( x/τ) + β2 (x/τ) exp( x/τ)]dx. (3.73) m 0 · − · · − Z x To change variable, we let s = τ then get dx = τds. Eq.(3.73) turns into [19, p.210]:

m m spot τ τ s τ τ s r (m) =β0 + β1 e− ds + β2 s e− ds m 0 m 0 · Z Z m m m τ τ s τ τ s τ s =β0 + β1 e− 0 + β2 se− 0 e− ds m − m − − 0  Z   m  m  (3.74) 1 e τ 1 e τ m − − − =β0 + β1 − + β2 − e τ " m/τ # " m/τ − # m 1 e τ m − − =β0 + (β1 + β2) − β2 e τ , " m/τ # − · which as well is linear in coefficients, given τ. In their published research article, Nelson and Siegel [16] assigned values to those parameters, such as τ = 1, β0 = 1 and β0 + β1 = 0, to get a new formula. The following formula was reformed by them [16, p.476]:

rspot(m) = 1 (1 a) [1 exp( m)]/m a exp( m), (3.75) − − · − − − · − where a becomes the single parameter which can decide the span of shapes available for rspot(m). If the range values of a is within interval [ 6,12] with equal increments, we obtain the following figure. −

Figure 3.13 includes humps, S shapes and monotonic curves, which proves the shape flex- ibility of the model (3.71). Furthermore, the negative co-relationship between the exponential decay term and its coefficient implies that if m gets large the upper limitation turns to β0 as well as if m gets small the lower limitation turns to (β0 + β1) which is equal to zero. There is another way to observe the shape flexibility of the second-order model (3.71). To interpret coefficients of the model in order to assess strengths of the short-, medium-, and long-term components of the forward rate curve. Nelson and Siegel [16] found out that β0

58 Figure 3.13: Yield curve shapes, parameter a spans from 6 to 12 with equal increments [16, p.476] −

represents the contribution of the long-term component of the model while β1 represents the contribution of the short-term component and β2 implies the contribution of the medium- term component. Additionally, they also charted a Figure 3.14 to illustrate the adequacy of assignments of coefficients.

The horizon line implies that the long-term component is constant, namely β0. The medium-term curve what is determined by β2 and starts out at zero and falls off to zero again, and is the only function within this model (3.71). The fastest and monotonic decline curve is the short-term curve and determined by β1. For the parameter depended model, choosing appropriate values for parameters is ex- tremely important. Through empirical practice Nelson and Siegel [16] found the best fitting values for τ is within range of 50-100 and the best fit for U.S. Treasury Bills to be given by τ = 40. However, they also claimed that the set values of parameters were not perfectly fit the data. This indicates that in practice we have to fit τ value to each data set individually.

3.3.2 The extended version of Svensson In research paper from Nelson and Siegel [16], they had carried out several progresses by adding factors and decaying parameters to improve the model’s flexibility to catch a wider variety of curve shapes. The ENS model is widely used by central banks and other market participants for modelling the yield curve. Under 1990s, the collapse of fixed exchange rates in Europe and the widening of ERM

59 Figure 3.14: Components of the forward rate curve [16, p.477] bands9 implied that a clarified intermediate goal for monetary police didn’t work anymore and new monetary police indicators were in need. Since flexible exchange rates have taken over fixed exchange rates [21]. To increase the flexibility and improve the fit, year 1994, Lars Svensson extended the NS model by adding a second hump or trough in the model (a fourth term). This achieved by adding another exponential term which is similar to the third term in the original NS model, but with a different declining parameter τ2. The function is then [21, p.6]:

m m m m m f (m;b) = β0 + β1 exp − + β2 exp − + β3 exp − , (3.76) · τ τ · τ τ · τ  1   1   1   2   2  where f (m;b) denotes instantaneous forward rate and b = (β0,β1,β2,τ1,β3,τ2) is parameter set. Note that here τ1 equals to τ in the NS model and β3 is a new added parameter. Parameters were estimated for Sweden for the trade date December 29, 1993. They are β0 = 8.06 percent per year, β1 = 0.31 percent per year, β2 = 6.25 percent per year, β3 = 1.98 percent per − − − year, τ1 = 1.58 year and τ2 = 0.15 year. Thereby he got Figure 3.15 below. The thick solid curve is the forward rate curve. The other curves show the four components of the forward rate curve. If we do same substituting and variable changing as I did for the NS model, we will get spot rate equal to [21, p.6]:

9"An exchange rate mechanism (ERM) is a device used to manage a country’s currency exchange rate relative to other currencies. It is part of an economy’s monetary policy and is put to use by central banks" [11].

60 Figure 3.15: Forward rate curve and components [21]

m m 1 exp − 1 exp − − τ1 − τ1 m i(m;b) =β0 + β1 m + β2 m exp      − −τ1  τ1 τ1   (3.77) m   1 exp − − τ2 m + β3 m exp .    − −τ2  τ2     Then the discount function becomes [21, p.7]:

i(m;b) d(m;b) = exp m . (3.78) − 100   Afterward, putting this discount function into eq.(2.25) to get estimated bond prices. This discount function is also parameter based function. McCulloch [21, p.7] suggested that para- meters should be chosen so as to minimize the sum of squared errors between the estimated and observed prices of the bonds. The observed prices of the bonds are calculated from quoted yields to maturity, coupon rates and times to maturity in accordance with eq.(2.26). However, due to prices are very insensitive to yields for short maturities, therefore minimizing price errors sometimes leads to fairly large yield errors for bonds and bills. There exists another reason which is that the focus of monetary policy analysis is on interest rates rather than prices. That is why it is better to minimize yield errors. Svensson [21] argued that the best fit parameters what are used in the discount function eq.(3.78) in order to compute estimated prices of coupon bonds (via eq.(2.25)) for obtaining estimated yield to maturity for each bond in accordance with eq.(2.26) should make yield error smallest. To make yield error smallest means to minimize the sum of squared yield errors between estimated yields and observed yields as small as possible.

61 In the next subsection, I will discuss the details about how to fix parameters of the ENS model.

Fixing parameters of the extended Nelson and Siegel model To fix parameters of the ENS model is to find the optimal values of the parameters that best fit the market spot rates by using least square method. We can summarize three steps to obtain best fit parameters by minimizing yield errors:

1. Using market spot rates in eq.(2.24) and eq.(2.25) in order to compute estimated prices of coupon bonds;

2. Using these estimated prices of coupon bonds in eq.(2.26) in order to compute estimated yield to maturity for each bond;

3. Minimizing the sum of squared yield errors between estimated yields and observed yields as small as possible. The best fit parameters is the parameters set which makes the sum of squared yield errors smallest.

In the conclusion section we will compare the ENS model with the bootstrapping method and the SW model. But no implementation for Eonia and Euribor in Python will be done for the ENS model.

62 Chapter 4

Conclusion

4.1 Comparing the bootstrapping method with the Smith Wilson technique

Both models are required a certain time to implement with market data for the first time. With acids of the modern software and language program such as Python we can definitely save lots of time. Especially with "smart" code the implementation progress can be more smooth and faster. However, there is always some thing trick which requires long time relative studying or working experiences. For example, the parameter α in the SW technique and the parameter set β and τ in the ENS model. According to those figures we got by applying real market data, namely Eonia and Euribor rates, in the bootstrapping method and the SW model, the smoothness of curves by the SW technique are worse than those curves created by the bootstrapping method. This is because one of the SW technique’s properties, market consistency. As I mentioned previously, Fig- ure 3.12 displays a monotonically increasing discount curve which is very uncommon. But from the theoretical perspective, when the spot rates are negative the corresponded discount factor curve turns to increase monotonically. Comparing figures from 3-months Euribor by the SW model and 6-months Euribor by the same model, we find that the sensitiveness is much worse when spot rates are negative. In contrast, those figures from the bootstrapping method are smooth and sensitive for both positive and negative spot rates. When spot rates are positive, figures obtained by the SW model for Euribor rates, namely Figure 3.9 and Figure 3.10, are very sensitive, non-smooth and unstable as well. The SW technique as the chosen technique by EIOPA, it has strength on creating liability curves that is equivalent to the value that would be required to transfer that liability in current market conditions. Under this paper created period, the world is suffered by the big pandemic caused by COVID-19 which causes the economic depression and the rising of unemployment. Thus, negative rates appear reas- onable. The sensitivity of the SW model captured nowadays economy. In addition, from the stability perspective, a sensitive curve can cause liability stability problem. The overestimated volatility could make investors stop investment, which is not good for economy for long-term consideration. The "trick" parameter α transfer emphasis to political decisions and human manipulation.

63 It might gives a reliable curve but it also requires lots of relative experiences. On the contrary, the traditional method, bootstrapping, is more simply to understand and implement as long as using right tools. Anyway, the Smith-Wilson method is far from being flawless, some of its issues are hard to overcome such as predetermination of an appropriate parameter. Nevertheless its positive strength such as market consistency what can give a real and more accurate estimation of yield curves.

4.2 Comparing the bootstrapping method with the extended Nelson and Siegel model

The other sophisticated technique like the SW model is the ENS model. We introduced it in previous section. Same as the SW model there is a parameter set which needs lots of experiences to predetermine. Although we can achieve this by getting help from the economic interpretation for this parameter set. Furthermore the initial values of parameters play a big roll on performence of yield curves. Kazemie [14, p.37-40] discusses comparative between the bootstrapping method and the ENS model and illustrate with some Figures 4.1, 4.2 and 4.3. Accordingly, curves created by the bootstrapping method and the ENS model are almost overlapped with each other except forward rate curves. As depicted in figures, the ENS model builds more smooth forward curve specially at long tail of the curve while the bootstrapping method builds a kind of zigzag forward curve. Getting the optimal values for the parameters is highly related to the initial values that we set. Although the initial values of the vector of parameters can be set by the help of the economic interpretation of these parameters. Due to most of yield curves from both methods are overlapped, which proves accuracy. By adopting linear interpolation performs the bootstrapping method with regard to missing data. Except the predetermined parameter set in the ENS what we can create and solve the optimal problem by minimize the sum of the squared deference between estimated rates taken from ENS model and observed rates from the market. Otherwise the ENS is a simple and flexible model.

Figure 4.1: Plot of fitted yield curves for 3M Euribor rates, together with actual market rates

64 Figure 4.2: 3M Forward Curves for EONIA rates by linear interpolation and NSS model

Figure 4.3: Discount Curves for 6M Euribor rates built by linear interpolation and NSS model

65 Bibliography

[1] EIOPA: Mission and tasks. https://www.eiopa.europa.eu/about/mission-and-tasks_en. accessed: 10.09.2020.

[2] Panel banks of Eonia. https://www.emmi-benchmarks.eu/euribor-eonia-org/panel- banks.html. accessed: 28.04.2020.

[3] Panel banks of Euribor. https://www.emmi-benchmarks.eu/euribor-org/panel- banks.html. accessed: 28.04.2020.

[4] Commission delegated regulation (EU) 2015/35 of 10 october 2014 supplementing dir- ective 2009/138/ec of the European Parliament and of the Council on the taking-up and pursuit of the business of insurance and reinsurance (Solvency II). https://eur- lex.europa.eu/eli/reg_del/2015/35/2020-07-30, 2015.

[5] Solvency II overview — frequently asked questions. ht- tps://ec.europa.eu/commission/presscorner/detail/en/MEMO_15_3120, January 2015.

[6] Risk-free interest rate term structures. report on the calculation of the UFR for 2020. ht- tps://www.eiopa.europa.eu/sites/default/files/risk_free_interest_rate/calculation_of_the_ufr_for_2020.pdf, May 2019.

[7] Technical documentationof the methodology to de- rive EIOPA’s risk-free interest rate term structures. https://www.eiopa.europa.eu/sites/default/files/risk_free_interest_rate/12092019- technical_documentation.pdf, September 2019.

[8] Kemi Akinyemi, Jack Kerbeshian, Benjamin Leiser, and Patricia Matson. Yield curve ex- trapolation methods. methodologies for valuing cash flows that extend beyond the max- imum yield curve. technical report, Society of Actuaries, 475 N. Martingale Road, Suite 600, Schaumburg, Illinois 60173, March 2019.

[9] German Bernhart. Interest rate bootstrapping explained. technical report, XAIA Invest- ment, Sonnenstraße 19, 80331 München, Germany, February 2013.

[10] Lev Borodovsky and Marc Lore, editors. Professional’s Handbook of Financial Risk Management. Butterworth-Heinemann, London, February 2000.

66 [11] Adam Hayes. Exchange rate mechanism (ERM) definition. https://www.investopedia.com/terms/e/exchange-rate-mechanism.asp. accessed: 30.03.2020.

[12] Matthew Hornbach, Kelcie Gerson, Vishwanath Tirupattur, Todd Castagno, James Egan, Jay Bacow, Frederick T. Fuchs, Somdutta Basu, Ailing Deng, Charlie Wu, Bill Tang, and Zuri Zhao. Usd libor reform. technical report, Morgan Stanley, September 2019.

[13] John C. Hull. Options, Futures, and Other Derivatives. Pearson, 10th edition, 2020.

[14] Neda Kazemie. Mispricing due to Nelson–Siegel–Svensson model. Master thesis, Divi- sion of Applied Mathematics, Mälardalen University, Sweden, 2014.

[15] Maria-Magdalena Magurean. Extrapolation methods of the termstructure of interest rates under Solvency II. mathesis, Facoltà di ingegneria dell’informazione, informatica e stat- istica, Università di Roma La Sapienza, 2016.

[16] Charles R. Nelson and Andrew F. Siegel. Parsimonious modeling of yield curves. The Journal of Business, 60(4):473–489, 1987.

[17] FINANSTILSYNET The Financial Supervisory Authority of Norway. A technical note on the Smith–Wilson method. https://1library.net/document/zgxw4lvq-a-technical-note- on-the-smith-wilson-method.html, July 2010.

[18] Jan Röman. Libor versus OIS discounting whenbootstrapping the STIBOR swap curve. Technical report, Mälardalen University, 2020.

[19] Jan R. M. Röman. Analytical finance. Vol. II. The mathematics of interest rate derivat- ives, markets, risk and valuation. Palgrave Macmillan, Cham, 2017.

[20] Andrew D. Smith and Michael Thomas. Further down the line. The Actuary, (12), 2009.

[21] Lars Svensson. Estimating forward interest rates with the extended Nelson and Siegel method. Sveriges Riksbank Quarterly Review, (3):13–26, 1995.

67 Appendices

68 Appendix A

The calculation of OIS discounting with bootstrapping method in Python

69 EoData

August 31, 2020

[1]: import pandas as pd import math import numpy as np [2]: EoData = pd.read_csv('Data_per_2020-04-14.csv', sep=';') #import Eonia rates␣ , →index EoData.head() [2]: Name Quote From date To date Days 0 EONIA O/N -0.4510 2020-04-14 2020-04-15 1 1 EUR 1W OIS -0.4583 2020-04-14 2020-04-23 9 2 EUR 1M OIS -0.4606 2020-04-14 2020-05-18 34 3 EUR 2M OIS -0.4645 2020-04-14 2020-06-16 63 4 EUR 3M OIS -0.4696 2020-04-14 2020-07-16 93 [3]: print(EoData.index) # There are total 45 rows/tenors

RangeIndex(start=0, stop=45, step=1)

i 1 Tj Tj 1 D s ∑ − − − D(0, T ) O/N − i j=1 360 j DT = (Tj Tj 1 ) − − 1 + si 360 for one year tenors; ( )

i 1 Tj Tj 1 − − DO/N si ∑j−=1 360 D(0, Tj) = − DT T T ( j− j 1 ) 360− (1 + si)( ) for tenors longer than a year. [4]: s_i=EoData['Quote'] print(s_i)

0 -0.4510 1 -0.4583 2 -0.4606 3 -0.4645 4 -0.4696

1 5 -0.4841 6 -0.4978 7 -0.5077 8 -0.5169 9 -0.5217 10 -0.5242 11 -0.5232 12 -0.5261 13 -0.5245 14 -0.5205 15 -0.5149 16 -0.5095 17 -0.5037 18 -0.4973 19 -0.4902 20 -0.4823 21 -0.4736 22 -0.4645 23 -0.4549 24 -0.4453 25 -0.4353 26 -0.4251 27 -0.4147 28 -0.4042 29 -0.3934 30 -0.3821 31 -0.3714 32 -0.3602 33 -0.3486 34 -0.3373 35 -0.3258 36 -0.3032 37 -0.2806 38 -0.2584 39 -0.2361 40 -0.1477 41 -0.0444 42 0.0225 43 0.0071 44 -0.0368 Name: Quote, dtype: float64

[5]: EoData['Days'].shift(1).head() [5]: 0 NaN 1 1.0 2 9.0 3 34.0

2 4 63.0 Name: Days, dtype: float64 [6]: EoData['DeltaT'] = EoData['Days'] - EoData['Days'].shift(1) # get delta␣ , →time=time difference [7]: EoData.head() [7]: Name Quote From date To date Days DeltaT 0 EONIA O/N -0.4510 2020-04-14 2020-04-15 1 NaN 1 EUR 1W OIS -0.4583 2020-04-14 2020-04-23 9 8.0 2 EUR 1M OIS -0.4606 2020-04-14 2020-05-18 34 25.0 3 EUR 2M OIS -0.4645 2020-04-14 2020-06-16 63 29.0 4 EUR 3M OIS -0.4696 2020-04-14 2020-07-16 93 30.0 [8]: s_ON=s_i[0] s_ON [8]: -0.451 [9]: D_ON=1/(1+s_ON*1/36000) D_ON [9]: 1.000012527934725 [10]: EoData['Discount']=0.0 # creat column 'Discount' for discount factors [11]: EoData.head() [11]: Name Quote From date To date Days DeltaT Discount 0 EONIA O/N -0.4510 2020-04-14 2020-04-15 1 NaN 0.0 1 EUR 1W OIS -0.4583 2020-04-14 2020-04-23 9 8.0 0.0 2 EUR 1M OIS -0.4606 2020-04-14 2020-05-18 34 25.0 0.0 3 EUR 2M OIS -0.4645 2020-04-14 2020-06-16 63 29.0 0.0 4 EUR 3M OIS -0.4696 2020-04-14 2020-07-16 93 30.0 0.0 [12]: EoData.loc[0,'Discount']=D_ON.copy() # assign discount factor for over-night to␣ , →first row of 'Discount' [13]: EoData.head() [13]: Name Quote From date To date Days DeltaT Discount 0 EONIA O/N -0.4510 2020-04-14 2020-04-15 1 NaN 1.000013 1 EUR 1W OIS -0.4583 2020-04-14 2020-04-23 9 8.0 0.000000 2 EUR 1M OIS -0.4606 2020-04-14 2020-05-18 34 25.0 0.000000 3 EUR 2M OIS -0.4645 2020-04-14 2020-06-16 63 29.0 0.000000 4 EUR 3M OIS -0.4696 2020-04-14 2020-07-16 93 30.0 0.000000 [14]: EoData.index [14]: RangeIndex(start=0, stop=45, step=1) [15]: EoData[0:8] # tenors not more than one year

3 [15]: Name Quote From date To date Days DeltaT Discount 0 EONIA O/N -0.4510 2020-04-14 2020-04-15 1 NaN 1.000013 1 EUR 1W OIS -0.4583 2020-04-14 2020-04-23 9 8.0 0.000000 2 EUR 1M OIS -0.4606 2020-04-14 2020-05-18 34 25.0 0.000000 3 EUR 2M OIS -0.4645 2020-04-14 2020-06-16 63 29.0 0.000000 4 EUR 3M OIS -0.4696 2020-04-14 2020-07-16 93 30.0 0.000000 5 EUR 6M OIS -0.4841 2020-04-14 2020-10-16 185 92.0 0.000000 6 EUR 9M OIS -0.4978 2020-04-14 2021-01-18 279 94.0 0.000000 7 EUR 1Y OIS -0.5077 2020-04-14 2021-04-16 367 88.0 0.000000 [16]: j=np.array(range(1,8)) j [16]: array([1, 2, 3, 4, 5, 6, 7]) [17]: h=np.zeros(8) h [17]: array([0., 0., 0., 0., 0., 0., 0., 0.]) [18]: # get discount factor for tenors under one year (incl. one year) h=EoData.loc[0,'Days']/360*EoData.loc[0,'Discount'].copy() for j in range(1,8): EoData.loc[j,'Discount']=(D_ON-s_i[j]/100*h)/(1+s_i[j]*EoData. , →loc[j,'DeltaT']/36000).copy() h+=EoData.loc[j,'DeltaT']/360*EoData.loc[j,'Discount'].copy() print(h) EoData['Discount'][:8]

0.02500285960071368 0.09447839400470748 0.1751004779491218 0.25853602904304773 0.5147315835008299 0.7768557315064395 1.0225722960019237

[18]: 0 1.000013 1 1.000127 2 1.000448 3 1.000826 4 1.001227 5 1.002504 6 1.003880 7 1.005204 Name: Discount, dtype: float64 [19]: # get discount factor for tenors over one year #h=EoData.loc[7,'Days']/360*EoData.loc[7,'Discount'].copy() for j in range(8,45):

4 EoData.loc[j,'Discount']=(D_ON-s_i[j]/100*h)/(1+s_i[j]/100)**(EoData. , →loc[j,'DeltaT']/360).copy() h+=EoData.loc[j,'DeltaT']/360*EoData.loc[j,'Discount'].copy() EoData.Discount[:45] [19]: 0 1.000013 1 1.000127 2 1.000448 3 1.000826 4 1.001227 5 1.002504 6 1.003880 7 1.005204 8 1.006616 9 1.008051 10 1.009427 11 1.010745 12 1.012151 13 1.013458 14 1.014690 15 1.015854 16 1.016998 17 1.018101 18 1.019166 19 1.020157 20 1.021077 21 1.021934 22 1.022727 23 1.023421 24 1.024080 25 1.024679 26 1.025215 27 1.025662 28 1.026061 29 1.026396 30 1.026663 31 1.026849 32 1.026974 33 1.027041 34 1.027040 35 1.026965 36 1.026669 37 1.026138 38 1.025418 39 1.024448 40 1.018350 41 1.006885

5 42 0.995392 43 0.998195 44 1.011320 Name: Discount, dtype: float64 [20]: EoData.head() [20]: Name Quote From date To date Days DeltaT Discount 0 EONIA O/N -0.4510 2020-04-14 2020-04-15 1 NaN 1.000013 1 EUR 1W OIS -0.4583 2020-04-14 2020-04-23 9 8.0 1.000127 2 EUR 1M OIS -0.4606 2020-04-14 2020-05-18 34 25.0 1.000448 3 EUR 2M OIS -0.4645 2020-04-14 2020-06-16 63 29.0 1.000826 4 EUR 3M OIS -0.4696 2020-04-14 2020-07-16 93 30.0 1.001227 [21]: EoData['Forward']=0.0 # creat column 'Forward' for forward rates [22]: EoData.loc[0,'Forward']=(1-EoData.loc[0,'Discount'])/EoData. , →loc[0,'Discount']*36000 # assign forward rate for over-night to first row of␣ , →'Forward' EoData.head() [22]: Name Quote From date To date Days DeltaT Discount Forward 0 EONIA O/N -0.4510 2020-04-14 2020-04-15 1 NaN 1.000013 -0.451 1 EUR 1W OIS -0.4583 2020-04-14 2020-04-23 9 8.0 1.000127 0.000 2 EUR 1M OIS -0.4606 2020-04-14 2020-05-18 34 25.0 1.000448 0.000 3 EUR 2M OIS -0.4645 2020-04-14 2020-06-16 63 29.0 1.000826 0.000 4 EUR 3M OIS -0.4696 2020-04-14 2020-07-16 93 30.0 1.001227 0.000 [23]: k=np.array(range(0,45)) [24]: # get forward rates for all tenors for k in range(1,45): EoData.loc[k,'Forward']=(EoData.loc[k-1,'Discount']-EoData. , →loc[k,'Discount'])/EoData.loc[k,'Discount']*36000/EoData.loc[k,'DeltaT']. , →copy() EoData.Forward[:45] [24]: 0 -0.451000 1 -0.515581 2 -0.461428 3 -0.469070 4 -0.480303 5 -0.498732 6 -0.524703 7 -0.539000 8 -0.554874 9 -0.545029 10 -0.539280 11 -0.516170 12 -0.549359 13 -0.510088

6 14 -0.480517 15 -0.453393 16 -0.444863 17 -0.428557 18 -0.409053 19 -0.384136 20 -0.356507 21 -0.328097 22 -0.303326 23 -0.271392 24 -0.254455 25 -0.228894 26 -0.204476 27 -0.174216 28 -0.153800 29 -0.128049 30 -0.099389 31 -0.074042 32 -0.048452 33 -0.024813 34 0.000202 35 0.029191 36 0.056964 37 0.102424 38 0.138143 39 0.187239 40 0.294883 41 0.374366 42 0.227500 43 -0.055324 44 -0.255717 Name: Forward, dtype: float64 [25]: EoData['Spot']=0.0 # creat column 'Spot' for continuously compounded zero rates [26]: m=np.array(range(0,45)) [27]: # get continuously compounded zero rates for all tenors for m in range(0,45): EoData.loc[m,'Spot']=-100*np.log(EoData.loc[m,'Discount'])*365/EoData. , →loc[m,'Days'].copy() EoData.Spot[:45] [27]: 0 -0.457267 1 -0.515493 2 -0.480507 3 -0.478283 4 -0.481118 5 -0.493483

7 6 -0.506579 7 -0.516235 8 -0.525521 9 -0.530199 10 -0.532597 11 -0.531492 12 -0.534347 13 -0.532674 14 -0.528591 15 -0.522902 16 -0.517422 17 -0.511544 18 -0.505067 19 -0.497888 20 -0.489909 21 -0.481127 22 -0.471945 23 -0.462261 24 -0.452578 25 -0.442493 26 -0.432208 27 -0.421721 28 -0.411132 29 -0.400241 30 -0.388844 31 -0.378050 32 -0.366751 33 -0.355045 34 -0.343638 35 -0.332026 36 -0.309194 37 -0.286340 38 -0.263868 39 -0.241274 40 -0.151360 41 -0.045700 42 0.023069 43 0.007219 44 -0.037482 Name: Spot, dtype: float64 [28]: EoData.head() [28]: Name Quote From date To date Days DeltaT Discount \ 0 EONIA O/N -0.4510 2020-04-14 2020-04-15 1 NaN 1.000013 1 EUR 1W OIS -0.4583 2020-04-14 2020-04-23 9 8.0 1.000127 2 EUR 1M OIS -0.4606 2020-04-14 2020-05-18 34 25.0 1.000448 3 EUR 2M OIS -0.4645 2020-04-14 2020-06-16 63 29.0 1.000826

8 4 EUR 3M OIS -0.4696 2020-04-14 2020-07-16 93 30.0 1.001227

Forward Spot 0 -0.451000 -0.457267 1 -0.515581 -0.515493 2 -0.461428 -0.480507 3 -0.469070 -0.478283 4 -0.480303 -0.481118 [ ]: EoData.to_excel(r'/Users/pennyandersson/Desktop/Analytical Finance/thesis/my␣ , →work/ EoData.xlsx', sheet_name='EoData', index = False) [29]: import matplotlib.pyplot as plt %matplotlib inline [30]: EoData['TTM']=EoData['Days']/360 # time to maturity [31]: plt.figure(figsize=(15, 6)) [31]:

[32]: plt.plot(EoData['TTM'], EoData['Discount'], 'o-y', label= 'OIS discounting␣ , →factor', lw=1.5) plt.grid(True) plt.xlabel('Term(years)') plt.ylabel('Discount factor') plt.title('The bootstrapped OIS discounting curve at 2020-04-14 (Table 3.2)') [32]: Text(0.5, 1.0, 'The bootstrapped OIS discounting curve at 2020-04-14 (Table 3.2)')

9 [33]: plt.plot(EoData['TTM'], EoData['Spot'], 'o-c', label= 'Spot rate', lw=1.5) plt.plot(EoData['TTM'], EoData['Forward'],'o-m', label= 'Forward rate', lw=1.5) plt.grid(True) plt.xlabel('Term(years)') plt.ylabel('Yield') plt.title('The bootstrapped yield curve for Eonia at 2020-04-14 (Table 3.2)') plt.legend() [33]:

10 [ ]:

11 Appendix B

The calculation of 3-months Euribor with the bootstrapping method in Python

81 E3Data

August 31, 2020

[1]: import pandas as pd import math import numpy as np [2]: E3Data = pd.read_csv('E3 Data per 2020-04-14.csv', sep=';') #import 3-months␣ , →Euribor rates index E3Data.head() [2]: Name Quote Measured date From date To date Days 1 Days 2 0 EURIBOR S/W -0.518 2020-04-14 2020-04-16 2020-04-23 7 9 1 EURIBOR 1M -0.404 2020-04-14 2020-04-16 2020-05-18 32 34 2 EURIBOR 2M NaN 2020-04-14 2020-04-16 2020-06-16 61 63 3 EURIBOR 3M -0.248 2020-04-14 2020-04-16 2020-07-16 91 93 4 EUR 1X4 FRA -0.270 2020-04-14 2020-04-16 2020-08-17 123 125 [3]: print(E3Data.index) # There are total 29 rows/tenors

RangeIndex(start=0, stop=29, step=1)

0.1 Deposits We have discount factors and zero rates as:

1 Di = i = 1W, 1M, 2M, 3M di { } 1 + qi 360

ln Di Zi = 100 i = 1W, 1M, 2M, 3M − di { } 365

where qi is quoted rates in our case it is Euribor rates or swap rates and di is number of days. [4]: q_i=E3Data['Quote'] print(q_i)

0 -0.518 1 -0.404 2 NaN 3 -0.248 4 -0.270 5 -0.299

1 6 -0.322 7 -0.347 8 -0.347 9 -0.363 10 -0.373 11 -0.377 12 -0.380 13 -0.371 14 -0.346 15 -0.310 16 -0.271 17 -0.229 18 -0.184 19 -0.139 20 -0.094 21 -0.050 22 -0.008 23 0.094 24 0.157 25 0.140 26 0.092 27 0.016 28 -0.053 Name: Quote, dtype: float64

[5]: E3Data.loc[2,'Quote']=0.0 # assign a zero to Euribor 2M quoted rate for␣ , →calculation convenience [6]: E3Data[0:4] #tenors for deposits [6]: Name Quote Measured date From date To date Days 1 Days 2 0 EURIBOR S/W -0.518 2020-04-14 2020-04-16 2020-04-23 7 9 1 EURIBOR 1M -0.404 2020-04-14 2020-04-16 2020-05-18 32 34 2 EURIBOR 2M 0.000 2020-04-14 2020-04-16 2020-06-16 61 63 3 EURIBOR 3M -0.248 2020-04-14 2020-04-16 2020-07-16 91 93 [7]: # get discount facotors for deposits E3Data.loc[0:4,'Discount']=1/(1+q_i[0:4]*E3Data.loc[0:4,'Days 2']/36000).copy() E3Data[0:4] [7]: Name Quote Measured date From date To date Days 1 Days 2 \ 0 EURIBOR S/W -0.518 2020-04-14 2020-04-16 2020-04-23 7 9 1 EURIBOR 1M -0.404 2020-04-14 2020-04-16 2020-05-18 32 34 2 EURIBOR 2M 0.000 2020-04-14 2020-04-16 2020-06-16 61 63 3 EURIBOR 3M -0.248 2020-04-14 2020-04-16 2020-07-16 91 93

Discount 0 1.000130 1 1.000382

2 2 1.000000 3 1.000641 [8]: # using interpolation to get Euribor 2M discount factor E2m=E3Data.loc[3,'Discount']-(E3Data.loc[3,'Discount']-E3Data. , →loc[1,'Discount'])/(93-34)*(93-63) E2m [8]: 1.0005091911863857 [9]: E3Data.loc[2,'Discount']=E2m [10]: # get spot rates for deposits E3Data.loc[0:4,'Spot']=-100*np.log(E3Data.loc[0:4,'Discount'])/(E3Data.loc[0: , →4,'Days 2']/365).copy() E3Data[0:4] [10]: Name Quote Measured date From date To date Days 1 Days 2 \ 0 EURIBOR S/W -0.518 2020-04-14 2020-04-16 2020-04-23 7 9 1 EURIBOR 1M -0.404 2020-04-14 2020-04-16 2020-05-18 32 34 2 EURIBOR 2M 0.000 2020-04-14 2020-04-16 2020-06-16 61 63 3 EURIBOR 3M -0.248 2020-04-14 2020-04-16 2020-07-16 91 93

Discount Spot 0 1.000130 -0.525228 1 1.000382 -0.409689 2 1.000509 -0.294933 3 1.000641 -0.251525

0.2 FRAs We have discount factors and zero rates as:\

i 1 i DFRA− DFRA = i ; i = 1x4 FRA, 2x5 FRA, 3x6 FRA, 4x7 FRA i dFRA { } 1 + qFRA 360 i i ln (DFRA) ZFRA(T) = 100 i ; i = 1x4 FRA, 2x5 FRA, 3x6 FRA, 4x7 FRA − dFRA { } 365 [11]: E3Data[4:8] [11]: Name Quote Measured date From date To date Days 1 Days 2 \ 4 EUR 1X4 FRA -0.270 2020-04-14 2020-04-16 2020-08-17 123 125 5 EUR 2X5 FRA -0.299 2020-04-14 2020-04-16 2020-09-16 153 155 6 EUR 3X6 FRA -0.322 2020-04-14 2020-04-16 2020-10-16 183 185 7 EUR 4X7 FRA -0.347 2020-04-14 2020-04-16 2020-11-16 214 216

Discount Spot 4 NaN NaN 5 NaN NaN

3 6 NaN NaN 7 NaN NaN [12]: E3Data['Discount'][1] # discount factor at 2020-05-18 [12]: 1.0003817011957674 [13]: # discount factors for tenors 1x4 FRA, 3x6 FRA and 4x7 FRA for j in (4,6,7): E3Data.loc[j,'Discount']=E3Data.loc[j-3,'Discount']/(1+q_i[j]*(E3Data['Days␣ , →2'][j]-E3Data['Days 2'][j-3])/36000).copy() E3Data[4:8] [13]: Name Quote Measured date From date To date Days 1 Days 2 \ 4 EUR 1X4 FRA -0.270 2020-04-14 2020-04-16 2020-08-17 123 125 5 EUR 2X5 FRA -0.299 2020-04-14 2020-04-16 2020-09-16 153 155 6 EUR 3X6 FRA -0.322 2020-04-14 2020-04-16 2020-10-16 183 185 7 EUR 4X7 FRA -0.347 2020-04-14 2020-04-16 2020-11-16 214 216

Discount Spot 4 1.001065 NaN 5 NaN NaN 6 1.001465 NaN 7 1.001944 NaN [14]: # get discount factors for tenor 2x5 FRA, the 63 days is time different between␣ , →two months from today #(2020-04-14) and today (2020-06-16) E3Data.loc[5,'Discount']=E2m/(1+q_i[5]*(E3Data['Days 2'][5]-63)/36000).copy() E3Data[4:8] [14]: Name Quote Measured date From date To date Days 1 Days 2 \ 4 EUR 1X4 FRA -0.270 2020-04-14 2020-04-16 2020-08-17 123 125 5 EUR 2X5 FRA -0.299 2020-04-14 2020-04-16 2020-09-16 153 155 6 EUR 3X6 FRA -0.322 2020-04-14 2020-04-16 2020-10-16 183 185 7 EUR 4X7 FRA -0.347 2020-04-14 2020-04-16 2020-11-16 214 216

Discount Spot 4 1.001065 NaN 5 1.001274 NaN 6 1.001465 NaN 7 1.001944 NaN [15]: # zero rates for FRAs E3Data.loc[4:8,'Spot']=-100*np.log(E3Data.loc[4:8,'Discount'])/(E3Data.loc[4: , →8,'Days 2']/365).copy() E3Data[4:8] [15]: Name Quote Measured date From date To date Days 1 Days 2 \ 4 EUR 1X4 FRA -0.270 2020-04-14 2020-04-16 2020-08-17 123 125 5 EUR 2X5 FRA -0.299 2020-04-14 2020-04-16 2020-09-16 153 155

4 6 EUR 3X6 FRA -0.322 2020-04-14 2020-04-16 2020-10-16 183 185 7 EUR 4X7 FRA -0.347 2020-04-14 2020-04-16 2020-11-16 214 216

Discount Spot 4 1.001065 -0.310794 5 1.001274 -0.299880 6 1.001465 -0.288863 7 1.001944 -0.328143

0.3 Swaps

OIS 3M 3M P (0, Tj) P (0, Tj 1) P (0, Tj) = · − 3M n n 1 P (0,Tj 1) OIS 3M i OIS i − OIS P (0, Tj) + s ∑ = ∆jP (0, Tj) ∑ =− 3M 1 P (0, Tj) i · j 1 − j 1 P (0,Tj) − {( ) } [16]: # since we have to use OIS discounting so we import OIS discount factors here EoData2 = pd.read_csv('EoData.csv', sep=';') EoData2[7:12] [16]: Name Quote From date To date Days DeltaT Discount \ 7 EUR 1Y OIS -0.5077 2020-04-14 2021-04-16 367 88.0 1.005204 8 EUR 15M OIS -0.5169 2020-04-14 2021-07-16 458 91.0 1.006616 9 EUR 18M OIS -0.5217 2020-04-14 2021-10-18 552 94.0 1.008051 10 EUR 21M OIS -0.5242 2020-04-14 2022-01-17 643 91.0 1.009427 11 EUR 2Y OIS -0.5232 2020-04-14 2022-04-18 734 91.0 1.010745

Forward Spot 7 -0.539000 -0.516235 8 -0.554874 -0.525521 9 -0.545029 -0.530199 10 -0.539280 -0.532597 11 -0.516170 -0.531492 [17]: E3Data[8:13] [17]: Name Quote Measured date From date To date Days 1 \ 8 EUR 1Y IRS 3M -0.347 2020-04-14 2020-04-16 2021-04-16 365 9 EUR 15M IRS 3M -0.363 2020-04-14 2020-04-16 2021-07-16 456 10 EUR 18M IRS 3M -0.373 2020-04-14 2020-04-16 2021-10-18 550 11 EUR 21M IRS 3M -0.377 2020-04-14 2020-04-16 2022-01-17 641 12 EUR 2Y IRS 3M -0.380 2020-04-14 2020-04-16 2022-04-18 732

Days 2 Discount Spot 8 367 NaN NaN 9 458 NaN NaN 10 552 NaN NaN 11 643 NaN NaN 12 734 NaN NaN

5 [18]: E3Data['Days 2'].shift(1).head() [18]: 0 NaN 1 9.0 2 34.0 3 63.0 4 93.0 Name: Days 2, dtype: float64 [19]: E3Data['DeltaT'] = E3Data['Days 2'] - E3Data['Days 2'].shift(1) # get delta␣ , →time=time difference E3Data[0:8] [19]: Name Quote Measured date From date To date Days 1 Days 2 \ 0 EURIBOR S/W -0.518 2020-04-14 2020-04-16 2020-04-23 7 9 1 EURIBOR 1M -0.404 2020-04-14 2020-04-16 2020-05-18 32 34 2 EURIBOR 2M 0.000 2020-04-14 2020-04-16 2020-06-16 61 63 3 EURIBOR 3M -0.248 2020-04-14 2020-04-16 2020-07-16 91 93 4 EUR 1X4 FRA -0.270 2020-04-14 2020-04-16 2020-08-17 123 125 5 EUR 2X5 FRA -0.299 2020-04-14 2020-04-16 2020-09-16 153 155 6 EUR 3X6 FRA -0.322 2020-04-14 2020-04-16 2020-10-16 183 185 7 EUR 4X7 FRA -0.347 2020-04-14 2020-04-16 2020-11-16 214 216

Discount Spot DeltaT 0 1.000130 -0.525228 NaN 1 1.000382 -0.409689 25.0 2 1.000509 -0.294933 29.0 3 1.000641 -0.251525 30.0 4 1.001065 -0.310794 32.0 5 1.001274 -0.299880 30.0 6 1.001465 -0.288863 30.0 7 1.001944 -0.328143 31.0 [20]: E3Data.loc[0,'DeltaT']=9 # assign from today (2020-04-14) to the first tenor's␣ , →maturity E3Data.head() [20]: Name Quote Measured date From date To date Days 1 Days 2 \ 0 EURIBOR S/W -0.518 2020-04-14 2020-04-16 2020-04-23 7 9 1 EURIBOR 1M -0.404 2020-04-14 2020-04-16 2020-05-18 32 34 2 EURIBOR 2M 0.000 2020-04-14 2020-04-16 2020-06-16 61 63 3 EURIBOR 3M -0.248 2020-04-14 2020-04-16 2020-07-16 91 93 4 EUR 1X4 FRA -0.270 2020-04-14 2020-04-16 2020-08-17 123 125

Discount Spot DeltaT 0 1.000130 -0.525228 9.0 1 1.000382 -0.409689 25.0 2 1.000509 -0.294933 29.0 3 1.000641 -0.251525 30.0

6 4 1.001065 -0.310794 32.0 [21]: EoData2[:12] [21]: Name Quote From date To date Days DeltaT Discount \ 0 EONIA O/N -0.4510 2020-04-14 2020-04-15 1 NaN 1.000013 1 EUR 1W OIS -0.4583 2020-04-14 2020-04-23 9 8.0 1.000127 2 EUR 1M OIS -0.4606 2020-04-14 2020-05-18 34 25.0 1.000448 3 EUR 2M OIS -0.4645 2020-04-14 2020-06-16 63 29.0 1.000826 4 EUR 3M OIS -0.4696 2020-04-14 2020-07-16 93 30.0 1.001227 5 EUR 6M OIS -0.4841 2020-04-14 2020-10-16 185 92.0 1.002504 6 EUR 9M OIS -0.4978 2020-04-14 2021-01-18 279 94.0 1.003880 7 EUR 1Y OIS -0.5077 2020-04-14 2021-04-16 367 88.0 1.005204 8 EUR 15M OIS -0.5169 2020-04-14 2021-07-16 458 91.0 1.006616 9 EUR 18M OIS -0.5217 2020-04-14 2021-10-18 552 94.0 1.008051 10 EUR 21M OIS -0.5242 2020-04-14 2022-01-17 643 91.0 1.009427 11 EUR 2Y OIS -0.5232 2020-04-14 2022-04-18 734 91.0 1.010745

Forward Spot 0 -0.451000 -0.457267 1 -0.515581 -0.515493 2 -0.461428 -0.480507 3 -0.469070 -0.478283 4 -0.480303 -0.481118 5 -0.498732 -0.493483 6 -0.524703 -0.506579 7 -0.539000 -0.516235 8 -0.554874 -0.525521 9 -0.545029 -0.530199 10 -0.539280 -0.532597 11 -0.516170 -0.531492 [22]: # since we need OIS discounting for 4M, 5M and 7M, therefore we have to use␣ , →interpolation to get them D4m=EoData2.loc[4,'Discount']+(EoData2.loc[4,'Discount']-EoData2. , →loc[3,'Discount'])/EoData2.loc[4,'DeltaT']*(125-EoData2.loc[4,'Days']) D5m=EoData2.loc[4,'Discount']+(EoData2.loc[4,'Discount']-EoData2. , →loc[3,'Discount'])/(EoData2.loc[4,'Days']-EoData2. , →loc[3,'Days'])*(155-EoData2.loc[4,'Days']) D7m=EoData2.loc[5,'Discount']+(EoData2.loc[6,'Discount']-EoData2. , →loc[5,'Discount'])/(EoData2.loc[6,'Days']-EoData2. , →loc[5,'Days'])*(216-EoData2.loc[5,'Days']) print(D4m,D5m,D7m)

1.0016540728309071 1.002054816303217 1.0029579237358437

[23]: EoData2.loc[45]=['4m',0,0,0,125,0,D4m,0,0] # adding a row EoData2.loc[46]=['5m',0,0,0,155,0,D5m,0,0]

7 EoData2.loc[47]=['7m',0,0,0,216,0,D7m,0,0] EoData3= EoData2.reindex([0,1,2,3,4,45,46,5, 47, 6, 7, 8, 9, 10, 11, 12, 13,␣ , →14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44]) EoData3.head(10) [23]: Name Quote From date To date Days DeltaT Discount \ 0 EONIA O/N -0.4510 2020-04-14 2020-04-15 1 NaN 1.000013 1 EUR 1W OIS -0.4583 2020-04-14 2020-04-23 9 8.0 1.000127 2 EUR 1M OIS -0.4606 2020-04-14 2020-05-18 34 25.0 1.000448 3 EUR 2M OIS -0.4645 2020-04-14 2020-06-16 63 29.0 1.000826 4 EUR 3M OIS -0.4696 2020-04-14 2020-07-16 93 30.0 1.001227 45 4m 0.0000 0 0 125 0.0 1.001654 46 5m 0.0000 0 0 155 0.0 1.002055 5 EUR 6M OIS -0.4841 2020-04-14 2020-10-16 185 92.0 1.002504 47 7m 0.0000 0 0 216 0.0 1.002958 6 EUR 9M OIS -0.4978 2020-04-14 2021-01-18 279 94.0 1.003880

Forward Spot 0 -0.451000 -0.457267 1 -0.515581 -0.515493 2 -0.461428 -0.480507 3 -0.469070 -0.478283 4 -0.480303 -0.481118 45 0.000000 0.000000 46 0.000000 0.000000 5 -0.498732 -0.493483 47 0.000000 0.000000 6 -0.524703 -0.506579 [24]: EoData3.index=range(48) EoData3 [24]: Name Quote From date To date Days DeltaT Discount \ 0 EONIA O/N -0.4510 2020-04-14 2020-04-15 1 NaN 1.000013 1 EUR 1W OIS -0.4583 2020-04-14 2020-04-23 9 8.0 1.000127 2 EUR 1M OIS -0.4606 2020-04-14 2020-05-18 34 25.0 1.000448 3 EUR 2M OIS -0.4645 2020-04-14 2020-06-16 63 29.0 1.000826 4 EUR 3M OIS -0.4696 2020-04-14 2020-07-16 93 30.0 1.001227 5 4m 0.0000 0 0 125 0.0 1.001654 6 5m 0.0000 0 0 155 0.0 1.002055 7 EUR 6M OIS -0.4841 2020-04-14 2020-10-16 185 92.0 1.002504 8 7m 0.0000 0 0 216 0.0 1.002958 9 EUR 9M OIS -0.4978 2020-04-14 2021-01-18 279 94.0 1.003880 10 EUR 1Y OIS -0.5077 2020-04-14 2021-04-16 367 88.0 1.005204 11 EUR 15M OIS -0.5169 2020-04-14 2021-07-16 458 91.0 1.006616 12 EUR 18M OIS -0.5217 2020-04-14 2021-10-18 552 94.0 1.008051

8 13 EUR 21M OIS -0.5242 2020-04-14 2022-01-17 643 91.0 1.009427 14 EUR 2Y OIS -0.5232 2020-04-14 2022-04-18 734 91.0 1.010745 15 EUR 27M OIS -0.5261 2020-04-14 2022-07-18 825 91.0 1.012151 16 EUR 30M OIS -0.5245 2020-04-14 2022-10-17 916 91.0 1.013458 17 EUR 2Y 9M OIS -0.5205 2020-04-14 2023-01-16 1007 91.0 1.014690 18 EUR 3Y OIS -0.5149 2020-04-14 2023-04-17 1098 91.0 1.015854 19 EUR 3Y 3M OIS -0.5095 2020-04-14 2023-07-17 1189 91.0 1.016998 20 EUR 3Y 6M OIS -0.5037 2020-04-14 2023-10-16 1280 91.0 1.018101 21 EUR 3Y 9M OIS -0.4973 2020-04-14 2024-01-16 1372 92.0 1.019166 22 EUR 4Y OIS -0.4902 2020-04-14 2024-04-16 1463 91.0 1.020157 23 EUR 4Y 3M OIS -0.4823 2020-04-14 2024-07-16 1554 91.0 1.021077 24 EUR 4Y 6M OIS -0.4736 2020-04-14 2024-10-16 1646 92.0 1.021934 25 EUR 4Y 9M OIS -0.4645 2020-04-14 2025-01-16 1738 92.0 1.022727 26 EUR 5Y OIS -0.4549 2020-04-14 2025-04-16 1828 90.0 1.023421 27 EUR 5Y 3M OIS -0.4453 2020-04-14 2025-07-16 1919 91.0 1.024080 28 EUR 5Y 6M OIS -0.4353 2020-04-14 2025-10-16 2011 92.0 1.024679 29 EUR 5Y 9M OIS -0.4251 2020-04-14 2026-01-16 2103 92.0 1.025215 30 EUR 6Y OIS -0.4147 2020-04-14 2026-04-16 2193 90.0 1.025662 31 EUR 6Y 3M OIS -0.4042 2020-04-14 2026-07-16 2284 91.0 1.026061 32 EUR 6Y 6M OIS -0.3934 2020-04-14 2026-10-16 2376 92.0 1.026396 33 EUR 6Y 9M OIS -0.3821 2020-04-14 2027-01-18 2470 94.0 1.026663 34 EUR 7Y OIS -0.3714 2020-04-14 2027-04-16 2558 88.0 1.026849 35 EUR 7Y 3M OIS -0.3602 2020-04-14 2027-07-16 2649 91.0 1.026974 36 EUR 7Y 6M OIS -0.3486 2020-04-14 2027-10-18 2743 94.0 1.027041 37 EUR 7Y 9M OIS -0.3373 2020-04-14 2028-01-17 2834 91.0 1.027040 38 EUR 8Y OIS -0.3258 2020-04-14 2028-04-17 2925 91.0 1.026965 39 EUR 8Y 6M OIS -0.3032 2020-04-14 2028-10-16 3107 182.0 1.026669 40 EUR 9Y OIS -0.2806 2020-04-14 2029-04-16 3289 182.0 1.026138 41 EUR 9Y 6M OIS -0.2584 2020-04-14 2029-10-16 3472 183.0 1.025418 42 EUR 10Y OIS -0.2361 2020-04-14 2030-04-16 3654 182.0 1.024448 43 EUR 12Y OIS -0.1477 2020-04-14 2032-04-16 4385 731.0 1.018350 44 EUR 15Y OIS -0.0444 2020-04-14 2035-04-16 5480 1095.0 1.006885 45 EUR 20Y OIS 0.0225 2020-04-14 2040-04-16 7307 1827.0 0.995392 46 EUR 25Y OIS 0.0071 2020-04-14 2045-04-17 9134 1827.0 0.998195 47 EUR 30Y OIS -0.0368 2020-04-14 2050-04-18 10961 1827.0 1.011320

Forward Spot 0 -0.451000 -0.457267 1 -0.515581 -0.515493 2 -0.461428 -0.480507 3 -0.469070 -0.478283 4 -0.480303 -0.481118 5 0.000000 0.000000 6 0.000000 0.000000 7 -0.498732 -0.493483 8 0.000000 0.000000 9 -0.524703 -0.506579

9 10 -0.539000 -0.516235 11 -0.554874 -0.525521 12 -0.545029 -0.530199 13 -0.539280 -0.532597 14 -0.516170 -0.531492 15 -0.549359 -0.534347 16 -0.510088 -0.532674 17 -0.480517 -0.528591 18 -0.453393 -0.522902 19 -0.444863 -0.517422 20 -0.428557 -0.511544 21 -0.409053 -0.505067 22 -0.384136 -0.497888 23 -0.356507 -0.489909 24 -0.328097 -0.481127 25 -0.303326 -0.471945 26 -0.271392 -0.462261 27 -0.254455 -0.452578 28 -0.228894 -0.442493 29 -0.204476 -0.432208 30 -0.174216 -0.421721 31 -0.153800 -0.411132 32 -0.128049 -0.400241 33 -0.099389 -0.388844 34 -0.074042 -0.378050 35 -0.048452 -0.366751 36 -0.024813 -0.355045 37 0.000202 -0.343638 38 0.029191 -0.332026 39 0.056964 -0.309194 40 0.102424 -0.286340 41 0.138143 -0.263868 42 0.187239 -0.241274 43 0.294883 -0.151360 44 0.374366 -0.045700 45 0.227500 0.023069 46 -0.055324 0.007219 47 -0.255717 -0.037482 [25]: f=E3Data.loc[0,'DeltaT']/360*EoData3.loc[1,'Discount'].copy() l=(1/E3Data.loc[0,'Discount']-1)*EoData3.loc[1,'Discount'].copy() for n in range(1,8): f+=E3Data.loc[n,'DeltaT']/360*EoData3.loc[n+1,'Discount'].copy() l+=(E3Data.loc[n-1,'Discount']/E3Data.loc[n,'Discount']-1)*EoData3. , →loc[n+1,'Discount'].copy() print(f,l)

0.6009846827917024 -0.001945000863919427

10 [26]: # since 3-m Euribor has less tenors after 2 years than Eonia, we can delete␣ , →unuseful tenors for calculation # convience. EoData4=EoData3.drop(EoData3. , →index[[15,16,17,19,20,21,23,24,25,27,28,29,31,32,33,35,36,37,39,41]]) EoData4.index=range(28) EoData4 [26]: Name Quote From date To date Days DeltaT Discount \ 0 EONIA O/N -0.4510 2020-04-14 2020-04-15 1 NaN 1.000013 1 EUR 1W OIS -0.4583 2020-04-14 2020-04-23 9 8.0 1.000127 2 EUR 1M OIS -0.4606 2020-04-14 2020-05-18 34 25.0 1.000448 3 EUR 2M OIS -0.4645 2020-04-14 2020-06-16 63 29.0 1.000826 4 EUR 3M OIS -0.4696 2020-04-14 2020-07-16 93 30.0 1.001227 5 4m 0.0000 0 0 125 0.0 1.001654 6 5m 0.0000 0 0 155 0.0 1.002055 7 EUR 6M OIS -0.4841 2020-04-14 2020-10-16 185 92.0 1.002504 8 7m 0.0000 0 0 216 0.0 1.002958 9 EUR 9M OIS -0.4978 2020-04-14 2021-01-18 279 94.0 1.003880 10 EUR 1Y OIS -0.5077 2020-04-14 2021-04-16 367 88.0 1.005204 11 EUR 15M OIS -0.5169 2020-04-14 2021-07-16 458 91.0 1.006616 12 EUR 18M OIS -0.5217 2020-04-14 2021-10-18 552 94.0 1.008051 13 EUR 21M OIS -0.5242 2020-04-14 2022-01-17 643 91.0 1.009427 14 EUR 2Y OIS -0.5232 2020-04-14 2022-04-18 734 91.0 1.010745 15 EUR 3Y OIS -0.5149 2020-04-14 2023-04-17 1098 91.0 1.015854 16 EUR 4Y OIS -0.4902 2020-04-14 2024-04-16 1463 91.0 1.020157 17 EUR 5Y OIS -0.4549 2020-04-14 2025-04-16 1828 90.0 1.023421 18 EUR 6Y OIS -0.4147 2020-04-14 2026-04-16 2193 90.0 1.025662 19 EUR 7Y OIS -0.3714 2020-04-14 2027-04-16 2558 88.0 1.026849 20 EUR 8Y OIS -0.3258 2020-04-14 2028-04-17 2925 91.0 1.026965 21 EUR 9Y OIS -0.2806 2020-04-14 2029-04-16 3289 182.0 1.026138 22 EUR 10Y OIS -0.2361 2020-04-14 2030-04-16 3654 182.0 1.024448 23 EUR 12Y OIS -0.1477 2020-04-14 2032-04-16 4385 731.0 1.018350 24 EUR 15Y OIS -0.0444 2020-04-14 2035-04-16 5480 1095.0 1.006885 25 EUR 20Y OIS 0.0225 2020-04-14 2040-04-16 7307 1827.0 0.995392 26 EUR 25Y OIS 0.0071 2020-04-14 2045-04-17 9134 1827.0 0.998195 27 EUR 30Y OIS -0.0368 2020-04-14 2050-04-18 10961 1827.0 1.011320

Forward Spot 0 -0.451000 -0.457267 1 -0.515581 -0.515493 2 -0.461428 -0.480507 3 -0.469070 -0.478283 4 -0.480303 -0.481118 5 0.000000 0.000000 6 0.000000 0.000000 7 -0.498732 -0.493483

11 8 0.000000 0.000000 9 -0.524703 -0.506579 10 -0.539000 -0.516235 11 -0.554874 -0.525521 12 -0.545029 -0.530199 13 -0.539280 -0.532597 14 -0.516170 -0.531492 15 -0.453393 -0.522902 16 -0.384136 -0.497888 17 -0.271392 -0.462261 18 -0.174216 -0.421721 19 -0.074042 -0.378050 20 0.029191 -0.332026 21 0.102424 -0.286340 22 0.187239 -0.241274 23 0.294883 -0.151360 24 0.374366 -0.045700 25 0.227500 0.023069 26 -0.055324 0.007219 27 -0.255717 -0.037482 [27]: # get discount factors for tenor 1Y f+=E3Data.loc[8,'DeltaT']/360*EoData4.loc[10,'Discount'].copy() print(f) E3Data.loc[8,'Discount']=EoData4.loc[10,'Discount']*E3Data.loc[7,'Discount']/ , →(EoData4.loc[10,'Discount']+ q_i[8]/100*f-l).copy() f+=E3Data.loc[9,'DeltaT']/360*EoData4.loc[11,'Discount'].copy() l+=(E3Data.loc[7,'Discount']/E3Data.loc[8,'Discount']-1)*EoData4. , →loc[10,'Discount'].copy() print(f,l)

E3Data.head(13)

1.0226119695964553 1.2770621263344144 -0.003548463534499651

[27]: Name Quote Measured date From date To date Days 1 \ 0 EURIBOR S/W -0.518 2020-04-14 2020-04-16 2020-04-23 7 1 EURIBOR 1M -0.404 2020-04-14 2020-04-16 2020-05-18 32 2 EURIBOR 2M 0.000 2020-04-14 2020-04-16 2020-06-16 61 3 EURIBOR 3M -0.248 2020-04-14 2020-04-16 2020-07-16 91 4 EUR 1X4 FRA -0.270 2020-04-14 2020-04-16 2020-08-17 123 5 EUR 2X5 FRA -0.299 2020-04-14 2020-04-16 2020-09-16 153 6 EUR 3X6 FRA -0.322 2020-04-14 2020-04-16 2020-10-16 183 7 EUR 4X7 FRA -0.347 2020-04-14 2020-04-16 2020-11-16 214 8 EUR 1Y IRS 3M -0.347 2020-04-14 2020-04-16 2021-04-16 365 9 EUR 15M IRS 3M -0.363 2020-04-14 2020-04-16 2021-07-16 456

12 10 EUR 18M IRS 3M -0.373 2020-04-14 2020-04-16 2021-10-18 550 11 EUR 21M IRS 3M -0.377 2020-04-14 2020-04-16 2022-01-17 641 12 EUR 2Y IRS 3M -0.380 2020-04-14 2020-04-16 2022-04-18 732

Days 2 Discount Spot DeltaT 0 9 1.000130 -0.525228 9.0 1 34 1.000382 -0.409689 25.0 2 63 1.000509 -0.294933 29.0 3 93 1.000641 -0.251525 30.0 4 125 1.001065 -0.310794 32.0 5 155 1.001274 -0.299880 30.0 6 185 1.001465 -0.288863 30.0 7 216 1.001944 -0.328143 31.0 8 367 1.003545 NaN 151.0 9 458 NaN NaN 91.0 10 552 NaN NaN 94.0 11 643 NaN NaN 91.0 12 734 NaN NaN 91.0 [28]: # get discount factor for tenors 15M, 18M, 21M and 2Y for m in range(9,13): E3Data.loc[m,'Discount']=EoData4.loc[m+2,'Discount']*E3Data. , →loc[m-1,'Discount']/(EoData4.loc[m+2,'Discount']+ q_i[m]/100*f-l).copy() f+=E3Data.loc[m+1,'DeltaT']/360*EoData4.loc[m+3,'Discount'].copy() l+=(E3Data.loc[m-1,'Discount']/E3Data.loc[m,'Discount']-1)*EoData4. , →loc[m+2,'Discount'].copy() print(f,l) E3Data[:13]

1.5402753364891955 -0.004635735518594056 1.7954359550361305 -0.005745227005104716 2.050929932851229 -0.006768793550486265 3.078071614590645 -0.0077935337448346844

[28]: Name Quote Measured date From date To date Days 1 \ 0 EURIBOR S/W -0.518 2020-04-14 2020-04-16 2020-04-23 7 1 EURIBOR 1M -0.404 2020-04-14 2020-04-16 2020-05-18 32 2 EURIBOR 2M 0.000 2020-04-14 2020-04-16 2020-06-16 61 3 EURIBOR 3M -0.248 2020-04-14 2020-04-16 2020-07-16 91 4 EUR 1X4 FRA -0.270 2020-04-14 2020-04-16 2020-08-17 123 5 EUR 2X5 FRA -0.299 2020-04-14 2020-04-16 2020-09-16 153 6 EUR 3X6 FRA -0.322 2020-04-14 2020-04-16 2020-10-16 183 7 EUR 4X7 FRA -0.347 2020-04-14 2020-04-16 2020-11-16 214 8 EUR 1Y IRS 3M -0.347 2020-04-14 2020-04-16 2021-04-16 365 9 EUR 15M IRS 3M -0.363 2020-04-14 2020-04-16 2021-07-16 456 10 EUR 18M IRS 3M -0.373 2020-04-14 2020-04-16 2021-10-18 550 11 EUR 21M IRS 3M -0.377 2020-04-14 2020-04-16 2022-01-17 641

13 12 EUR 2Y IRS 3M -0.380 2020-04-14 2020-04-16 2022-04-18 732

Days 2 Discount Spot DeltaT 0 9 1.000130 -0.525228 9.0 1 34 1.000382 -0.409689 25.0 2 63 1.000509 -0.294933 29.0 3 93 1.000641 -0.251525 30.0 4 125 1.001065 -0.310794 32.0 5 155 1.001274 -0.299880 30.0 6 185 1.001465 -0.288863 30.0 7 216 1.001944 -0.328143 31.0 8 367 1.003545 NaN 151.0 9 458 1.004630 NaN 91.0 10 552 1.005737 NaN 94.0 11 643 1.006758 NaN 91.0 12 734 1.007779 NaN 91.0 [29]: # using extrapolation to calculate discount factors for tenors 11Y, 40Y and 50Y␣ , →for Eonia D11y=(EoData4.loc[23,'Discount']-EoData4.loc[22,'Discount'])/(EoData4. , →loc[23,'Days']-EoData4.loc[22,'Days'])*(E3Data.loc[21,'Days 2']-EoData4. , →loc[22,'Days'])+EoData4.loc[22,'Discount'].copy() D40y=(EoData4.loc[27,'Discount']-EoData4.loc[26,'Discount'])/(EoData4. , →loc[27,'Days']-EoData4.loc[26,'Days'])*(E3Data.loc[27,'Days 2']-EoData4. , →loc[27,'Days'])+EoData4.loc[27,'Discount'].copy() D50y=(EoData4.loc[27,'Discount']-EoData4.loc[26,'Discount'])/(EoData4. , →loc[27,'Days']-EoData4.loc[26,'Days'])*(E3Data.loc[28,'Days 2']-EoData4. , →loc[27,'Days'])+EoData4.loc[27,'Discount'].copy()

print(D11y,D40y,D50y)

1.0214032379992057 1.0375471147548474 1.063781806147311

[30]: EoData4.loc[28]=['11Y',0,0,0,14612,0,D11y,0,0] EoData4.loc[29]=['40Y',0,0,0,14612,0,D40y,0,0] EoData4.loc[30]=['50Y',0,0,0,18264,0,D50y,0,0] EoData4.index [30]: Int64Index([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30], dtype='int64') [31]: EoData4= EoData4.reindex([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,␣ , →13, 14, 15, 16, 17, 18, 19, 20, 21, 22,28, 23, 24, 25, 26, 27, 29, 30]) EoData4.index=range(31) EoData4

14 [31]: Name Quote From date To date Days DeltaT Discount \ 0 EONIA O/N -0.4510 2020-04-14 2020-04-15 1 NaN 1.000013 1 EUR 1W OIS -0.4583 2020-04-14 2020-04-23 9 8.0 1.000127 2 EUR 1M OIS -0.4606 2020-04-14 2020-05-18 34 25.0 1.000448 3 EUR 2M OIS -0.4645 2020-04-14 2020-06-16 63 29.0 1.000826 4 EUR 3M OIS -0.4696 2020-04-14 2020-07-16 93 30.0 1.001227 5 4m 0.0000 0 0 125 0.0 1.001654 6 5m 0.0000 0 0 155 0.0 1.002055 7 EUR 6M OIS -0.4841 2020-04-14 2020-10-16 185 92.0 1.002504 8 7m 0.0000 0 0 216 0.0 1.002958 9 EUR 9M OIS -0.4978 2020-04-14 2021-01-18 279 94.0 1.003880 10 EUR 1Y OIS -0.5077 2020-04-14 2021-04-16 367 88.0 1.005204 11 EUR 15M OIS -0.5169 2020-04-14 2021-07-16 458 91.0 1.006616 12 EUR 18M OIS -0.5217 2020-04-14 2021-10-18 552 94.0 1.008051 13 EUR 21M OIS -0.5242 2020-04-14 2022-01-17 643 91.0 1.009427 14 EUR 2Y OIS -0.5232 2020-04-14 2022-04-18 734 91.0 1.010745 15 EUR 3Y OIS -0.5149 2020-04-14 2023-04-17 1098 91.0 1.015854 16 EUR 4Y OIS -0.4902 2020-04-14 2024-04-16 1463 91.0 1.020157 17 EUR 5Y OIS -0.4549 2020-04-14 2025-04-16 1828 90.0 1.023421 18 EUR 6Y OIS -0.4147 2020-04-14 2026-04-16 2193 90.0 1.025662 19 EUR 7Y OIS -0.3714 2020-04-14 2027-04-16 2558 88.0 1.026849 20 EUR 8Y OIS -0.3258 2020-04-14 2028-04-17 2925 91.0 1.026965 21 EUR 9Y OIS -0.2806 2020-04-14 2029-04-16 3289 182.0 1.026138 22 EUR 10Y OIS -0.2361 2020-04-14 2030-04-16 3654 182.0 1.024448 23 11Y 0.0000 0 0 14612 0.0 1.021403 24 EUR 12Y OIS -0.1477 2020-04-14 2032-04-16 4385 731.0 1.018350 25 EUR 15Y OIS -0.0444 2020-04-14 2035-04-16 5480 1095.0 1.006885 26 EUR 20Y OIS 0.0225 2020-04-14 2040-04-16 7307 1827.0 0.995392 27 EUR 25Y OIS 0.0071 2020-04-14 2045-04-17 9134 1827.0 0.998195 28 EUR 30Y OIS -0.0368 2020-04-14 2050-04-18 10961 1827.0 1.011320 29 40Y 0.0000 0 0 14612 0.0 1.037547 30 50Y 0.0000 0 0 18264 0.0 1.063782

Forward Spot 0 -0.451000 -0.457267 1 -0.515581 -0.515493 2 -0.461428 -0.480507 3 -0.469070 -0.478283 4 -0.480303 -0.481118 5 0.000000 0.000000 6 0.000000 0.000000 7 -0.498732 -0.493483 8 0.000000 0.000000 9 -0.524703 -0.506579 10 -0.539000 -0.516235 11 -0.554874 -0.525521 12 -0.545029 -0.530199

15 13 -0.539280 -0.532597 14 -0.516170 -0.531492 15 -0.453393 -0.522902 16 -0.384136 -0.497888 17 -0.271392 -0.462261 18 -0.174216 -0.421721 19 -0.074042 -0.378050 20 0.029191 -0.332026 21 0.102424 -0.286340 22 0.187239 -0.241274 23 0.000000 0.000000 24 0.294883 -0.151360 25 0.374366 -0.045700 26 0.227500 0.023069 27 -0.055324 0.007219 28 -0.255717 -0.037482 29 0.000000 0.000000 30 0.000000 0.000000 [32]: # discount factors for tenors from 3Y to 40Y for u in range(13,28): E3Data.loc[u,'Discount']=EoData4.loc[u+2,'Discount']*E3Data. , →loc[u-1,'Discount']/(EoData4.loc[u+2,'Discount']+ q_i[u]/100*f-l).copy() f+=E3Data.loc[u+1,'DeltaT']/360*EoData4.loc[u+3,'Discount'].copy() l+=(E3Data.loc[u-1,'Discount']/E3Data.loc[u,'Discount']-1)*EoData4. , →loc[u+2,'Discount'].copy() [33]: # get discount factor for tenor 50Y E3Data.loc[28,'Discount']=EoData4.loc[30,'Discount']*E3Data.loc[27,'Discount']/ , →(EoData4.loc[30,'Discount']+ q_i[28]/100*f-l).copy() E3Data [33]: Name Quote Measured date From date To date Days 1 \ 0 EURIBOR S/W -0.518 2020-04-14 2020-04-16 2020-04-23 7 1 EURIBOR 1M -0.404 2020-04-14 2020-04-16 2020-05-18 32 2 EURIBOR 2M 0.000 2020-04-14 2020-04-16 2020-06-16 61 3 EURIBOR 3M -0.248 2020-04-14 2020-04-16 2020-07-16 91 4 EUR 1X4 FRA -0.270 2020-04-14 2020-04-16 2020-08-17 123 5 EUR 2X5 FRA -0.299 2020-04-14 2020-04-16 2020-09-16 153 6 EUR 3X6 FRA -0.322 2020-04-14 2020-04-16 2020-10-16 183 7 EUR 4X7 FRA -0.347 2020-04-14 2020-04-16 2020-11-16 214 8 EUR 1Y IRS 3M -0.347 2020-04-14 2020-04-16 2021-04-16 365 9 EUR 15M IRS 3M -0.363 2020-04-14 2020-04-16 2021-07-16 456 10 EUR 18M IRS 3M -0.373 2020-04-14 2020-04-16 2021-10-18 550 11 EUR 21M IRS 3M -0.377 2020-04-14 2020-04-16 2022-01-17 641 12 EUR 2Y IRS 3M -0.380 2020-04-14 2020-04-16 2022-04-18 732

16 13 EUR 3Y IRS 3M -0.371 2020-04-14 2020-04-16 2023-04-17 1096 14 EUR 4Y IRS 3M -0.346 2020-04-14 2020-04-16 2024-04-16 1461 15 EUR 5Y IRS 3M -0.310 2020-04-14 2020-04-16 2025-04-16 1826 16 EUR 6Y IRS 3M -0.271 2020-04-14 2020-04-16 2026-04-16 2191 17 EUR 7Y IRS 3M -0.229 2020-04-14 2020-04-16 2027-04-16 2556 18 EUR 8Y IRS 3M -0.184 2020-04-14 2020-04-16 2028-04-17 2923 19 EUR 9Y IRS 3M -0.139 2020-04-14 2020-04-16 2029-04-16 3287 20 EUR 10Y IRS 3M -0.094 2020-04-14 2020-04-16 2030-04-16 3652 21 EUR 11Y IRS 3M -0.050 2020-04-14 2020-04-16 2031-04-16 4017 22 EUR 12Y IRS 3M -0.008 2020-04-14 2020-04-16 2032-04-16 4383 23 EUR 15Y IRS 3M 0.094 2020-04-14 2020-04-16 2035-04-16 5478 24 EUR 20Y IRS 3M 0.157 2020-04-14 2020-04-16 2040-04-16 7305 25 EUR 25Y IRS 3M 0.140 2020-04-14 2020-04-16 2045-04-17 9132 26 EUR 30Y IRS 3M 0.092 2020-04-14 2020-04-16 2050-04-18 10959 27 EUR 40Y IRS 3M 0.016 2020-04-14 2020-04-16 2060-04-16 14610 28 EUR 50Y IRS 3M -0.053 2020-04-14 2020-04-16 2070-04-16 18262

Days 2 Discount Spot DeltaT 0 9 1.000130 -0.525228 9.0 1 34 1.000382 -0.409689 25.0 2 63 1.000509 -0.294933 29.0 3 93 1.000641 -0.251525 30.0 4 125 1.001065 -0.310794 32.0 5 155 1.001274 -0.299880 30.0 6 185 1.001465 -0.288863 30.0 7 216 1.001944 -0.328143 31.0 8 367 1.003545 NaN 151.0 9 458 1.004630 NaN 91.0 10 552 1.005737 NaN 94.0 11 643 1.006758 NaN 91.0 12 734 1.007779 NaN 91.0 13 1098 1.011389 NaN 364.0 14 1463 1.014182 NaN 365.0 15 1828 1.015906 NaN 365.0 16 2193 1.016708 NaN 365.0 17 2558 1.016495 NaN 365.0 18 2925 1.015182 NaN 367.0 19 3289 1.012929 NaN 364.0 20 3654 1.009759 NaN 365.0 21 4019 1.005783 NaN 365.0 22 4385 1.001162 NaN 366.0 23 5480 0.985933 NaN 1095.0 24 7307 0.968718 NaN 1827.0 25 9134 0.965237 NaN 1827.0 26 10961 0.972515 NaN 1827.0 27 14612 0.993267 NaN 3651.0 28 18264 1.026250 NaN 3652.0

17 [34]: E3Data['Forward']=0.0 # creat column 'Forward' for forward rates [35]: # get the forward rate for tenor Euribor S/W E3Data.loc[0,'Forward']=(1-E3Data.loc[0,'Discount'])/E3Data. , →loc[0,'Discount']*36000/E3Data.loc[0,'Days 2'].copy() E3Data.head() [35]: Name Quote Measured date From date To date Days 1 Days 2 \ 0 EURIBOR S/W -0.518 2020-04-14 2020-04-16 2020-04-23 7 9 1 EURIBOR 1M -0.404 2020-04-14 2020-04-16 2020-05-18 32 34 2 EURIBOR 2M 0.000 2020-04-14 2020-04-16 2020-06-16 61 63 3 EURIBOR 3M -0.248 2020-04-14 2020-04-16 2020-07-16 91 93 4 EUR 1X4 FRA -0.270 2020-04-14 2020-04-16 2020-08-17 123 125

Discount Spot DeltaT Forward 0 1.000130 -0.525228 9.0 -0.518 1 1.000382 -0.409689 25.0 0.000 2 1.000509 -0.294933 29.0 0.000 3 1.000641 -0.251525 30.0 0.000 4 1.001065 -0.310794 32.0 0.000 [36]: # get all other the forward rates for z in range(1,29): E3Data.loc[z,'Forward']=(E3Data.loc[z-1,'Discount']-E3Data. , →loc[z,'Discount'])/E3Data.loc[z,'Discount']*36000/E3Data.loc[z,'DeltaT']. , →copy() E3Data.Forward[:29] [36]: 0 -0.518000 1 -0.363007 2 -0.158183 3 -0.158162 4 -0.476325 5 -0.250898 6 -0.228740 7 -0.554715 8 -0.380303 9 -0.427303 10 -0.421518 11 -0.401146 12 -0.401082 13 -0.353029 14 -0.271602 15 -0.167323 16 -0.077856 17 0.020712 18 0.126810 19 0.220031 20 0.309589

18 21 0.389928 22 0.454050 23 0.507818 24 0.350151 25 0.071074 26 -0.147466 27 -0.206007 28 -0.316814 Name: Forward, dtype: float64 [37]: # get all other spot rates E3Data.loc[8:,'Spot']=-100*np.log(E3Data.loc[8:,'Discount'])/(E3Data.loc[8: , →,'Days 2']/365).copy() E3Data [37]: Name Quote Measured date From date To date Days 1 \ 0 EURIBOR S/W -0.518 2020-04-14 2020-04-16 2020-04-23 7 1 EURIBOR 1M -0.404 2020-04-14 2020-04-16 2020-05-18 32 2 EURIBOR 2M 0.000 2020-04-14 2020-04-16 2020-06-16 61 3 EURIBOR 3M -0.248 2020-04-14 2020-04-16 2020-07-16 91 4 EUR 1X4 FRA -0.270 2020-04-14 2020-04-16 2020-08-17 123 5 EUR 2X5 FRA -0.299 2020-04-14 2020-04-16 2020-09-16 153 6 EUR 3X6 FRA -0.322 2020-04-14 2020-04-16 2020-10-16 183 7 EUR 4X7 FRA -0.347 2020-04-14 2020-04-16 2020-11-16 214 8 EUR 1Y IRS 3M -0.347 2020-04-14 2020-04-16 2021-04-16 365 9 EUR 15M IRS 3M -0.363 2020-04-14 2020-04-16 2021-07-16 456 10 EUR 18M IRS 3M -0.373 2020-04-14 2020-04-16 2021-10-18 550 11 EUR 21M IRS 3M -0.377 2020-04-14 2020-04-16 2022-01-17 641 12 EUR 2Y IRS 3M -0.380 2020-04-14 2020-04-16 2022-04-18 732 13 EUR 3Y IRS 3M -0.371 2020-04-14 2020-04-16 2023-04-17 1096 14 EUR 4Y IRS 3M -0.346 2020-04-14 2020-04-16 2024-04-16 1461 15 EUR 5Y IRS 3M -0.310 2020-04-14 2020-04-16 2025-04-16 1826 16 EUR 6Y IRS 3M -0.271 2020-04-14 2020-04-16 2026-04-16 2191 17 EUR 7Y IRS 3M -0.229 2020-04-14 2020-04-16 2027-04-16 2556 18 EUR 8Y IRS 3M -0.184 2020-04-14 2020-04-16 2028-04-17 2923 19 EUR 9Y IRS 3M -0.139 2020-04-14 2020-04-16 2029-04-16 3287 20 EUR 10Y IRS 3M -0.094 2020-04-14 2020-04-16 2030-04-16 3652 21 EUR 11Y IRS 3M -0.050 2020-04-14 2020-04-16 2031-04-16 4017 22 EUR 12Y IRS 3M -0.008 2020-04-14 2020-04-16 2032-04-16 4383 23 EUR 15Y IRS 3M 0.094 2020-04-14 2020-04-16 2035-04-16 5478 24 EUR 20Y IRS 3M 0.157 2020-04-14 2020-04-16 2040-04-16 7305 25 EUR 25Y IRS 3M 0.140 2020-04-14 2020-04-16 2045-04-17 9132 26 EUR 30Y IRS 3M 0.092 2020-04-14 2020-04-16 2050-04-18 10959 27 EUR 40Y IRS 3M 0.016 2020-04-14 2020-04-16 2060-04-16 14610 28 EUR 50Y IRS 3M -0.053 2020-04-14 2020-04-16 2070-04-16 18262

Days 2 Discount Spot DeltaT Forward 0 9 1.000130 -0.525228 9.0 -0.518000

19 1 34 1.000382 -0.409689 25.0 -0.363007 2 63 1.000509 -0.294933 29.0 -0.158183 3 93 1.000641 -0.251525 30.0 -0.158162 4 125 1.001065 -0.310794 32.0 -0.476325 5 155 1.001274 -0.299880 30.0 -0.250898 6 185 1.001465 -0.288863 30.0 -0.228740 7 216 1.001944 -0.328143 31.0 -0.554715 8 367 1.003545 -0.351904 151.0 -0.380303 9 458 1.004630 -0.368110 91.0 -0.427303 10 552 1.005737 -0.378242 94.0 -0.421518 11 643 1.006758 -0.382301 91.0 -0.401146 12 734 1.007779 -0.385346 91.0 -0.401082 13 1098 1.011389 -0.376470 364.0 -0.353029 14 1463 1.014182 -0.351343 365.0 -0.271602 15 1828 1.015906 -0.315092 365.0 -0.167323 16 2193 1.016708 -0.275792 365.0 -0.077856 17 2558 1.016495 -0.233443 365.0 0.020712 18 2925 1.015182 -0.188032 367.0 0.126810 19 3289 1.012929 -0.142560 364.0 0.220031 20 3654 1.009759 -0.097014 365.0 0.309589 21 4019 1.005783 -0.052370 365.0 0.389928 22 4385 1.001162 -0.009663 366.0 0.454050 23 5480 0.985933 0.094362 1095.0 0.507818 24 7307 0.968718 0.158754 1827.0 0.350151 25 9134 0.965237 0.141388 1827.0 0.071074 26 10961 0.972515 0.092806 1827.0 -0.147466 27 14612 0.993267 0.016876 3651.0 -0.206007 28 18264 1.026250 -0.051782 3652.0 -0.316814 [ ]: E3Data.to_excel(r'/Users/pennyandersson/Desktop/Analytical Finance/thesis/my␣ , →work/E3Data.xlsx', sheet_name='E3Data', index = False) [38]: import matplotlib.pyplot as plt %matplotlib inline [39]: E3Data['TTM']=E3Data['Days 2']/360 # time to maturity [40]: plt.figure(figsize=(15, 6)) [40]:

[41]: plt.plot(E3Data['TTM'], E3Data['Discount'], 'o-y', lw=1.5) plt.grid(True) plt.xlabel('Term(years)') plt.ylabel('Discount factor')

20 plt.title('The bootstrapped discount curve for 3-months Euribor at 2020-04-14␣ , →(Table 3.4)') [41]: Text(0.5, 1.0, 'The bootstrapped discount curve for 3-months Euribor at 2020-04-14 (Table 3.4)')

[42]: plt.plot(E3Data['TTM'], E3Data['Spot'], 'o-c', label= 'Spot rate', lw=1.5) plt.plot(E3Data['TTM'], E3Data['Forward'],'o-m', label= 'Forward rate', lw=1.5) plt.grid(True) plt.xlabel('Term(years)') plt.ylabel('Yield') plt.title('The bootstrapped yield curve for 3-months Euribor at 2020-04-14␣ , →(Table 3.4)') plt.legend() [42]:

21 [ ]:

22 Appendix C

The calculation of 6-months Euribor with the bootstrapping method in Python

104 E6Data

August 31, 2020

[1]: import pandas as pd import math import numpy as np [2]: E6Data = pd.read_csv('E6Data per 2020-04-14.csv', sep=';') #import 6-months␣ , →Euribor rates index E6Data.tail() [2]: Name Quote Measured date From date To date 38 EUR 27Y IRS 0.135 2020-04-14 2020-04-16 2047-04-16 39 EUR 28Y IRS 0.124 2020-04-14 2020-04-16 2048-04-16 40 EUR 29Y IRS 0.113 2020-04-14 2020-04-16 2049-04-16 41 EUR 30Y IRS 0.102 2020-04-14 2020-04-16 2050-04-18 42 EUR 40Y IRS 0.020 2020-04-14 2020-04-16 2060-04-16 [3]: print(E6Data.index) # There are total 43 rows/tenors

RangeIndex(start=0, stop=43, step=1)

[4]: import datetime as dt import calendar [5]: start_date=dt.datetime(2020, 4, 14) [6]: d0=dt.datetime(2020,10,16) d1=dt.datetime(2020,11,16) d2=dt.datetime(2020,12,16) d3=dt.datetime(2021,1,18) d4=dt.datetime(2021,2,16) d5=dt.datetime(2021,3,16) d6=dt.datetime(2021,4,16) d7=dt.datetime(2021,5,17) d8=dt.datetime(2021,6,16) d9=dt.datetime(2021,7,16) d10=dt.datetime(2021,8,16) d11=dt.datetime(2021,9,16) d12=dt.datetime(2021,10,18) d13=dt.datetime(2022,4,18) d14=dt.datetime(2023,4,17)

1 d15=dt.datetime(2024,4,16) d16=dt.datetime(2025,4,16) d17=dt.datetime(2026,4,16) d18=dt.datetime(2027,4,16) d19=dt.datetime(2028,4,17) d20=dt.datetime(2029,4,16) d21=dt.datetime(2030,4,16) d22=dt.datetime(2031,4,16) d23=dt.datetime(2032,4,16) d24=dt.datetime(2033,4,18) d25=dt.datetime(2034,4,17) d26=dt.datetime(2035,4,16) d27=dt.datetime(2036,4,16) d28=dt.datetime(2037,4,16) d29=dt.datetime(2038,4,16) d30=dt.datetime(2039,4,18) d31=dt.datetime(2040,4,16) d32=dt.datetime(2041,4,16) d33=dt.datetime(2042,4,16) d34=dt.datetime(2043,4,16) d35=dt.datetime(2044,4,18) d36=dt.datetime(2045,4,17) d37=dt.datetime(2046,4,16) d38=dt.datetime(2047,4,16) d39=dt.datetime(2048,4,16) d40=dt.datetime(2049,4,16) d41=dt.datetime(2050,4,18) d42=dt.datetime(2060,4,16) [7]: end_date=np. , →array([d0,d1,d2,d3,d4,d5,d6,d7,d8,d9,d10,d11,d12,d13,d14,d15,d16,d17,d18,d19,d20,d21,d22,d23,d24, ␣ , →d25,d26,d27,d28,d29,d30,d31,d32,d33,d34,d35,d36,d37,d38,d39,d40,d41,d42]) [8]: # get time to the maturity ttm = np.zeros(len(end_date)) for ind in range(len(end_date)): ttm[ind] = ((end_date[ind]-start_date).days) ttm [8]: array([ 185., 216., 246., 279., 308., 336., 367., 398., 428., 458., 489., 520., 552., 734., 1098., 1463., 1828., 2193., 2558., 2925., 3289., 3654., 4019., 4385., 4752., 5116., 5480., 5846., 6211., 6576., 6943., 7307., 7672., 8037., 8402., 8770., 9134., 9498., 9863., 10229., 10594., 10961., 14612.]) [9]: E6Data['TTM']=ttm E6Data.head()

2 [9]: Name Quote Measured date From date To date TTM 0 EURIBOR 6M -0.195 2020-04-14 2020-04-16 2020-10-16 185.0 1 EUR 1X7 FRA -0.223 2020-04-14 2020-04-16 2020-11-16 216.0 2 EUR 2X8 FRA -0.250 2020-04-14 2020-04-16 2020-12-16 246.0 3 EUR 3X9 FRA -0.269 2020-04-14 2020-04-16 2021-01-18 279.0 4 EUR 4X10 FRA -0.288 2020-04-14 2020-04-16 2021-02-16 308.0

0.1 Deposits We have discount factors and zero rates as:

1 Di = i = 6M di { } 1 + qi 360

ln Di Zi = 100 i = 6M − di { } 365

where qi is quoted rates in our case it is Euribor rates or swap rates and di is number of days. [10]: q_i=E6Data['Quote'] print(q_i)

0 -0.195 1 -0.223 2 -0.250 3 -0.269 4 -0.288 5 -0.307 6 -0.316 7 -0.326 8 -0.335 9 -0.337 10 -0.338 11 -0.339 12 -0.336 13 -0.294 14 -0.287 15 -0.262 16 -0.227 17 -0.191 18 -0.154 19 -0.114 20 -0.075 21 -0.036 22 0.003 23 0.040 24 0.075 25 0.105 26 0.130

3 27 0.150 28 0.164 29 0.174 30 0.180 31 0.182 32 0.181 33 0.178 34 0.172 35 0.165 36 0.156 37 0.146 38 0.135 39 0.124 40 0.113 41 0.102 42 0.020 Name: Quote, dtype: float64

[11]: # get the discount factor for deposit E6Data.loc[0,'Discount']=1/(1+q_i[0]*E6Data.loc[0,'TTM']/36000).copy() E6Data.head() [11]: Name Quote Measured date From date To date TTM Discount 0 EURIBOR 6M -0.195 2020-04-14 2020-04-16 2020-10-16 185.0 1.001003 1 EUR 1X7 FRA -0.223 2020-04-14 2020-04-16 2020-11-16 216.0 NaN 2 EUR 2X8 FRA -0.250 2020-04-14 2020-04-16 2020-12-16 246.0 NaN 3 EUR 3X9 FRA -0.269 2020-04-14 2020-04-16 2021-01-18 279.0 NaN 4 EUR 4X10 FRA -0.288 2020-04-14 2020-04-16 2021-02-16 308.0 NaN [12]: # get spot rate for deposit E6Data.loc[0,'Spot']=-100*np.log(E6Data.loc[0,'Discount'])/(E6Data.loc[0,'TTM']/ , →365).copy() E6Data.head() [12]: Name Quote Measured date From date To date TTM Discount \ 0 EURIBOR 6M -0.195 2020-04-14 2020-04-16 2020-10-16 185.0 1.001003 1 EUR 1X7 FRA -0.223 2020-04-14 2020-04-16 2020-11-16 216.0 NaN 2 EUR 2X8 FRA -0.250 2020-04-14 2020-04-16 2020-12-16 246.0 NaN 3 EUR 3X9 FRA -0.269 2020-04-14 2020-04-16 2021-01-18 279.0 NaN 4 EUR 4X10 FRA -0.288 2020-04-14 2020-04-16 2021-02-16 308.0 NaN

Spot 0 -0.197807 1 NaN 2 NaN 3 NaN 4 NaN

4 0.2 FRAs We have discount factors and zero rates as:\

i 1 i DFRA− DFRA = i ; i = 1x7 FRA, 2x8 FRA, ... 11x17 FRA, 12x18 FRA i dFRA { } 1 + qFRA 360

i i ln (DFRA) ZFRA(T) = 100 i ; i = 1x7 FRA, 2x8 FRA, ... 11x17 FRA, 12x18 FRA − dFRA { } 365

[13]: E6Data[1:13] [13]: Name Quote Measured date From date To date TTM \ 1 EUR 1X7 FRA -0.223 2020-04-14 2020-04-16 2020-11-16 216.0 2 EUR 2X8 FRA -0.250 2020-04-14 2020-04-16 2020-12-16 246.0 3 EUR 3X9 FRA -0.269 2020-04-14 2020-04-16 2021-01-18 279.0 4 EUR 4X10 FRA -0.288 2020-04-14 2020-04-16 2021-02-16 308.0 5 EUR 5X11 FRA -0.307 2020-04-14 2020-04-16 2021-03-16 336.0 6 EUR 6X12 FRA -0.316 2020-04-14 2020-04-16 2021-04-16 367.0 7 EUR 7X13 FRA -0.326 2020-04-14 2020-04-16 2021-05-17 398.0 8 EUR 8X14 FRA -0.335 2020-04-14 2020-04-16 2021-06-16 428.0 9 EUR 9X15 FRA -0.337 2020-04-14 2020-04-16 2021-07-16 458.0 10 EUR 10X16 FRA -0.338 2020-04-14 2020-04-16 2021-08-16 489.0 11 EUR 11X17 FRA -0.339 2020-04-14 2020-04-16 2021-09-16 520.0 12 EUR 12X18 FRA -0.336 2020-04-14 2020-04-16 2021-10-18 552.0

Discount Spot 1 NaN NaN 2 NaN NaN 3 NaN NaN 4 NaN NaN 5 NaN NaN 6 NaN NaN 7 NaN NaN 8 NaN NaN 9 NaN NaN 10 NaN NaN 11 NaN NaN 12 NaN NaN [14]: # since 6-month Euribor pays every half year, so we have to use interpolation␣ , →to get some unknown discount factors # we need, such as discount factors for 1m,2m,3m,4m and 5m D1m=1+(E6Data.loc[0,'Discount']-1)/(E6Data.loc[0,'TTM']-0)*(34-0) D2m=1+(E6Data.loc[0,'Discount']-1)/(E6Data.loc[0,'TTM']-0)*(63-0) D3m=1+(E6Data.loc[0,'Discount']-1)/(E6Data.loc[0,'TTM']-0)*(93-0) D4m=1+(E6Data.loc[0,'Discount']-1)/(E6Data.loc[0,'TTM']-0)*(125-0)

5 D5m=1+(E6Data.loc[0,'Discount']-1)/(E6Data.loc[0,'TTM']-0)*(155-0) print(D1m,D2m,D3m,D4m,D5m)

1.0001843514021342 1.0003415923039545 1.0005042553058376 1.0006777625078462 1.0008404255097294

[15]: # get discount factors for FRAs 1x7,2x8,3x9,4x10,5x11,6x12 E6Data.loc[1,'Discount']=D1m/(1+q_i[1]*(E6Data['TTM'][1]-34)/36000).copy() E6Data.loc[2,'Discount']=D2m/(1+q_i[2]*(E6Data['TTM'][2]-63)/36000).copy() E6Data.loc[3,'Discount']=D3m/(1+q_i[3]*(E6Data['TTM'][3]-93)/36000).copy() E6Data.loc[4,'Discount']=D4m/(1+q_i[4]*(E6Data['TTM'][4]-125)/36000).copy() E6Data.loc[5,'Discount']=D5m/(1+q_i[5]*(E6Data['TTM'][5]-155)/36000).copy() E6Data.loc[6,'Discount']=E6Data.loc[0,'Discount']/ , →(1+q_i[6]*(E6Data['TTM'][6]-E6Data['TTM'][0])/36000).copy()

E6Data[0:7] [15]: Name Quote Measured date From date To date TTM Discount \ 0 EURIBOR 6M -0.195 2020-04-14 2020-04-16 2020-10-16 185.0 1.001003 1 EUR 1X7 FRA -0.223 2020-04-14 2020-04-16 2020-11-16 216.0 1.001313 2 EUR 2X8 FRA -0.250 2020-04-14 2020-04-16 2020-12-16 246.0 1.001614 3 EUR 3X9 FRA -0.269 2020-04-14 2020-04-16 2021-01-18 279.0 1.001897 4 EUR 4X10 FRA -0.288 2020-04-14 2020-04-16 2021-02-16 308.0 1.002145 5 EUR 5X11 FRA -0.307 2020-04-14 2020-04-16 2021-03-16 336.0 1.002388 6 EUR 6X12 FRA -0.316 2020-04-14 2020-04-16 2021-04-16 367.0 1.002605

Spot 0 -0.197807 1 NaN 2 NaN 3 NaN 4 NaN 5 NaN 6 NaN [16]: # get discount factors for rest of FRAs for i in range(7,13): E6Data.loc[i,'Discount']=E6Data.loc[i-6,'Discount']/ , →(1+q_i[i]*(E6Data['TTM'][i]-E6Data['TTM'][i-6])/36000).copy()

E6Data[1:13] [16]: Name Quote Measured date From date To date TTM \ 1 EUR 1X7 FRA -0.223 2020-04-14 2020-04-16 2020-11-16 216.0 2 EUR 2X8 FRA -0.250 2020-04-14 2020-04-16 2020-12-16 246.0 3 EUR 3X9 FRA -0.269 2020-04-14 2020-04-16 2021-01-18 279.0 4 EUR 4X10 FRA -0.288 2020-04-14 2020-04-16 2021-02-16 308.0 5 EUR 5X11 FRA -0.307 2020-04-14 2020-04-16 2021-03-16 336.0 6 EUR 6X12 FRA -0.316 2020-04-14 2020-04-16 2021-04-16 367.0

6 7 EUR 7X13 FRA -0.326 2020-04-14 2020-04-16 2021-05-17 398.0 8 EUR 8X14 FRA -0.335 2020-04-14 2020-04-16 2021-06-16 428.0 9 EUR 9X15 FRA -0.337 2020-04-14 2020-04-16 2021-07-16 458.0 10 EUR 10X16 FRA -0.338 2020-04-14 2020-04-16 2021-08-16 489.0 11 EUR 11X17 FRA -0.339 2020-04-14 2020-04-16 2021-09-16 520.0 12 EUR 12X18 FRA -0.336 2020-04-14 2020-04-16 2021-10-18 552.0

Discount Spot 1 1.001313 NaN 2 1.001614 NaN 3 1.001897 NaN 4 1.002145 NaN 5 1.002388 NaN 6 1.002605 NaN 7 1.002966 NaN 8 1.003314 NaN 9 1.003578 NaN 10 1.003851 NaN 11 1.004127 NaN 12 1.004339 NaN [17]: # get zero rates for FRAs E6Data.loc[1:13,'Spot']=-100*np.log(E6Data.loc[1:13,'Discount'])/(E6Data.loc[1: , →13,'TTM']/365).copy() E6Data[1:13] [17]: Name Quote Measured date From date To date TTM \ 1 EUR 1X7 FRA -0.223 2020-04-14 2020-04-16 2020-11-16 216.0 2 EUR 2X8 FRA -0.250 2020-04-14 2020-04-16 2020-12-16 246.0 3 EUR 3X9 FRA -0.269 2020-04-14 2020-04-16 2021-01-18 279.0 4 EUR 4X10 FRA -0.288 2020-04-14 2020-04-16 2021-02-16 308.0 5 EUR 5X11 FRA -0.307 2020-04-14 2020-04-16 2021-03-16 336.0 6 EUR 6X12 FRA -0.316 2020-04-14 2020-04-16 2021-04-16 367.0 7 EUR 7X13 FRA -0.326 2020-04-14 2020-04-16 2021-05-17 398.0 8 EUR 8X14 FRA -0.335 2020-04-14 2020-04-16 2021-06-16 428.0 9 EUR 9X15 FRA -0.337 2020-04-14 2020-04-16 2021-07-16 458.0 10 EUR 10X16 FRA -0.338 2020-04-14 2020-04-16 2021-08-16 489.0 11 EUR 11X17 FRA -0.339 2020-04-14 2020-04-16 2021-09-16 520.0 12 EUR 12X18 FRA -0.336 2020-04-14 2020-04-16 2021-10-18 552.0

Discount Spot 1 1.001313 -0.221764 2 1.001614 -0.239353 3 1.001897 -0.247903 4 1.002145 -0.253913 5 1.002388 -0.259062 6 1.002605 -0.258724 7 1.002966 -0.271625

7 8 1.003314 -0.282126 9 1.003578 -0.284666 10 1.003851 -0.286883 11 1.004127 -0.289119 12 1.004339 -0.286285

0.3 Swaps

OIS 3M 3M P (0, Tj) P (0, Tj 1) P (0, Tj) = · − 3M n n 1 P (0,Tj 1) OIS 3M i OIS i − OIS P (0, Tj) + s ∑ = ∆jP (0, Tj) ∑ =− 3M 1 P (0, Tj) i · j 1 − j 1 P (0,Tj) − {( ) } [18]: # since we have to use OIS discounting so we import OIS discount factors here EoData2 = pd.read_csv('EoData.csv', sep=';') EoData2.head() [18]: Name Quote From date To date Days DeltaT Discount \ 0 EONIA O/N -0.4510 2020-04-14 2020-04-15 1 NaN 1.000013 1 EUR 1W OIS -0.4583 2020-04-14 2020-04-23 9 8.0 1.000127 2 EUR 1M OIS -0.4606 2020-04-14 2020-05-18 34 25.0 1.000448 3 EUR 2M OIS -0.4645 2020-04-14 2020-06-16 63 29.0 1.000826 4 EUR 3M OIS -0.4696 2020-04-14 2020-07-16 93 30.0 1.001227

Forward Spot 0 -0.451000 -0.457267 1 -0.515581 -0.515493 2 -0.461428 -0.480507 3 -0.469070 -0.478283 4 -0.480303 -0.481118 [19]: # delete some OIS tenors which we don't need EoData3=EoData2.drop(EoData2. , →index[[10,12,13,14,16,17,18,20,21,22,24,25,26,28,29,30,32,33,34,36,38]]) EoData3.index=range(24) EoData3 [19]: Name Quote From date To date Days DeltaT Discount \ 0 EONIA O/N -0.4510 2020-04-14 2020-04-15 1 NaN 1.000013 1 EUR 1W OIS -0.4583 2020-04-14 2020-04-23 9 8.0 1.000127 2 EUR 1M OIS -0.4606 2020-04-14 2020-05-18 34 25.0 1.000448 3 EUR 2M OIS -0.4645 2020-04-14 2020-06-16 63 29.0 1.000826 4 EUR 3M OIS -0.4696 2020-04-14 2020-07-16 93 30.0 1.001227 5 EUR 6M OIS -0.4841 2020-04-14 2020-10-16 185 92.0 1.002504 6 EUR 9M OIS -0.4978 2020-04-14 2021-01-18 279 94.0 1.003880 7 EUR 1Y OIS -0.5077 2020-04-14 2021-04-16 367 88.0 1.005204 8 EUR 15M OIS -0.5169 2020-04-14 2021-07-16 458 91.0 1.006616 9 EUR 18M OIS -0.5217 2020-04-14 2021-10-18 552 94.0 1.008051 10 EUR 2Y OIS -0.5232 2020-04-14 2022-04-18 734 91.0 1.010745

8 11 EUR 3Y OIS -0.5149 2020-04-14 2023-04-17 1098 91.0 1.015854 12 EUR 4Y OIS -0.4902 2020-04-14 2024-04-16 1463 91.0 1.020157 13 EUR 5Y OIS -0.4549 2020-04-14 2025-04-16 1828 90.0 1.023421 14 EUR 6Y OIS -0.4147 2020-04-14 2026-04-16 2193 90.0 1.025662 15 EUR 7Y OIS -0.3714 2020-04-14 2027-04-16 2558 88.0 1.026849 16 EUR 8Y OIS -0.3258 2020-04-14 2028-04-17 2925 91.0 1.026965 17 EUR 9Y OIS -0.2806 2020-04-14 2029-04-16 3289 182.0 1.026138 18 EUR 10Y OIS -0.2361 2020-04-14 2030-04-16 3654 182.0 1.024448 19 EUR 12Y OIS -0.1477 2020-04-14 2032-04-16 4385 731.0 1.018350 20 EUR 15Y OIS -0.0444 2020-04-14 2035-04-16 5480 1095.0 1.006885 21 EUR 20Y OIS 0.0225 2020-04-14 2040-04-16 7307 1827.0 0.995392 22 EUR 25Y OIS 0.0071 2020-04-14 2045-04-17 9134 1827.0 0.998195 23 EUR 30Y OIS -0.0368 2020-04-14 2050-04-18 10961 1827.0 1.011320

Forward Spot 0 -0.451000 -0.457267 1 -0.515581 -0.515493 2 -0.461428 -0.480507 3 -0.469070 -0.478283 4 -0.480303 -0.481118 5 -0.498732 -0.493483 6 -0.524703 -0.506579 7 -0.539000 -0.516235 8 -0.554874 -0.525521 9 -0.545029 -0.530199 10 -0.516170 -0.531492 11 -0.453393 -0.522902 12 -0.384136 -0.497888 13 -0.271392 -0.462261 14 -0.174216 -0.421721 15 -0.074042 -0.378050 16 0.029191 -0.332026 17 0.102424 -0.286340 18 0.187239 -0.241274 19 0.294883 -0.151360 20 0.374366 -0.045700 21 0.227500 0.023069 22 -0.055324 0.007219 23 -0.255717 -0.037482 [20]: # using interpolation method to get OIS discount factors for␣ , →7m,8m,10m,11m,13m,14m,16m,17m, 11Y,13Y,14Y,16Y, #17Y,18Y,19Y,21Y,22Y,23Y,24Y,26Y,27Y, 28Y,29Y and 40Y. since we need OIS␣ , →discounting of them D7m=EoData3.loc[5,'Discount']+(EoData3.loc[6,'Discount']-EoData3. , →loc[5,'Discount'])/(EoData3.loc[6,'Days']- EoData3.loc[5,'Days'])*(216-EoData3.loc[5,'Days'])

9 D8m=EoData3.loc[5,'Discount']+(EoData3.loc[6,'Discount']-EoData3. , →loc[5,'Discount'])/(EoData3.loc[6,'Days']- EoData3.loc[5,'Days'])*(246-EoData3.loc[5,'Days']) D10m=EoData3.loc[6,'Discount']+(EoData3.loc[6,'Discount']-EoData3. , →loc[5,'Discount'])/(EoData3.loc[6,'Days']- EoData3.loc[5,'Days'])*(308-EoData3.loc[6,'Days']) D11m=EoData3.loc[7,'Discount']-(EoData3.loc[7,'Discount']-EoData3. , →loc[6,'Discount'])/(EoData3.loc[7,'Days']- EoData3.loc[6,'Days'])*(EoData3.loc[7,'Days']-336) D13m=EoData3.loc[7,'Discount']+(EoData3.loc[7,'Discount']-EoData3. , →loc[6,'Discount'])/(EoData3.loc[7,'Days']- EoData3.loc[6,'Days'])*(398-EoData3.loc[7,'Days']) D14m=EoData3.loc[8,'Discount']-(EoData3.loc[8,'Discount']-EoData3. , →loc[7,'Discount'])/(EoData3.loc[8,'Days']- EoData3.loc[7,'Days'])*(EoData3.loc[8,'Days']-428) D16m=EoData3.loc[8,'Discount']+(EoData3.loc[8,'Discount']-EoData3. , →loc[7,'Discount'])/(EoData3.loc[8,'Days']- EoData3.loc[7,'Days'])*(489-EoData3.loc[8,'Days']) D17m=EoData3.loc[9,'Discount']-(EoData3.loc[9,'Discount']-EoData3. , →loc[8,'Discount'])/(EoData3.loc[9,'Days']- EoData3.loc[8,'Days'])*(EoData3.loc[9,'Days']-520)

D11y=EoData3.loc[18,'Discount']+(EoData3.loc[19,'Discount']-EoData3. , →loc[18,'Discount'])/(EoData3.loc[19,'Days']- EoData3.loc[18,'Days'])*(4019-EoData3.loc[18,'Days']) D13y=EoData3.loc[19,'Discount']+(EoData3.loc[19,'Discount']-EoData3. , →loc[18,'Discount'])/(EoData3.loc[19,'Days']- EoData3.loc[18,'Days'])*(4752-EoData3.loc[19,'Days']) D14y=EoData3.loc[19,'Discount']+(EoData3.loc[19,'Discount']-EoData3. , →loc[18,'Discount'])/(EoData3.loc[19,'Days']- EoData3.loc[18,'Days'])*(5116-EoData3.loc[19,'Days']) D16y=EoData3.loc[20,'Discount']+(EoData3.loc[20,'Discount']-EoData3. , →loc[19,'Discount'])/(EoData3.loc[20,'Days']- EoData3.loc[19,'Days'])*(5846-EoData3.loc[20,'Days']) D17y=EoData3.loc[20,'Discount']+(EoData3.loc[20,'Discount']-EoData3. , →loc[19,'Discount'])/(EoData3.loc[20,'Days']- EoData3.loc[19,'Days'])*(6211-EoData3.loc[20,'Days']) D18y=EoData3.loc[20,'Discount']+(EoData3.loc[20,'Discount']-EoData3. , →loc[19,'Discount'])/(EoData3.loc[20,'Days']- EoData3.loc[19,'Days'])*(6576-EoData3.loc[20,'Days']) D19y=EoData3.loc[21,'Discount']-(EoData3.loc[21,'Discount']-EoData3. , →loc[20,'Discount'])/(EoData3.loc[21,'Days']- EoData3.loc[20,'Days'])*(EoData3.loc[21,'Days']-6943) D21y=EoData3.loc[21,'Discount']+(EoData3.loc[21,'Discount']-EoData3. , →loc[20,'Discount'])/(EoData3.loc[21,'Days']- EoData3.loc[20,'Days'])*(7672-EoData3.loc[21,'Days'])

10 [21]: D22y=EoData3.loc[21,'Discount']+(EoData3.loc[21,'Discount']-EoData3. , →loc[20,'Discount'])/(EoData3.loc[21,'Days']- EoData3.loc[20,'Days'])*(8037-EoData3.loc[21,'Days']) D23y=EoData3.loc[22,'Discount']-(EoData3.loc[22,'Discount']-EoData3. , →loc[21,'Discount'])/(EoData3.loc[22,'Days']- EoData3.loc[21,'Days'])*(EoData3.loc[22,'Days']-8402) D24y=EoData3.loc[22,'Discount']-(EoData3.loc[22,'Discount']-EoData3. , →loc[21,'Discount'])/(EoData3.loc[22,'Days']- EoData3.loc[21,'Days'])*(EoData3.loc[22,'Days']-8770) D26y=EoData3.loc[22,'Discount']+(EoData3.loc[22,'Discount']-EoData3. , →loc[21,'Discount'])/(EoData3.loc[22,'Days']- EoData3.loc[21,'Days'])*(9498-EoData3.loc[22,'Days']) D27y=EoData3.loc[22,'Discount']+(EoData3.loc[22,'Discount']-EoData3. , →loc[21,'Discount'])/(EoData3.loc[22,'Days']- EoData3.loc[21,'Days'])*(9863-EoData3.loc[22,'Days']) D28y=EoData3.loc[23,'Discount']-(EoData3.loc[23,'Discount']-EoData3. , →loc[22,'Discount'])/(EoData3.loc[23,'Days']- EoData3.loc[22,'Days'])*(EoData3.loc[23,'Days']-10229) D29y=EoData3.loc[23,'Discount']-(EoData3.loc[23,'Discount']-EoData3. , →loc[22,'Discount'])/(EoData3.loc[23,'Days']- EoData3.loc[22,'Days'])*(EoData3.loc[23,'Days']-10594) D40y=EoData3.loc[23,'Discount']+(EoData3.loc[23,'Discount']-EoData3. , →loc[22,'Discount'])/(EoData3.loc[23,'Days']- EoData3.loc[22,'Days'])*(14612-EoData3.loc[23,'Days']) [22]: # adding some rows in EoData3 EoData3.loc[24]=['11y',0,0,0,4019,0,D11y,0,0] EoData3.loc[25]=['13y',0,0,0,4752,0,D13y,0,0] EoData3.loc[26]=['14y',0,0,0,5116,0,D14y,0,0] EoData3.loc[27]=['16y',0,0,0,5846,0,D16y,0,0] EoData3.loc[28]=['17y',0,0,0,6211,0,D17y,0,0]

EoData3.loc[29]=['18y',0,0,0,6576,0,D18y,0,0] EoData3.loc[30]=['19y',0,0,0,6943,0,D19y,0,0] EoData3.loc[31]=['21y',0,0,0,7672,0,D21y,0,0] EoData3.loc[32]=['22y',0,0,0,8037,0,D22y,0,0] EoData3.loc[33]=['23y',0,0,0,8402,0,D23y,0,0]

EoData3.loc[34]=['24y',0,0,0,8770,0,D24y,0,0] EoData3.loc[35]=['26y',0,0,0,9498,0,D26y,0,0] EoData3.loc[36]=['27y',0,0,0,9863,0,D27y,0,0] EoData3.loc[37]=['28y',0,0,0,10229,0,D28y,0,0] EoData3.loc[38]=['29y',0,0,0,10594,0,D29y,0,0] EoData3.loc[39]=['40y',0,0,0,14612,0,D40y,0,0]

EoData3.loc[40]=['7m',0,0,0,216,0,D7m,0,0] EoData3.loc[41]=['8m',0,0,0,246,0,D8m,0,0]

11 EoData3.loc[42]=['10m',0,0,0,308,0,D10m,0,0] EoData3.loc[43]=['11m',0,0,0,336,0,D11m,0,0] EoData3.loc[44]=['13m',0,0,0,398,0,D13m,0,0] EoData3.loc[45]=['14m',0,0,0,428,0,D14m,0,0] EoData3.loc[46]=['16m',0,0,0,489,0,D16m,0,0] EoData3.loc[47]=['17m',0,0,0,520,0,D17m,0,0] [23]: # sort EoData's index EoData4= EoData3.reindex([0,1,2,3,4,5,40,41,6,42,43,7, 44,45, 8, 46,47, 9, 10,␣ , →11, 12, 13, 14, 15, 16, 17, 18,24, 19, 25,26,20, 27,28,29,30,21,31,32,33,34,22,35,36,37,38, 23,␣ , →39]) EoData4.index=range(48) EoData4 [23]: Name Quote From date To date Days DeltaT Discount \ 0 EONIA O/N -0.4510 2020-04-14 2020-04-15 1 NaN 1.000013 1 EUR 1W OIS -0.4583 2020-04-14 2020-04-23 9 8.0 1.000127 2 EUR 1M OIS -0.4606 2020-04-14 2020-05-18 34 25.0 1.000448 3 EUR 2M OIS -0.4645 2020-04-14 2020-06-16 63 29.0 1.000826 4 EUR 3M OIS -0.4696 2020-04-14 2020-07-16 93 30.0 1.001227 5 EUR 6M OIS -0.4841 2020-04-14 2020-10-16 185 92.0 1.002504 6 7m 0.0000 0 0 216 0.0 1.002958 7 8m 0.0000 0 0 246 0.0 1.003397 8 EUR 9M OIS -0.4978 2020-04-14 2021-01-18 279 94.0 1.003880 9 10m 0.0000 0 0 308 0.0 1.004304 10 11m 0.0000 0 0 336 0.0 1.004738 11 EUR 1Y OIS -0.5077 2020-04-14 2021-04-16 367 88.0 1.005204 12 13m 0.0000 0 0 398 0.0 1.005671 13 14m 0.0000 0 0 428 0.0 1.006151 14 EUR 15M OIS -0.5169 2020-04-14 2021-07-16 458 91.0 1.006616 15 16m 0.0000 0 0 489 0.0 1.007097 16 17m 0.0000 0 0 520 0.0 1.007562 17 EUR 18M OIS -0.5217 2020-04-14 2021-10-18 552 94.0 1.008051 18 EUR 2Y OIS -0.5232 2020-04-14 2022-04-18 734 91.0 1.010745 19 EUR 3Y OIS -0.5149 2020-04-14 2023-04-17 1098 91.0 1.015854 20 EUR 4Y OIS -0.4902 2020-04-14 2024-04-16 1463 91.0 1.020157 21 EUR 5Y OIS -0.4549 2020-04-14 2025-04-16 1828 90.0 1.023421 22 EUR 6Y OIS -0.4147 2020-04-14 2026-04-16 2193 90.0 1.025662 23 EUR 7Y OIS -0.3714 2020-04-14 2027-04-16 2558 88.0 1.026849 24 EUR 8Y OIS -0.3258 2020-04-14 2028-04-17 2925 91.0 1.026965 25 EUR 9Y OIS -0.2806 2020-04-14 2029-04-16 3289 182.0 1.026138 26 EUR 10Y OIS -0.2361 2020-04-14 2030-04-16 3654 182.0 1.024448 27 11y 0.0000 0 0 4019 0.0 1.021403 28 EUR 12Y OIS -0.1477 2020-04-14 2032-04-16 4385 731.0 1.018350 29 13y 0.0000 0 0 4752 0.0 1.015289 30 14y 0.0000 0 0 5116 0.0 1.012253 31 EUR 15Y OIS -0.0444 2020-04-14 2035-04-16 5480 1095.0 1.006885

12 32 16y 0.0000 0 0 5846 0.0 1.003053 33 17y 0.0000 0 0 6211 0.0 0.999231 34 18y 0.0000 0 0 6576 0.0 0.995409 35 19y 0.0000 0 0 6943 0.0 0.997682 36 EUR 20Y OIS 0.0225 2020-04-14 2040-04-16 7307 1827.0 0.995392 37 21y 0.0000 0 0 7672 0.0 0.993096 38 22y 0.0000 0 0 8037 0.0 0.990801 39 23y 0.0000 0 0 8402 0.0 0.997072 40 24y 0.0000 0 0 8770 0.0 0.997637 41 EUR 25Y OIS 0.0071 2020-04-14 2045-04-17 9134 1827.0 0.998195 42 26y 0.0000 0 0 9498 0.0 0.998753 43 27y 0.0000 0 0 9863 0.0 0.999313 44 28y 0.0000 0 0 10229 0.0 1.006061 45 29y 0.0000 0 0 10594 0.0 1.008683 46 EUR 30Y OIS -0.0368 2020-04-14 2050-04-18 10961 1827.0 1.011320 47 40y 0.0000 0 0 14612 0.0 1.037547

Forward Spot 0 -0.451000 -0.457267 1 -0.515581 -0.515493 2 -0.461428 -0.480507 3 -0.469070 -0.478283 4 -0.480303 -0.481118 5 -0.498732 -0.493483 6 0.000000 0.000000 7 0.000000 0.000000 8 -0.524703 -0.506579 9 0.000000 0.000000 10 0.000000 0.000000 11 -0.539000 -0.516235 12 0.000000 0.000000 13 0.000000 0.000000 14 -0.554874 -0.525521 15 0.000000 0.000000 16 0.000000 0.000000 17 -0.545029 -0.530199 18 -0.516170 -0.531492 19 -0.453393 -0.522902 20 -0.384136 -0.497888 21 -0.271392 -0.462261 22 -0.174216 -0.421721 23 -0.074042 -0.378050 24 0.029191 -0.332026 25 0.102424 -0.286340 26 0.187239 -0.241274 27 0.000000 0.000000 28 0.294883 -0.151360

13 29 0.000000 0.000000 30 0.000000 0.000000 31 0.374366 -0.045700 32 0.000000 0.000000 33 0.000000 0.000000 34 0.000000 0.000000 35 0.000000 0.000000 36 0.227500 0.023069 37 0.000000 0.000000 38 0.000000 0.000000 39 0.000000 0.000000 40 0.000000 0.000000 41 -0.055324 0.007219 42 0.000000 0.000000 43 0.000000 0.000000 44 0.000000 0.000000 45 0.000000 0.000000 46 -0.255717 -0.037482 47 0.000000 0.000000 [24]: E6Data['TTM'].shift(1).head() [24]: 0 NaN 1 185.0 2 216.0 3 246.0 4 279.0 Name: TTM, dtype: float64 [25]: E6Data['DeltaT'] = E6Data['TTM'] - E6Data['TTM'].shift(1) # get delta time=time␣ , →difference E6Data.head() [25]: Name Quote Measured date From date To date TTM Discount \ 0 EURIBOR 6M -0.195 2020-04-14 2020-04-16 2020-10-16 185.0 1.001003 1 EUR 1X7 FRA -0.223 2020-04-14 2020-04-16 2020-11-16 216.0 1.001313 2 EUR 2X8 FRA -0.250 2020-04-14 2020-04-16 2020-12-16 246.0 1.001614 3 EUR 3X9 FRA -0.269 2020-04-14 2020-04-16 2021-01-18 279.0 1.001897 4 EUR 4X10 FRA -0.288 2020-04-14 2020-04-16 2021-02-16 308.0 1.002145

Spot DeltaT 0 -0.197807 NaN 1 -0.221764 31.0 2 -0.239353 30.0 3 -0.247903 33.0 4 -0.253913 29.0 [26]: f=185/360*EoData4.loc[5,'Discount'].copy() l=(1/E6Data.loc[0,'Discount']-1)*EoData4.loc[5,'Discount'].copy()

14 for m in range(1,13): f+=E6Data.loc[m,'DeltaT']/360*EoData4.loc[m+5,'Discount'].copy() l+=(E6Data.loc[m-1,'Discount']/E6Data.loc[m,'Discount']-1)*EoData4. , →loc[m+5,'Discount'].copy() print(f,l)

1.5402071520507432 -0.004349106370997167

[27]: f+=E6Data.loc[13,'DeltaT']/360*EoData4.loc[18,'Discount'].copy() for n in range(13,42): E6Data.loc[n,'Discount']=EoData4.loc[n+5,'Discount']*E6Data. , →loc[n-1,'Discount']/(EoData4.loc[n+5,'Discount']+ q_i[n]/100*f-l).copy() f+=E6Data.loc[n+1,'DeltaT']/360*EoData4.loc[n+6,'Discount'].copy() l+=(E6Data.loc[n-1,'Discount']/E6Data.loc[n,'Discount']-1)*EoData4. , →loc[n+5,'Discount'].copy() [28]: E6Data.loc[42,'Discount']=EoData4.loc[47,'Discount']*E6Data.loc[41,'Discount']/ , →(EoData4.loc[47,'Discount']+ q_i[42]/100*f-l).copy() E6Data [28]: Name Quote Measured date From date To date TTM \ 0 EURIBOR 6M -0.195 2020-04-14 2020-04-16 2020-10-16 185.0 1 EUR 1X7 FRA -0.223 2020-04-14 2020-04-16 2020-11-16 216.0 2 EUR 2X8 FRA -0.250 2020-04-14 2020-04-16 2020-12-16 246.0 3 EUR 3X9 FRA -0.269 2020-04-14 2020-04-16 2021-01-18 279.0 4 EUR 4X10 FRA -0.288 2020-04-14 2020-04-16 2021-02-16 308.0 5 EUR 5X11 FRA -0.307 2020-04-14 2020-04-16 2021-03-16 336.0 6 EUR 6X12 FRA -0.316 2020-04-14 2020-04-16 2021-04-16 367.0 7 EUR 7X13 FRA -0.326 2020-04-14 2020-04-16 2021-05-17 398.0 8 EUR 8X14 FRA -0.335 2020-04-14 2020-04-16 2021-06-16 428.0 9 EUR 9X15 FRA -0.337 2020-04-14 2020-04-16 2021-07-16 458.0 10 EUR 10X16 FRA -0.338 2020-04-14 2020-04-16 2021-08-16 489.0 11 EUR 11X17 FRA -0.339 2020-04-14 2020-04-16 2021-09-16 520.0 12 EUR 12X18 FRA -0.336 2020-04-14 2020-04-16 2021-10-18 552.0 13 EUR 2Y IRS -0.294 2020-04-14 2020-04-16 2022-04-18 734.0 14 EUR 3Y IRS -0.287 2020-04-14 2020-04-16 2023-04-17 1098.0 15 EUR 4Y IRS -0.262 2020-04-14 2020-04-16 2024-04-16 1463.0 16 EUR 5Y IRS -0.227 2020-04-14 2020-04-16 2025-04-16 1828.0 17 EUR 6Y IRS -0.191 2020-04-14 2020-04-16 2026-04-16 2193.0 18 EUR 7Y IRS -0.154 2020-04-14 2020-04-16 2027-04-16 2558.0 19 EUR 8Y IRS -0.114 2020-04-14 2020-04-16 2028-04-17 2925.0 20 EUR 9Y IRS -0.075 2020-04-14 2020-04-16 2029-04-16 3289.0 21 EUR 10Y IRS -0.036 2020-04-14 2020-04-16 2030-04-16 3654.0 22 EUR 11Y IRS 0.003 2020-04-14 2020-04-16 2031-04-16 4019.0 23 EUR 12Y IRS 0.040 2020-04-14 2020-04-16 2032-04-16 4385.0 24 EUR 13Y IRS 0.075 2020-04-14 2020-04-16 2033-04-18 4752.0

15 25 EUR 14Y IRS 0.105 2020-04-14 2020-04-16 2034-04-17 5116.0 26 EUR 15Y IRS 0.130 2020-04-14 2020-04-16 2035-04-16 5480.0 27 EUR 16Y IRS 0.150 2020-04-14 2020-04-16 2036-04-16 5846.0 28 EUR 17Y IRS 0.164 2020-04-14 2020-04-16 2037-04-16 6211.0 29 EUR 18Y IRS 0.174 2020-04-14 2020-04-16 2038-04-16 6576.0 30 EUR 19Y IRS 0.180 2020-04-14 2020-04-16 2039-04-18 6943.0 31 EUR 20Y IRS 0.182 2020-04-14 2020-04-16 2040-04-16 7307.0 32 EUR 21Y IRS 0.181 2020-04-14 2020-04-16 2041-04-16 7672.0 33 EUR 22Y IRS 0.178 2020-04-14 2020-04-16 2042-04-16 8037.0 34 EUR 23Y IRS 0.172 2020-04-14 2020-04-16 2043-04-16 8402.0 35 EUR 24Y IRS 0.165 2020-04-14 2020-04-16 2044-04-18 8770.0 36 EUR 25Y IRS 0.156 2020-04-14 2020-04-16 2045-04-17 9134.0 37 EUR 26Y IRS 0.146 2020-04-14 2020-04-16 2046-04-16 9498.0 38 EUR 27Y IRS 0.135 2020-04-14 2020-04-16 2047-04-16 9863.0 39 EUR 28Y IRS 0.124 2020-04-14 2020-04-16 2048-04-16 10229.0 40 EUR 29Y IRS 0.113 2020-04-14 2020-04-16 2049-04-16 10594.0 41 EUR 30Y IRS 0.102 2020-04-14 2020-04-16 2050-04-18 10961.0 42 EUR 40Y IRS 0.020 2020-04-14 2020-04-16 2060-04-16 14612.0

Discount Spot DeltaT 0 1.001003 -0.197807 NaN 1 1.001313 -0.221764 31.0 2 1.001614 -0.239353 30.0 3 1.001897 -0.247903 33.0 4 1.002145 -0.253913 29.0 5 1.002388 -0.259062 28.0 6 1.002605 -0.258724 31.0 7 1.002966 -0.271625 31.0 8 1.003314 -0.282126 30.0 9 1.003578 -0.284666 30.0 10 1.003851 -0.286883 31.0 11 1.004127 -0.289119 31.0 12 1.004339 -0.286285 32.0 13 1.006012 NaN 182.0 14 1.008797 NaN 364.0 15 1.010720 NaN 365.0 16 1.011625 NaN 365.0 17 1.011755 NaN 365.0 18 1.011079 NaN 365.0 19 1.009409 NaN 367.0 20 1.007004 NaN 364.0 21 1.003811 NaN 365.0 22 0.999827 NaN 365.0 23 0.995304 NaN 366.0 24 0.990305 NaN 367.0 25 0.985328 NaN 364.0 26 0.980513 NaN 364.0

16 27 0.976008 NaN 366.0 28 0.972141 NaN 365.0 29 0.968725 NaN 365.0 30 0.965876 NaN 367.0 31 0.963724 NaN 364.0 32 0.962157 NaN 365.0 33 0.961051 NaN 365.0 34 0.960681 NaN 365.0 35 0.960650 NaN 368.0 36 0.961267 NaN 364.0 37 0.962315 NaN 364.0 38 0.963821 NaN 365.0 39 0.965522 NaN 366.0 40 0.967438 NaN 365.0 41 0.969560 NaN 367.0 42 0.991623 NaN 3651.0 [29]: E6Data.loc[0,'DeltaT']=185 [30]: # get the forward rate for tenor Euribor S/W E6Data.loc[0,'Forward']=(1-E6Data.loc[0,'Discount'])/E6Data. , →loc[0,'Discount']*36000/E6Data.loc[0,'DeltaT'].copy() E6Data.head() [30]: Name Quote Measured date From date To date TTM Discount \ 0 EURIBOR 6M -0.195 2020-04-14 2020-04-16 2020-10-16 185.0 1.001003 1 EUR 1X7 FRA -0.223 2020-04-14 2020-04-16 2020-11-16 216.0 1.001313 2 EUR 2X8 FRA -0.250 2020-04-14 2020-04-16 2020-12-16 246.0 1.001614 3 EUR 3X9 FRA -0.269 2020-04-14 2020-04-16 2021-01-18 279.0 1.001897 4 EUR 4X10 FRA -0.288 2020-04-14 2020-04-16 2021-02-16 308.0 1.002145

Spot DeltaT Forward 0 -0.197807 185.0 -0.195 1 -0.221764 31.0 NaN 2 -0.239353 30.0 NaN 3 -0.247903 33.0 NaN 4 -0.253913 29.0 NaN [31]: # get all other the forward rates for z in range(1,43): E6Data.loc[z,'Forward']=(E6Data.loc[z-1,'Discount']-E6Data. , →loc[z,'Discount'])/E6Data.loc[z,'Discount']*36000/E6Data.loc[z,'DeltaT']. , →copy() [32]: # get all other spot rates E6Data.loc[13:,'Spot']=-100*np.log(E6Data.loc[13:,'Discount'])/(E6Data.loc[13: , →,'TTM']/365).copy() E6Data

17 [32]: Name Quote Measured date From date To date TTM \ 0 EURIBOR 6M -0.195 2020-04-14 2020-04-16 2020-10-16 185.0 1 EUR 1X7 FRA -0.223 2020-04-14 2020-04-16 2020-11-16 216.0 2 EUR 2X8 FRA -0.250 2020-04-14 2020-04-16 2020-12-16 246.0 3 EUR 3X9 FRA -0.269 2020-04-14 2020-04-16 2021-01-18 279.0 4 EUR 4X10 FRA -0.288 2020-04-14 2020-04-16 2021-02-16 308.0 5 EUR 5X11 FRA -0.307 2020-04-14 2020-04-16 2021-03-16 336.0 6 EUR 6X12 FRA -0.316 2020-04-14 2020-04-16 2021-04-16 367.0 7 EUR 7X13 FRA -0.326 2020-04-14 2020-04-16 2021-05-17 398.0 8 EUR 8X14 FRA -0.335 2020-04-14 2020-04-16 2021-06-16 428.0 9 EUR 9X15 FRA -0.337 2020-04-14 2020-04-16 2021-07-16 458.0 10 EUR 10X16 FRA -0.338 2020-04-14 2020-04-16 2021-08-16 489.0 11 EUR 11X17 FRA -0.339 2020-04-14 2020-04-16 2021-09-16 520.0 12 EUR 12X18 FRA -0.336 2020-04-14 2020-04-16 2021-10-18 552.0 13 EUR 2Y IRS -0.294 2020-04-14 2020-04-16 2022-04-18 734.0 14 EUR 3Y IRS -0.287 2020-04-14 2020-04-16 2023-04-17 1098.0 15 EUR 4Y IRS -0.262 2020-04-14 2020-04-16 2024-04-16 1463.0 16 EUR 5Y IRS -0.227 2020-04-14 2020-04-16 2025-04-16 1828.0 17 EUR 6Y IRS -0.191 2020-04-14 2020-04-16 2026-04-16 2193.0 18 EUR 7Y IRS -0.154 2020-04-14 2020-04-16 2027-04-16 2558.0 19 EUR 8Y IRS -0.114 2020-04-14 2020-04-16 2028-04-17 2925.0 20 EUR 9Y IRS -0.075 2020-04-14 2020-04-16 2029-04-16 3289.0 21 EUR 10Y IRS -0.036 2020-04-14 2020-04-16 2030-04-16 3654.0 22 EUR 11Y IRS 0.003 2020-04-14 2020-04-16 2031-04-16 4019.0 23 EUR 12Y IRS 0.040 2020-04-14 2020-04-16 2032-04-16 4385.0 24 EUR 13Y IRS 0.075 2020-04-14 2020-04-16 2033-04-18 4752.0 25 EUR 14Y IRS 0.105 2020-04-14 2020-04-16 2034-04-17 5116.0 26 EUR 15Y IRS 0.130 2020-04-14 2020-04-16 2035-04-16 5480.0 27 EUR 16Y IRS 0.150 2020-04-14 2020-04-16 2036-04-16 5846.0 28 EUR 17Y IRS 0.164 2020-04-14 2020-04-16 2037-04-16 6211.0 29 EUR 18Y IRS 0.174 2020-04-14 2020-04-16 2038-04-16 6576.0 30 EUR 19Y IRS 0.180 2020-04-14 2020-04-16 2039-04-18 6943.0 31 EUR 20Y IRS 0.182 2020-04-14 2020-04-16 2040-04-16 7307.0 32 EUR 21Y IRS 0.181 2020-04-14 2020-04-16 2041-04-16 7672.0 33 EUR 22Y IRS 0.178 2020-04-14 2020-04-16 2042-04-16 8037.0 34 EUR 23Y IRS 0.172 2020-04-14 2020-04-16 2043-04-16 8402.0 35 EUR 24Y IRS 0.165 2020-04-14 2020-04-16 2044-04-18 8770.0 36 EUR 25Y IRS 0.156 2020-04-14 2020-04-16 2045-04-17 9134.0 37 EUR 26Y IRS 0.146 2020-04-14 2020-04-16 2046-04-16 9498.0 38 EUR 27Y IRS 0.135 2020-04-14 2020-04-16 2047-04-16 9863.0 39 EUR 28Y IRS 0.124 2020-04-14 2020-04-16 2048-04-16 10229.0 40 EUR 29Y IRS 0.113 2020-04-14 2020-04-16 2049-04-16 10594.0 41 EUR 30Y IRS 0.102 2020-04-14 2020-04-16 2050-04-18 10961.0 42 EUR 40Y IRS 0.020 2020-04-14 2020-04-16 2060-04-16 14612.0

Discount Spot DeltaT Forward 0 1.001003 -0.197807 185.0 -0.195000

18 1 1.001313 -0.221764 31.0 -0.359681 2 1.001614 -0.239353 30.0 -0.360925 3 1.001897 -0.247903 33.0 -0.307323 4 1.002145 -0.253913 29.0 -0.307423 5 1.002388 -0.259062 28.0 -0.311346 6 1.002605 -0.258724 31.0 -0.251538 7 1.002966 -0.271625 31.0 -0.418467 8 1.003314 -0.282126 30.0 -0.415599 9 1.003578 -0.284666 30.0 -0.316459 10 1.003851 -0.286883 31.0 -0.315210 11 1.004127 -0.289119 31.0 -0.319917 12 1.004339 -0.286285 32.0 -0.236918 13 1.006012 -0.298091 182.0 -0.329050 14 1.008797 -0.291164 364.0 -0.273021 15 1.010720 -0.266020 365.0 -0.187596 16 1.011625 -0.230783 365.0 -0.088278 17 1.011755 -0.194516 365.0 -0.012705 18 1.011079 -0.157216 365.0 0.065994 19 1.009409 -0.116863 367.0 0.162286 20 1.007004 -0.077460 364.0 0.236171 21 1.003811 -0.037993 365.0 0.313787 22 0.999827 0.001568 365.0 0.392946 23 0.995304 0.039183 366.0 0.447054 24 0.990305 0.074833 367.0 0.495169 25 0.985328 0.105454 364.0 0.499541 26 0.980513 0.131077 364.0 0.485670 27 0.976008 0.151624 366.0 0.454029 28 0.972141 0.166043 365.0 0.392312 29 0.968725 0.176362 365.0 0.347744 30 0.965876 0.182526 367.0 0.289396 31 0.963724 0.184577 364.0 0.220872 32 0.962157 0.183534 365.0 0.160573 33 0.961051 0.180426 365.0 0.113570 34 0.960681 0.174261 365.0 0.037989 35 0.960650 0.167079 368.0 0.003077 36 0.961267 0.157856 364.0 -0.063450 37 0.962315 0.147620 364.0 -0.107692 38 0.963821 0.136370 365.0 -0.154104 39 0.965522 0.125199 366.0 -0.173277 40 0.967438 0.114056 365.0 -0.195318 41 0.969560 0.102939 367.0 -0.214750 42 0.991623 0.021013 3651.0 -0.219386 [ ]: E6Data.to_excel(r'/Users/pennyandersson/Desktop/Analytical Finance/thesis/my␣ , →work/E6Data.xlsx', sheet_name='E6Data', index = False)

19 [33]: import matplotlib.pyplot as plt %matplotlib inline [34]: E6Data['TTM2']=E6Data['TTM']/360 # time to maturity [35]: plt.figure(figsize=(15, 6)) [35]:

[36]: plt.plot(E6Data['TTM2'], E6Data['Discount'], 'o-y', lw=1.5) plt.grid(True) plt.xlabel('Term(years)') plt.ylabel('Discount factor') plt.title('The bootstrapped discount curve for 6-months Euribor at 2020-04-14␣ , →(Table 3.6)') [36]: Text(0.5, 1.0, 'The bootstrapped discount curve for 6-months Euribor at 2020-04-14 (Table 3.6)')

[37]: plt.plot(E6Data['TTM2'], E6Data['Spot'], 'o-c', label= 'Spot rate', lw=1.5) plt.plot(E6Data['TTM2'], E6Data['Forward'],'o-m', label= 'Forward rate', lw=1.5) plt.grid(True) plt.xlabel('Term(years)') plt.ylabel('Yield') plt.title('The bootstrapped yield curve for 6-months Euribor at 2020-04-14␣ , →(Table 3.6)')

20 plt.legend() [37]:

[ ]:

21 Appendix D

The calculation of Eonia with the Smith Wilson model in Python

126 SWEO 2020-10-12 10:39 em

Applying Smith-Wilson technique on Eonia

In [1]: import pandas as pd import math import numpy as np

In [2]: # UFR rate for 2020 by EIOPA ufr=0.0375 alpha0=0.05 # the minst alpha

In [3]: LLP=20 # the last liquid point for a euro T=60 # the convergence point for a euro

In [4]: tau=0.0001 # the convergence tolerance

In [5]: EoData = pd.read_csv('Data_per_2020-04-14.csv', sep=';') #import Eo nia rates index EoData.head()

Out[5]: Name Quote From date To date Days

0 EONIA O/N -0.4510 2020-04-14 2020-04-15 1

1 EUR 1W OIS -0.4583 2020-04-14 2020-04-23 9

2 EUR 1M OIS -0.4606 2020-04-14 2020-05-18 34

3 EUR 2M OIS -0.4645 2020-04-14 2020-06-16 63

4 EUR 3M OIS -0.4696 2020-04-14 2020-07-16 93

Solve the following optimal problem in order to get the ! (! should be ≥ 0.05) "#$#"#%& !

\ '()*&+, ,- ! ≥ 0.05 \ ! . .(!) = ≤ / = 0.0001, ! = 0.05 |1 − 0&!1 | where ′ 1 + !( 2) 0 = ′ sin ℎ[!( ]2) file:///Users/pennyandersson/Downloads/SWEO-5.html Sida 1 av 23 SWEO 2020-10-12 10:39 em

\ !( !( ⎡ & 1 − &− 1 ⎤ ⎢ !( !( ⎥ 1 ⎢ & 2 − &− 2 ⎥ sin ℎ[!(] = ⎢ ⎥ , 2 ⎢ ⋮ ⎥ ! ! ⎣ & (" − &− (" ⎦ \

2 = 5Δ4 \ ! ( 7 !|( 8| !(( + 7) + &− ( + ) − !|( − 7| − &− − 6((, 7) = 2 \ ′ ) = (2 62)−1(9 − :) \ ; = log(1 + <=>) \ ;( ⎡ &− 1 ⎤ ⎢ ;( ⎥ ⎢ &− 2 ⎥ 5 = &?9[−;(] = ⎢ ⎥ ⎢ ⋮ ⎥ ⎣ &−;(" ⎦

⟹ ;( ⎡ &− 1 0 ⋯ 0 ⎤ ⎢ ;( ⎥ 0 &− 2 ⋯ 0 5 ⎢ ⎥ Δ = ⎢ ⎥ ⎢ ⋮ ⋮ ⋱ ⋮ ⎥ ; ⎣ 0 0 ⋯ &− (" ⎦ In this case, for Eonia rates, every tenor can be seen as a zero coupon bond. Thus for each zero coupon bond, the only cash flow is on the maturity of the zero coupon bond. Therefore cash-flow matrix 4 is an NxN indentity matrix.

⟹ ;( ⎡ &− 1 0 ⋯ 0 ⎤ ⎡ 1 0 ⋯ 0 ⎤ ⎢ ;( ⎥ ⎢ ⎥ 0 &− 2 ⋯ 0 0 1 ⋯ 0 2 5 4 ⎢ ⎥ ⎢ ⎥ = Δ = ⎢ ⎥ ⎢ ⎥ ⎢ ⋮ ⋮ ⋱ ⋮ ⎥ ⎢ ⋮ ⋮ ⋱ ⋮ ⎥ ; ⎣ 0 0 ⋯ &− (" ⎦ ⎣ 0 0 ⋯ 1 ⎦ ⎡ : ⎤ ⎢ 1 ⎥ ⎢ :2 ⎥ ′ ′ : = ⎢ ⎥ = 2 ) = 4 5 ⎢ ⋮ ⎥ ⎣ :$ ⎦ where " is the number of the observed duration to maturity and $ is the number of financial instruments. In this case, " = $.

file:///Users/pennyandersson/Downloads/SWEO-5.html Sida 2 av 23 SWEO 2020-10-12 10:39 em

In this case, ; is known therefore 2 is known.

Moreover, !'s lower bound is 0.05, then we can first test the appropriateness of !. When ! = 0.05 if the convergence gap .(!) ≤ / (/ = 0.0001) then ! = 0.05 is apposite in this case. Otherwise ! > 0.05 and .(!) = /.

In [6]: n=len(EoData.index) # the number of zero coupon bonds

In [7]: s_i=np.array(EoData['Quote']) # zero coupon rates print(s_i)

[-0.451 -0.4583 -0.4606 -0.4645 -0.4696 -0.4841 -0.4978 -0.5077 - 0.5169 -0.5217 -0.5242 -0.5232 -0.5261 -0.5245 -0.5205 -0.5149 -0.5095 - 0.5037 -0.4973 -0.4902 -0.4823 -0.4736 -0.4645 -0.4549 -0.4453 -0.4353 - 0.4251 -0.4147 -0.4042 -0.3934 -0.3821 -0.3714 -0.3602 -0.3486 -0.3373 - 0.3258 -0.3032 -0.2806 -0.2584 -0.2361 -0.1477 -0.0444 0.0225 0.0071 - 0.0368]

In [8]: s_i.shape

Out[8]: (45,)

file:///Users/pennyandersson/Downloads/SWEO-5.html Sida 3 av 23 SWEO 2020-10-12 10:39 em

In [9]: u_i=np.array(EoData['Days']/365) # the maturities of zero coupon bo nds in years u_i

Out[9]: array([2.73972603e-03, 2.46575342e-02, 9.31506849e-02, 1.72602740e -01, 2.54794521e-01, 5.06849315e-01, 7.64383562e-01, 1.00547945e +00, 1.25479452e+00, 1.51232877e+00, 1.76164384e+00, 2.01095890e +00, 2.26027397e+00, 2.50958904e+00, 2.75890411e+00, 3.00821918e +00, 3.25753425e+00, 3.50684932e+00, 3.75890411e+00, 4.00821918e +00, 4.25753425e+00, 4.50958904e+00, 4.76164384e+00, 5.00821918e +00, 5.25753425e+00, 5.50958904e+00, 5.76164384e+00, 6.00821918e +00, 6.25753425e+00, 6.50958904e+00, 6.76712329e+00, 7.00821918e +00, 7.25753425e+00, 7.51506849e+00, 7.76438356e+00, 8.01369863e +00, 8.51232877e+00, 9.01095890e+00, 9.51232877e+00, 1.00109589e +01, 1.20136986e+01, 1.50136986e+01, 2.00191781e+01, 2.50246575e +01, 3.00301370e+01])

In [10]: u_i.shape

Out[10]: (45,)

In [11]: def calculate_prices(rates: np.array, t: np.array) -> np.array: """Calculate prices from zero-coupon rates Args: rates=s_i: zero-coupon rates vector of length n t=u_i: time to maturity vector (in years) of length n Returns: Prices as vector of length n """

return np.exp(-rates * t)

file:///Users/pennyandersson/Downloads/SWEO-5.html Sida 4 av 23 SWEO 2020-10-12 10:39 em

In [12]: def ufr_discount_factor(ufr: float, t: np.array) -> np.array: """Calculate Ultimate Forward Rate (UFR) discount factors. Takes the UFR with a vector of maturities and returns for each of the maturities the discount factor d_UFR = e^(-UFR * t)

Args: ufr: Ultimate Forward Rate (annualized/annual compounding) t=u_i: time to maturity vector (in years) of length n Returns: UFR discount factors as vector of length n """

ufr = np.log(1 + ufr) return np.exp(-ufr * t)

file:///Users/pennyandersson/Downloads/SWEO-5.html Sida 5 av 23 SWEO 2020-10-12 10:39 em

In [13]: def wilson_function(t1: np.array, t2: np.array, alpha: float, ufr: float) -> np.array: """Calculate matrix of Wilson functions The Smith-Wilson method requires the calculation of a series of Wilson functions. The Wilson function is calculated for each maturity combination t1 and t2. If t1 and t2 are scalars, the result is a scalar. If t1 and t2 are vectors of shape (m, 1) and (n, 1), then the result is a ma trix of Wilson functions with shape (m, n): W = e^(-UFR * (t1 + t2)) * (α * min(t1, t2) - 0.5 * e^(-α * max(t1, t2)) * (e^(α * min(t1, t2)) - e^(-α * min(t1, t2))))

Args: t1=u_i: time to maturity vector of length n (the number of input zero coupon bonds) t2=u_i: time to maturity vector of length m (zero coupon bo nds only have one cash flow at the maturity) m=n alpha: Convergence speed parameter ufr: Ultimate Forward Rate (continuously compounding) Returns: Wilson-matrix of shape (m, n) as numpy matrix """

# Take time vectors of shape (nx1) and (mx1) and turn them into matrices of shape (mxn). # This is achieved by repeating the vectors along the axis 1. T he operation is required # because the Wilson function needs all possible combinations o f maturities to construct # the Wilson matrix

m = len(t1) n = len(t2)

t1_Mat = t1 t2_Mat = t2.T

# Calculate the minimum and maximum of the two matrices min_t = np.minimum(t1_Mat, t2_Mat) max_t = np.maximum(t1_Mat, t2_Mat)

# Calculate the UFR discount factor ufr_disc = ufr_discount_factor(ufr=ufr, t=(t1_Mat + t2_Mat)) W = ufr_disc * (alpha * min_t - 0.5 * np.exp(-alpha * max_t) * (np.exp(alpha * min_t) - np.exp(-alpha * min_t)))

return W

file:///Users/pennyandersson/Downloads/SWEO-5.html Sida 6 av 23 SWEO 2020-10-12 10:39 em

In [14]: def fit_parameters(rates: np.array, t: np.array, alpha: float, ufr: float) -> np.ndarray: """Calculate Smith-Wilson parameter vector ζ Given the Wilson-matrix, vector of discount factors and prices, the parameter vector can be calculated as follows: ζ = W^-1 * (P - μ)

rates=s_i: Observed zero-coupon rates vector of length n t1=u_i: time to maturity vector of length m t2=u_i: Observed time to maturity vector (in years) of leng th n alpha: Convergence speed parameter ufr: Ultimate Forward Rate (continuously compounding) Returns: Wilson-matrix of shape (m, n) as numpy matrix """

# Calcualte square matrix of Wilson functions, UFR discount vec tor and price vector # The price vector is calculated with zero-coupon rates and ass umed face value of 1 # For the estimation of zeta, t1 and t2 correspond both to the observed maturities W = wilson_function(t1=t, t2=t, alpha=alpha, ufr=ufr) mu = ufr_discount_factor(ufr=ufr, t=t) P = calculate_prices(rates=rates, t=t)

# Calculate vector of parameters # To invert the Wilson-matrix, conversion to type matrix is req uired zeta = np.matrix(W).I * (P-mu) zeta = np.array(zeta) # Convert back to more general array type

return zeta

In [15]: def fit_smithwilson_rates(rates_obs: np.array, t_obs: np.array, t_t arget: np.array, alpha: float, ufr: float) -> np.arr ay: """Calculate zero-coupon yields with Smith-Wilson method based on observed rates. This function expects the rates and initial maturity vector to be before the Last Liquid Point (LLP). The targeted maturity vecto r can contain both, more granular maturity structure (interpolation) or terms after the LLP (extrapolation). The Smith-Wilson method calculated first the Wilson-matrix: W = e^(-UFR * (t1 + t2)) * (α * min(t1, t2) - 0.5 * e^(-α * max(t1, t2)) * (e^(α * min(t1, t2)) - e^(-α * min(t1, t2))))

file:///Users/pennyandersson/Downloads/SWEO-5.html Sida 7 av 23 SWEO 2020-10-12 10:39 em

Given the Wilson-matrix, vector of discount factors and prices, the parameter vector can be calculated as follows: zeta = W^{-1} * (P - μ) With the Smith-Wilson parameter and Wilson-matrix, the zero-cou pon bond prices can be represented as in matrix notation: P = e^(-t * UFR) + W * zeta In the last case, t can be any maturity vector

Args: rates_obs=s_i: Initially observed zero-coupon rates vector before LLP of length n t_obs=u_i: Initially observed time to maturity vector (in y ears) of length m t_target=u_i: New targeted maturity vector (in years) with interpolated/extrapolated terms alpha: Convergence speed parameter ufr: Ultimate Forward Rate (continuously compounding) Returns: Vector of zero-coupon rates with Smith-Wilson interpolated or extrapolated rates """

# Convert list to numpy array and use reshape to convert from 1 -d to 2-d array # E.g. reshape((-1, 1)) converts an input of shape (10,) with s econd dimension # being empty (1-d vector) to shape (10, 1) where second dimens ion is 1 (2-d vector) rates_obs = np.array(rates_obs).reshape((-1, 1)) t_obs = np.array(t_obs).reshape((-1, 1)) t_target = np.array(t_target).reshape((-1, 1))

zeta = fit_parameters(rates=rates_obs, t=t_obs, alpha=alpha, uf r=ufr) ufr_disc = ufr_discount_factor(ufr=ufr, t=t_target) W = wilson_function(t1=t_target, t2=t_obs, alpha=alpha, ufr=ufr )

# Price vector - equivalent to discounting with zero-coupon yie lds 1/(1 + r)^t # for prices where t_obs = t_target. All other matuirites are i nterpolated or extrapolated P = ufr_disc + W @ zeta # '@' in numpy is the dot product of t wo matrices, for zero-coupon bonds

# Transform price vector to zero-coupon rate vector (1/P)^(1/t) - 1 return np.power(1/P, 1/t_target) - 1

file:///Users/pennyandersson/Downloads/SWEO-5.html Sida 8 av 23 SWEO 2020-10-12 10:39 em

In [16]: R=fit_smithwilson_rates(s_i, u_i, u_i, alpha0, ufr) R

Out[16]: array([[-0.36300916], [-0.36764226], [-0.36909501], [-0.37155075], [-0.37474768], [-0.38374843], [-0.3921335 ], [-0.39812169], [-0.40363358], [-0.40648928], [-0.4079712 ], [-0.40737888], [-0.40909499], [-0.40814878], [-0.40577664], [-0.40243965], [-0.3992041 ], [-0.39570936], [-0.39182949], [-0.38749612], [-0.38263817], [-0.37724369], [-0.37155075], [-0.36548858], [-0.35936794], [-0.35292948], [-0.34629559], [-0.33946159], [-0.33248939], [-0.32524121], [-0.31757319], [-0.31023202], [-0.3024632 ], [-0.29432466], [-0.2863053 ], [-0.27805044], [-0.26154861], [-0.24466959], [-0.22771374], [-0.2102983 ], [-0.13731012], [-0.04342875], [ 0.02275503], [ 0.00712526], [-0.03613111]])

In [17]: R.shape

Out[17]: (45, 1)

file:///Users/pennyandersson/Downloads/SWEO-5.html Sida 9 av 23 SWEO 2020-10-12 10:39 em

In [18]: import matplotlib.pyplot as plt %matplotlib inline

In [19]: EoData['TTM']=u_i EoData['Spot']=R

In [20]: plt.figure(figsize=(15, 6))

Out[20]:

In [21]: plt.plot(EoData['TTM'], EoData['Spot'], 'o-c', label= 'Spot rate', lw=1.5) plt.grid(True) plt.xlabel('Term(years)') plt.ylabel('Yield') plt.title('The spot rates for Eonia by Smith-Wilson technique at 20 20-04-14') plt.legend()

Out[21]:

Test the appropriateness of alpha

file:///Users/pennyandersson/Downloads/SWEO-5.html Sida 10 av 23 SWEO 2020-10-12 10:39 em

In [22]: p_i=calculate_prices(s_i, u_i) # price vector p_i

Out[22]: array([ 1.00123638, 1.01136464, 1.04383894, 1.08347555, 1.1271 04 , 1.27808869, 1.46303075, 1.66609392, 1.91286724, 2.2011 5433, 2.51797171, 2.86375499, 3.28422314, 3.72951968, 4.2038 8707, 4.70644128, 5.25780531, 5.84975629, 6.48377572, 7.1336 9292, 7.79442525, 8.46331863, 9.13198934, 9.75947789, 10.3934 9365, 11.00471822, 11.57994583, 12.08069221, 12.54466333, 12.9471 0652, 13.27281301, 13.50219956, 13.65579311, 13.73232959, 13.7209 8723, 13.61079208, 13.20952397, 12.53437749, 11.68125889, 10.6290 1363, 5.89687935, 1.9476202 , 0.63735307, 0.83721442, 3.0195 5371])

In [25]: p_i.shape

Out[25]: (45,)

In [26]: omega=np.log(1 + ufr) # computer the ultimate forward intensity omega

Out[26]: 0.0368139731227164

In [27]: d=np.exp(-omega*u_i) d

Out[27]: array([0.99989914, 0.99909267, 0.99657663, 0.99366595, 0.99066386, 0.98151387, 0.97225225, 0.96366101, 0.95485673, 0.94584665, 0.93720512, 0.92864255, 0.9201582 , 0.91175137, 0.90342135, 0.89516744, 0.88698893, 0.87888514, 0.87076757, 0.86281199, 0.85492909, 0.84703277, 0.83920939, 0.83162601, 0.82402804, 0.81641713, 0.80887652, 0.80156724, 0.79424389, 0.78690808, 0.77948277, 0.77259493, 0.76553628, 0.75831264, 0.75138447, 0.74451961, 0.73097747, 0.71768165, 0.7045566 , 0.69174135, 0.64257485, 0.57538615, 0.47855435, 0.39801839, 0.33103583] )

In [28]: d.shape

Out[28]: (45,)

file:///Users/pennyandersson/Downloads/SWEO-5.html Sida 11 av 23 SWEO 2020-10-12 10:39 em

In [29]: dd = np.diag(d) dd

Out[29]: array([[0.99989914, 0. , 0. , ..., 0. , 0. , 0. ], [0. , 0.99909267, 0. , ..., 0. , 0. , 0. ], [0. , 0. , 0.99657663, ..., 0. , 0. , 0. ], ..., [0. , 0. , 0. , ..., 0.47855435, 0. , 0. ], [0. , 0. , 0. , ..., 0. , 0.398 01839, 0. ], [0. , 0. , 0. , ..., 0. , 0. , 0.33103583]])

In [30]: dd.shape

Out[30]: (45, 45)

In [31]: c=np.ones(n) # compute cash-flow matrix C=np.diag(c) C

Out[31]: array([[1., 0., 0., ..., 0., 0., 0.], [0., 1., 0., ..., 0., 0., 0.], [0., 0., 1., ..., 0., 0., 0.], ..., [0., 0., 0., ..., 1., 0., 0.], [0., 0., 0., ..., 0., 1., 0.], [0., 0., 0., ..., 0., 0., 1.]])

file:///Users/pennyandersson/Downloads/SWEO-5.html Sida 12 av 23 SWEO 2020-10-12 10:39 em

In [32]: Q=dd*C Q

Out[32]: array([[0.99989914, 0. , 0. , ..., 0. , 0. , 0. ], [0. , 0.99909267, 0. , ..., 0. , 0. , 0. ], [0. , 0. , 0.99657663, ..., 0. , 0. , 0. ], ..., [0. , 0. , 0. , ..., 0.47855435, 0. , 0. ], [0. , 0. , 0. , ..., 0. , 0.398 01839, 0. ], [0. , 0. , 0. , ..., 0. , 0. , 0.33103583]])

In [33]: Q.shape

Out[33]: (45, 45)

In [34]: q=C.T*d q

Out[34]: array([[0.99989914, 0. , 0. , ..., 0. , 0. , 0. ], [0. , 0.99909267, 0. , ..., 0. , 0. , 0. ], [0. , 0. , 0.99657663, ..., 0. , 0. , 0. ], ..., [0. , 0. , 0. , ..., 0.47855435, 0. , 0. ], [0. , 0. , 0. , ..., 0. , 0.398 01839, 0. ], [0. , 0. , 0. , ..., 0. , 0. , 0.33103583]])

file:///Users/pennyandersson/Downloads/SWEO-5.html Sida 13 av 23 SWEO 2020-10-12 10:39 em

In [35]: q.shape

Out[35]: (45, 45)

In [36]: sinh=0.5*(np.exp(alpha0*u_i)-np.exp(-alpha0*u_i)) sinh

Out[36]: array([1.36986302e-04, 1.23287702e-03, 4.65755109e-03, 8.63024411e -03, 1.27400706e-02, 2.53451785e-02, 3.82284833e-02, 5.02951530e -02, 6.27808942e-02, 7.56885195e-02, 8.81961332e-02, 1.00717452e -01, 1.13254423e-01, 1.25808992e-01, 1.38383112e-01, 1.50978737e -01, 1.63597823e-01, 1.76242331e-01, 1.89053639e-01, 2.01755225e -01, 2.14488164e-01, 2.27394914e-01, 2.40337782e-01, 2.53036207e -01, 2.65914837e-01, 2.78977004e-01, 2.92083481e-01, 3.04949910e -01, 3.18006435e-01, 3.31256681e-01, 3.44849333e-01, 3.57626148e -01, 3.70893216e-01, 3.84658200e-01, 3.98044614e-01, 4.11492883e -01, 4.38583354e-01, 4.65946454e-01, 4.93751962e-01, 5.21713261e -01, 6.37465694e-01, 8.23203694e-01, 1.17668140e+00, 1.60424849e +00, 2.13282660e+00])

In [37]: sinh.shape

Out[37]: (45,)

file:///Users/pennyandersson/Downloads/SWEO-5.html Sida 14 av 23 SWEO 2020-10-12 10:39 em

In [38]: H=(alpha0*2*u_i+np.exp(-alpha0*2*u_i)-alpha0*np.abs(u_i-u_i)-np.exp (-alpha0*np.abs(u_i-u_i)))/2 H

Out[38]: array([1.87635332e-08, 1.51873645e-06, 2.16254257e-05, 7.40525963e -05, 1.60930912e-04, 6.31526040e-04, 1.42418808e-03, 2.44484886e -03, 3.77667055e-03, 5.44018009e-03, 7.32226161e-03, 9.46494788e -03, 1.18618220e-02, 1.45066249e-02, 1.73932519e-02, 2.05157485e -02, 2.38683067e-02, 2.74452617e-02, 3.12839961e-02, 3.52956211e -02, 3.95154145e-02, 4.39879623e-02, 4.86628743e-02, 5.34271320e -02, 5.84316322e-02, 6.36778701e-02, 6.91072147e-02, 7.45913306e -02, 8.03058630e-02, 8.62521645e-02, 9.24988261e-02, 9.84996185e -02, 1.04856614e-01, 1.11581076e-01, 1.18239979e-01, 1.25041865e -01, 1.39060592e-01, 1.53610119e-01, 1.68748695e-01, 1.84286198e -01, 2.51075881e-01, 3.62097287e-01, 5.68496897e-01, 7.92174300e -01, 1.02632547e+00])

In [39]: H.shape

Out[39]: (45,)

In [40]: b=np.matrix(Q.T*H*Q).I*(p_i-q) b

Out[40]: matrix([[7.12821516e+04, 5.39114177e+07, 5.56424803e+07, ..., 3.39744996e+07, 4.46282323e+07, 1.60959178e+08], [6.60454127e+05, 8.09506483e+03, 6.88556418e+05, ..., 4.20422663e+05, 5.52258915e+05, 1.99181407e+06], [4.66176698e+04, 4.70892427e+04, 2.20053823e+03, ..., 2.96752251e+04, 3.89807902e+04, 1.40590734e+05], ..., [7.69034779e+00, 7.76814145e+00, 8.01757172e+00, ..., 1.21970934e+00, 6.43051947e+00, 2.31927431e+01], [7.97828592e+00, 8.05899230e+00, 8.31776161e+00, ..., 5.07870582e+00, 3.49970452e+00, 2.40611141e+01], [8.90228517e+00, 8.99233849e+00, 9.28107698e+00, ..., 5.66689235e+00, 7.44391798e+00, 2.39043979e+01]])

file:///Users/pennyandersson/Downloads/SWEO-5.html Sida 15 av 23 SWEO 2020-10-12 10:39 em

In [41]: b.shape

Out[41]: (45, 45)

In [42]: zeta=fit_parameters(s_i, u_i, alpha0, ufr) zeta

Out[42]: array([[1.77613415e-10, 1.62997989e-09, 6.27744519e-09, ..., 2.10918629e-08, 5.83346175e-08, 3.57092624e-07], [1.43530010e-08, 1.31719234e-07, 5.07282499e-07, ..., 1.70444068e-06, 4.71404045e-06, 2.88567774e-05], [2.03345615e-07, 1.86612741e-06, 7.18690619e-06, ..., 2.41476008e-05, 6.67859951e-05, 4.08827336e-04], ..., [1.23264890e-03, 1.13121687e-02, 4.35658866e-02, ..., 1.46378930e-01, 4.04846120e-01, 2.47824653e+00], [1.18816232e-03, 1.09039100e-02, 4.19935839e-02, ..., 1.41096081e-01, 3.90235133e-01, 2.38880606e+00], [1.06483881e-03, 9.77215512e-03, 3.76349233e-02, ..., 1.26451227e-01, 3.49731266e-01, 2.14086354e+00]])

In [43]: zeta.shape

Out[43]: (45, 45)

In [44]: kappa=(1+alpha0*u_i.T*Q*b)/sinh*Q*b kappa

Out[44]: matrix([[4.05217783e+12, 4.37886486e+12, 8.51474507e+12, ..., 5.24518950e+12, 6.88997744e+12, 2.48498551e+13], [4.40122279e+11, 3.20535257e+14, 3.30825065e+14, ..., 2.02002182e+14, 2.65346081e+14, 9.57014985e+14], [2.31261208e+11, 8.55441244e+13, 8.84118130e+13, ..., 5.39830516e+13, 7.09110714e+13, 2.55752630e+14], ..., [5.02319231e+09, 1.84322175e+12, 1.90496074e+12, ..., 1.16317102e+12, 1.52791850e+12, 5.51069343e+12], [5.33406640e+09, 1.95715641e+12, 2.02271197e+12, ..., 1.23507006e+12, 1.62236367e+12, 5.85132568e+12], [5.81898829e+09, 2.13487919e+12, 2.20638811e+12, ..., 1.34722293e+12, 1.76968546e+12, 6.38266634e+12]])

In [45]: kappa.shape

Out[45]: (45, 45)

file:///Users/pennyandersson/Downloads/SWEO-5.html Sida 16 av 23 SWEO 2020-10-12 10:39 em

In [46]: g=alpha0/np.abs(1-kappa*np.exp(alpha0*T)) g # all elements in g is greater than tau, therefore we should choo se g=tau, alpha > a

Out[46]: matrix([[6.14324820e-16, 5.68492862e-16, 2.92357951e-16, ..., 4.74597423e-16, 3.61300663e-16, 1.00175772e-16], [5.65604955e-15, 7.76623901e-18, 7.52468202e-18, ..., 1.23233986e-17, 9.38153452e-18, 2.60116451e-18], [1.07642498e-14, 2.91002267e-17, 2.81563440e-17, ..., 4.61136105e-17, 3.51052856e-17, 9.73344212e-18], ..., [4.95571991e-13, 1.35054473e-15, 1.30677413e-15, ..., 2.14014394e-15, 1.62924489e-15, 4.51731429e-16], [4.66689620e-13, 1.27192360e-15, 1.23070089e-15, ..., 2.01555644e-15, 1.53439914e-15, 4.25434090e-16], [4.27798320e-13, 1.16603948e-15, 1.12824820e-15, ..., 1.84776652e-15, 1.40666434e-15, 3.90017790e-16]])

In [47]: matrix = np.ones((45,45)) matrix.shape

Out[47]: (45, 45)

In [48]: Tau=matrix*tau Tau

Out[48]: array([[0.0001, 0.0001, 0.0001, ..., 0.0001, 0.0001, 0.0001], [0.0001, 0.0001, 0.0001, ..., 0.0001, 0.0001, 0.0001], [0.0001, 0.0001, 0.0001, ..., 0.0001, 0.0001, 0.0001], ..., [0.0001, 0.0001, 0.0001, ..., 0.0001, 0.0001, 0.0001], [0.0001, 0.0001, 0.0001, ..., 0.0001, 0.0001, 0.0001], [0.0001, 0.0001, 0.0001, ..., 0.0001, 0.0001, 0.0001]])

In [ ]: # test when alpha = 0.05, if the convergence gap g<=0.0001 for i in range(45): for j in range(45): if g[i,j]-Tau[i,j]<=0: print('True') else: print('False')

# the result (is not displayed here in order to save spaces) shows that the constraint is fullfilled, the alpha=0.05 is appropriate.

In [50]: # get discount factors for all tenors for l in range(0,45): EoData.loc[l,'Discount']=np.exp(EoData.loc[l,'Spot']/(-100)*EoD ata.loc[l,'Days']/360).copy() EoData.Discount[:45]

file:///Users/pennyandersson/Downloads/SWEO-5.html Sida 17 av 23 SWEO 2020-10-12 10:39 em

Out[50]: 0 1.000010 1 1.000092 2 1.000349 3 1.000650 4 1.000969 5 1.001974 6 1.003044 7 1.004067 8 1.005148 9 1.006252 10 1.007313 11 1.008341 12 1.009419 13 1.010439 14 1.011415 15 1.012350 16 1.013272 17 1.014169 18 1.015045 19 1.015872 20 1.016654 21 1.017398 22 1.018099 23 1.018732 24 1.019341 25 1.019911 26 1.020435 27 1.020894 28 1.021319 29 1.021698 30 1.022028 31 1.022288 32 1.022506 33 1.022679 34 1.022795 35 1.022849 36 1.022830 37 1.022605 38 1.022205 39 1.021575 40 1.016866 41 1.006633 42 0.995392 43 0.998194 44 1.011062 Name: Discount, dtype: float64

In [51]: plt.figure(figsize=(15, 6))

Out[51]:

file:///Users/pennyandersson/Downloads/SWEO-5.html Sida 18 av 23 SWEO 2020-10-12 10:39 em

In [52]: plt.plot(EoData['TTM'], EoData['Discount'], 'o-y', label= 'SW disco unt factors', lw=1.5) plt.grid(True) plt.xlabel('Term(years)') plt.ylabel('Discount factor') plt.title('The discount factors for Eonia by Smith-Wilson technique at 2020-04-14 (Table 3.2)')

Out[52]: Text(0.5, 1.0, 'The discount factors for Eonia by Smith-Wilson tec hnique at 2020-04-14 (Table 3.2)')

In [53]: EoData.loc[0,'Forward']=(1-EoData.loc[0,'Discount'])/EoData.loc[0,' Discount']*36000 # assign forward rate for over-night to first row of 'Forward' EoData.head()

Out[53]: From Name Quote To date Days TTM Spot Discount Forward date

EONIA 2020- 2020- 0 -0.4510 1 0.002740 -0.363009 1.000010 -0.363007 O/N 04-14 04-15

EUR 1W 2020- 2020- -0.4583 9 0.024658 -0.367642 1.000092 NaN 1 OIS 04-14 04-23

EUR 1M 2020- 2020- -0.4606 34 0.093151 -0.369095 1.000349 NaN 2 OIS 04-14 05-18

EUR 2M 2020- 2020- -0.4645 63 0.172603 -0.371551 1.000650 NaN 3 OIS 04-14 06-16

EUR 3M 2020- 2020- -0.4696 93 0.254795 -0.374748 1.000969 NaN 4 OIS 04-14 07-16

file:///Users/pennyandersson/Downloads/SWEO-5.html Sida 19 av 23 SWEO 2020-10-12 10:39 em

In [54]: EoData['Days'].shift(1).head()

Out[54]: 0 NaN 1 1.0 2 9.0 3 34.0 4 63.0 Name: Days, dtype: float64

In [55]: EoData['DeltaT'] = EoData['Days'] - EoData['Days'].shift(1) # get d elta time=time difference

In [56]: EoData.head()

Out[56]: From To Name Quote Days TTM Spot Discount Forward DeltaT date date

EONIA 2020- 2020- 0 -0.4510 1 0.002740 -0.363009 1.000010 -0.363007 NaN O/N 04-14 04-15

EUR 2020- 2020- 1W -0.4583 9 0.024658 -0.367642 1.000092 NaN 8.0 1 04-14 04-23 OIS

EUR 2020- 2020- 1M -0.4606 34 0.093151 -0.369095 1.000349 NaN 25.0 2 04-14 05-18 OIS

EUR 2020- 2020- 2M -0.4645 63 0.172603 -0.371551 1.000650 NaN 29.0 3 04-14 06-16 OIS

EUR 2020- 2020- 3M -0.4696 93 0.254795 -0.374748 1.000969 NaN 30.0 4 04-14 07-16 OIS

In [57]: # get forward rates for all tenors for f in range(1,45): EoData.loc[f,'Forward']=(EoData.loc[f-1,'Discount']-EoData.loc[ f,'Discount'])/EoData.loc[f,'Discount']*36000/EoData.loc[f,'DeltaT' ].copy() EoData.Forward[:45]

file:///Users/pennyandersson/Downloads/SWEO-5.html Sida 20 av 23 SWEO 2020-10-12 10:39 em

Out[57]: 0 -0.363007 1 -0.368206 2 -0.369571 3 -0.374373 4 -0.381401 5 -0.392650 6 -0.408418 7 -0.416894 8 -0.425634 9 -0.420173 10 -0.416741 11 -0.402988 12 -0.422711 13 -0.399369 14 -0.381714 15 -0.365344 16 -0.360000 17 -0.349892 18 -0.337703 19 -0.322031 20 -0.304420 21 -0.286019 22 -0.269604 23 -0.248344 24 -0.236346 25 -0.218571 26 -0.201236 27 -0.179733 28 -0.164433 29 -0.145270 30 -0.123732 31 -0.104165 32 -0.084073 33 -0.064968 34 -0.044577 35 -0.020970 36 0.003659 37 0.043484 38 0.077043 39 0.121972 40 0.228057 41 0.334213 42 0.222517 43 -0.055307 44 -0.250780 Name: Forward, dtype: float64

file:///Users/pennyandersson/Downloads/SWEO-5.html Sida 21 av 23 SWEO 2020-10-12 10:39 em

In [58]: plt.plot(EoData['TTM'], EoData['Spot'], 'o-c', label= 'Spot rate', lw=1.5) plt.plot(EoData['TTM'], EoData['Forward'],'o-m', label= 'Forward ra te', lw=1.5) plt.grid(True) plt.xlabel('Term(years)') plt.ylabel('Yield') plt.title('The yield curve for Eonia by Smith-Wilson at 2020-04-14 (Table 3.2)') plt.legend()

Out[58]:

In [59]: EoData.head()

Out[59]: From To Name Quote Days TTM Spot Discount Forward DeltaT date date

EONIA 2020- 2020- 0 -0.4510 1 0.002740 -0.363009 1.000010 -0.363007 NaN O/N 04-14 04-15

EUR 2020- 2020- 1W -0.4583 9 0.024658 -0.367642 1.000092 -0.368206 8.0 1 04-14 04-23 OIS

EUR 2020- 2020- 1M -0.4606 34 0.093151 -0.369095 1.000349 -0.369571 25.0 2 04-14 05-18 OIS

EUR 2020- 2020- 2M -0.4645 63 0.172603 -0.371551 1.000650 -0.374373 29.0 3 04-14 06-16 OIS

EUR 2020- 2020- 3M -0.4696 93 0.254795 -0.374748 1.000969 -0.381401 30.0 4 04-14 07-16 OIS

file:///Users/pennyandersson/Downloads/SWEO-5.html Sida 22 av 23 SWEO 2020-10-12 10:39 em

In [60]: EoData.to_excel(r'/Users/pennyandersson/Desktop/Analytical Finance/ thesis/my work/ EoDataSW.xlsx', sheet_name='EoDataSW', index = False)

In [ ]:

file:///Users/pennyandersson/Downloads/SWEO-5.html Sida 23 av 23 Appendix E

The calculation of 3-months Euribor with the Smith Wilson model in Python

150 SWE3 2020-10-07 8:21 fm

Applying Smith-Wilson technique to 3-months Euribor

In [1]: import pandas as pd import math import numpy as np

In [2]: # UFR rate for 2020 by EIOPA ufr=0.0375 alpha0=0.05 # the minst alpha

In [3]: LLP=20 # the last liquid point for a euro T=60 # the convergence point for a euro

In [4]: tau=0.0001 # the convergence tolerance

In [5]: E3Data = pd.read_csv('E3 Data per 2020-04-14.csv', sep=';') #import 3-months Euribor rates index E3Data.head()

Out[5]: Name Quote Measured date From date To date Days 1 Days 2

0 EURIBOR S/W -0.518 2020-04-14 2020-04-16 2020-04-23 7 9

1 EURIBOR 1M -0.404 2020-04-14 2020-04-16 2020-05-18 32 34

2 EURIBOR 2M NaN 2020-04-14 2020-04-16 2020-06-16 61 63

3 EURIBOR 3M -0.248 2020-04-14 2020-04-16 2020-07-16 91 93

4 EUR 1X4 FRA -0.270 2020-04-14 2020-04-16 2020-08-17 123 125

Solve the following optimal problem in order to get the ! (! should be ≥ 0.05) "#$#"#%& !

\ '()*&+, ,- ! ≥ 0.05 \ ! . .(!) = ≤ / = 0.0001, ! = 0.05 |1 − 0&!1 | where

′ 1 + ! 2) file:///Users/pennyandersson/Downloads/SWE3.html 0 = Sida 1 av 145 SWE3 2020-10-07 8:21 fm

′ 1 + !( 2) 0 = ′ sin ℎ[!( ]2) \ !( !( ⎡ & 1 − &− 1 ⎤ ⎢ !( !( ⎥ 1 ⎢ & 2 − &− 2 ⎥ sin ℎ[!(] = ⎢ ⎥ , 2 ⎢ ⋮ ⎥ ! ! ⎣ & (" − &− (" ⎦ \

2 = 5Δ4 \ ! ( 7 !|( 8| !(( + 7) + &− ( + ) − !|( − 7| − &− − 6((, 7) = 2 \ ′ ) = (2 62)−1(9 − :) \ ; = log(1 + <=>) \ ;( ⎡ &− 1 ⎤ ⎢ ;( ⎥ ⎢ &− 2 ⎥ 5 = &?9[−;(] = ⎢ ⎥ ⎢ ⋮ ⎥ ⎣ &−;(@ ⎦

⟹ ;( ⎡ &− 1 0 ⋯ 0 ⎤ ⎢ ;( ⎥ 0 &− 2 ⋯ 0 5 ⎢ ⎥ Δ = ⎢ ⎥ ⎢ ⋮ ⋮ ⋱ ⋮ ⎥ ; ⎣ 0 0 ⋯ &− (@ ⎦ In this case, for 3-months Euribor rates, every tenor can be seen as a coupon bond. Frequence is every three months has a cash flow. Thus for each coupon bond has several cash flows. Therefore cash-flow matrix 4 is an NxJ cash flow matrix.

⟹ −;(1 ⎡ ⎤ ⎡ & 0 ⋯ 0 ⎤ +1,1 +1,2 ⋯ +1,* ⋯ +1,@ ⎢ ⎥ ⎢ ⎥ −;(2 0 & ⋯ 0 +2,1 +2,2 ⋯ +2,* ⋯ +2,@ 2 5 4 ⎢ ⎥ ⎢ ⎥ = Δ = ⎢ ⎥ ⎢ ⎥ ⎢ ⋮ ⋮ ⋱ ⋮ ⎥ ⎢ ⋮ ⋮ ⋱ ⋮ ⋮ ⋯ ⎥ ⎣ −;(@ ⎦ 0 0 ⋯ & ⎣ +A,1 +A,2 ⋯ +A,* ⋯ +A,@ ⎦ ⎡ : ⎤ ⎢ 1 ⎥ ⎢ :2 ⎥ ′ ′ : = ⎢ ⎥ = 2 ) = 4 5 ⎢ ⋮ ⎥ ⎣ :A ⎦

file:///Users/pennyandersson/Downloads/SWE3.html Sida 2 av 145 SWE3 2020-10-07 8:21 fm

where @ is the number of the observed duration to maturity or in other words the number of dates of cash-flow and A is the number of financial instruments.

In this case, ; is known therefore 2 is known.

Moreover, !'s lower bound is 0.05, then we can first test the appropriateness of !. When ! = 0.05 if the convergence gap .(!) ≤ / (/ = 0.0001) then ! = 0.05 is apposite in this case. Otherwise ! > 0.05 and .(!) = /.

since maturities under 3 months don't pay any coupon therefore they can be seen as zero coupon bond

In [6]: s_i=np.array(E3Data.loc[0:2,'Quote'])/100 s_i

Out[6]: array([-0.00518, -0.00404, nan])

In [7]: s_i.shape

Out[7]: (3,)

In [8]: # using interpolation to get Euribor 2M quoted rate E2m=E3Data.loc[3,'Quote']/100-(E3Data.loc[3,'Quote']/100-E3Data.loc [1,'Quote']/100)/(93-34)*(93-63) E2m

Out[8]: -0.0032732203389830503

In [9]: s_i[2]=E2m s_i

Out[9]: array([-0.00518 , -0.00404 , -0.00327322])

In [10]: z_i=np.array(E3Data.loc[0:2,'Days 2']/365) # the maturities of zero coupon bonds in years z_i

Out[10]: array([0.02465753, 0.09315068, 0.17260274])

In [11]: z_i.shape

Out[11]: (3,)

In [12]: n=len(z_i) n

Out[12]: 3

file:///Users/pennyandersson/Downloads/SWE3.html Sida 3 av 145 SWE3 2020-10-07 8:21 fm

In [13]: z_t=np.zeros((n,n)) z_t

Out[13]: array([[0., 0., 0.], [0., 0., 0.], [0., 0., 0.]])

In [14]: for t in range (0,3): # computer JxN time matrix z_t[:,t]=z_i z_t

Out[14]: array([[0.02465753, 0.02465753, 0.02465753], [0.09315068, 0.09315068, 0.09315068], [0.17260274, 0.17260274, 0.17260274]])

In [15]: def calculate_prices(rates: np.array, t: np.array) -> np.array: """Calculate prices from coupon rates Args: rates=s_i: coupon rates vector of length n t=z_i: time to maturity vector (in years) of length n Returns: Prices as vector of length n """

return np.power(1 + rates, -t)

In [16]: def ufr_discount_factor(ufr: float, t: np.array) -> np.array: """Calculate Ultimate Forward Rate (UFR) discount factors. Takes the UFR with a vector of maturities and returns for each of the maturities the discount factor d_UFR = e^(-UFR * t) Note that UFR is expected to be annualy compounded and that this function performs the calculation of the log return prior to applying the formula above. Args: ufr: Ultimate Forward Rate (annualized/annual compounding) t=z_i: time to maturity vector (in years) of length n Returns: UFR discount factors as vector of length n """

ufr = np.log(1 + ufr) return np.exp(-ufr * t)

file:///Users/pennyandersson/Downloads/SWE3.html Sida 4 av 145 SWE3 2020-10-07 8:21 fm

In [17]: def wilson_function(t1: np.array, t2: np.array, alpha: float, ufr: float) -> np.array: """Calculate matrix of Wilson functions The Smith-Wilson method requires the calculation of a series of Wilson functions. The Wilson function is calculated for each maturity combination t1 and t2. If t1 and t2 are scalars, the result is a scalar. If t1 and t2 are vectors of shape (m, 1) and (n, 1), then the result is a ma trix of Wilson functions with shape (m, n): W = e^(-UFR * (t1 + t2)) * (α * min(t1, t2) - 0.5 * e^(-α * max(t1, t2)) * (e^(α * min(t1, t2)) - e^(-α * min(t1, t2))))

Args: t1=z_i: time to maturity vector of length m t2=z_i: time to maturity vector of length n (zero coupon bo nds only have one cash flow at the maturity) m=n alpha: Convergence speed parameter ufr: Ultimate Forward Rate (continuously compounding) Returns: Wilson-matrix of shape (m, n) as numpy matrix """

# Take time vectors of shape (nx1) and (mx1) and turn them into matrices of shape (mxn). # This is achieved by repeating the vectors along the axis 1. T he operation is required # because the Wilson function needs all possible combinations o f maturities to construct # the Wilson matrix

m = len(t1) n = len(t2)

t1_Mat = z_t t2_Mat = z_t.T

# Calculate the minimum and maximum of the two matrices min_t = np.minimum(t1_Mat, t2_Mat) max_t = np.maximum(t1_Mat, t2_Mat)

# Calculate the UFR discount factor ufr_disc = ufr_discount_factor(ufr=ufr, t=(t1_Mat + t2_Mat)) W = ufr_disc * (alpha * min_t - 0.5 * np.exp(-alpha * max_t) * (np.exp(alpha * min_t) - np.exp(-alpha * min_t)))

return W

file:///Users/pennyandersson/Downloads/SWE3.html Sida 5 av 145 SWE3 2020-10-07 8:21 fm

In [18]: W1=wilson_function(z_t, z_t, alpha0, ufr) W1

Out[18]: array([[1.51598172e-06, 5.70371255e-06, 1.05171523e-05], [5.70371255e-06, 2.14776153e-05, 3.96160340e-05], [1.05171523e-05, 3.96160340e-05, 7.31174619e-05]])

In [19]: def fit_parameters(rates: np.array, t: np.array, alpha: float, ufr: float) -> np.ndarray: """Calculate Smith-Wilson parameter vector ζ Given the Wilson-matrix, vector of discount factors and prices, the parameter vector can be calculated as follows: ζ = W^-1 * (P - μ)

rates=s_i: Observed zero-coupon rates vector of length n t1=z_i: time to maturity vector of length m t2=z_i: Observed time to maturity vector (in years) of leng th n alpha: Convergence speed parameter ufr: Ultimate Forward Rate (continuously compounding) Returns: Wilson-matrix of shape (m, n) as numpy matrix """

# Calcualte square matrix of Wilson functions, UFR discount vec tor and price vector # The price vector is calculated with zero-coupon rates and ass umed face value of 1 # For the estimation of zeta, t1 and t2 correspond both to the observed maturities W = wilson_function(t1=z_t, t2=z_t, alpha=alpha, ufr=ufr) mu = ufr_discount_factor(ufr=ufr, t=t) P = calculate_prices(rates=rates, t=t)

# Calculate vector of parameters (p. 17) # To invert the Wilson-matrix, conversion to type matrix is req uired zeta = np.matrix(W).I @ (P-mu) zeta = np.array(zeta) # Convert back to more general array type

return zeta

In [20]: P = calculate_prices(s_i, z_i) P

Out[20]: array([1.00012807, 1.00037716, 1.00056605])

np.matrix(W1).I

file:///Users/pennyandersson/Downloads/SWE3.html Sida 6 av 145 SWE3 2020-10-07 8:21 fm

In [21]: zeta1=fit_parameters(s_i, z_i, alpha0,ufr) zeta1

Out[21]: array([[17501.64629233, -2450.90682951, -1095.11693338]])

In [22]: def fit_smithwilson_rates(rates_obs: np.array, t_obs: np.array, t_t arget: np.array, alpha: float, ufr: float) -> np.arr ay: """Calculate zero-coupon yields with Smith-Wilson method based on observed rates. This function expects the rates and initial maturity vector to be before the Last Liquid Point (LLP). The targeted maturity vecto r can contain both, more granular maturity structure (interpolation) or terms after the LLP (extrapolation). The Smith-Wilson method calculated first the Wilson-matrix: W = e^(-UFR * (t1 + t2)) * (α * min(t1, t2) - 0.5 * e^(-α * max(t1, t2)) * (e^(α * min(t1, t2)) - e^(-α * min(t1, t2)))) Given the Wilson-matrix, vector of discount factors and prices, the parameter vector can be calculated as follows: zeta = W^{-1} * (P - μ) With the Smith-Wilson parameter and Wilson-matrix, the zero-cou pon bond prices can be represented as in matrix notation: P = e^(-t * UFR) + W * zeta In the last case, t can be any maturity vector

Args: rates_obs: Initially observed zero-coupon rates vector befo re LLP of length n t_obs: Initially observed time to maturity vector (in years ) of length n t_target: New targeted maturity vector (in years) with inte rpolated/extrapolated terms alpha: Convergence speed parameter ufr: Ultimate Forward Rate (continuously compounding) Returns: Vector of zero-coupon rates with Smith-Wilson interpolated or extrapolated rates """

# Convert list to numpy array and use reshape to convert from 1 -d to 2-d array # E.g. reshape((-1, 1)) converts an input of shape (10,) with s econd dimension # being empty (1-d vector) to shape (10, 1) where second dimens ion is 1 (2-d vector) rates_obs = np.array(rates_obs).reshape((-1, 1)) t_obs = np.array(t_obs).reshape((-1, 1)) file:///Users/pennyandersson/Downloads/SWE3.html Sida 7 av 145 SWE3 2020-10-07 8:21 fm

t_target = np.array(t_target).reshape((-1, 1))

zeta = fit_parameters(rates=rates_obs, t=t_obs, alpha=alpha, uf r=ufr) ufr_disc = ufr_discount_factor(ufr=ufr, t=t_target) W = wilson_function(t1=t_target, t2=t_obs, alpha=alpha, ufr=ufr )

# Price vector - equivalent to discounting with zero-coupon yie lds 1/(1 + r)^t # for prices where t_obs = t_target. All other matuirites are i nterpolated or extrapolated P = ufr_disc + W @ zeta # '@' in numpy is the dot product of t wo matrices, for zero-coupon bonds

# Transform price vector to zero-coupon rate vector (1/P)^(1/t) - 1 return 1/t_target*np.log(1/P) *100

In [23]: R1=fit_smithwilson_rates(s_i, z_i, z_i, alpha0, ufr) R1

Out[23]: array([[-0.51934627], [-0.40481828], [-0.3278589 ]])

In [24]: E3Data['TTM']=E3Data['Days 2']/365 E3Data.loc[0:2,'Spot']=R1 E3Data.head()

Out[24]: Measured From Days Days Name Quote To date TTM Spot date date 1 2

EURIBOR 2020- 2020- 0 -0.518 2020-04-14 7 9 0.024658 -0.519346 S/W 04-16 04-23

EURIBOR 2020- 2020- -0.404 2020-04-14 32 34 0.093151 -0.404818 1 1M 04-16 05-18

EURIBOR 2020- 2020- NaN 2020-04-14 61 63 0.172603 -0.327859 2 2M 04-16 06-16

EURIBOR 2020- 2020- -0.248 2020-04-14 91 93 0.254795 NaN 3 3M 04-16 07-16

EUR 1X4 2020- 2020- -0.270 2020-04-14 123 125 0.342466 NaN 4 FRA 04-16 08-17

Test the appropriateness of alpha

file:///Users/pennyandersson/Downloads/SWE3.html Sida 8 av 145 SWE3 2020-10-07 8:21 fm

In [25]: p_i=calculate_prices(s_i, z_i) # price vector p_i

Out[25]: array([1.00012807, 1.00037716, 1.00056605])

In [26]: omega=np.log(1 + ufr) # computer the ultimate forward intensity omega

Out[26]: 0.0368139731227164

In [27]: d=-omega*z_i d

Out[27]: array([-0.00090774, -0.00342925, -0.00635419])

In [28]: dd = np.diag(d) dd

Out[28]: array([[-0.00090774, 0. , 0. ], [ 0. , -0.00342925, 0. ], [ 0. , 0. , -0.00635419]])

In [29]: c=np.ones(n) # compute cash-flow matrix C=np.diag(c) C

Out[29]: array([[1., 0., 0.], [0., 1., 0.], [0., 0., 1.]])

In [30]: Q=dd*C Q

Out[30]: array([[-0.00090774, 0. , 0. ], [ 0. , -0.00342925, 0. ], [ 0. , 0. , -0.00635419]])

In [31]: q=C.T*d q

Out[31]: array([[-0.00090774, -0. , -0. ], [-0. , -0.00342925, -0. ], [-0. , -0. , -0.00635419]])

In [32]: sinh=0.5*(np.exp(alpha0*z_i)-np.exp(-alpha0*z_i)) sinh

Out[32]: array([0.00123288, 0.00465755, 0.00863024])

file:///Users/pennyandersson/Downloads/SWE3.html Sida 9 av 145 SWE3 2020-10-07 8:21 fm

In [33]: H=(alpha0*2*z_i+np.exp(-alpha0*2*z_i)-alpha0*np.abs(z_i-z_i)-np.exp (-alpha0*np.abs(z_i-z_i)))/2 H

Out[33]: array([1.51873645e-06, 2.16254257e-05, 7.40525963e-05])

In [34]: b=np.matrix(Q.T*H*Q).I*(p_i-q) b

Out[34]: matrix([[7.99912574e+11, 7.99386260e+11, 7.99537200e+11], [3.93272394e+09, 3.94718799e+09, 3.93444620e+09], [3.34498807e+08, 3.34582119e+08, 3.36770493e+08]])

In [35]: zeta=fit_parameters(s_i, z_i, alpha0, ufr) zeta

Out[35]: array([[17501.64629233, -2450.90682951, -1095.11693338]])

In [36]: kappa=(1+alpha0*z_i.T*Q*b)/sinh*Q*b kappa

Out[36]: matrix([[5.30051743e+17, 5.29714419e+17, 5.29806956e+17], [3.71916087e+16, 3.71679435e+16, 3.71744338e+16], [1.08604156e+16, 1.08535043e+16, 1.08554003e+16]])

In [37]: g=alpha0/np.abs(1-kappa*np.exp(alpha0*T)) g # all elements in g is greater than tau, therefore we should choo se g=tau, alpha > a

Out[37]: matrix([[4.69643474e-21, 4.69942544e-21, 4.69860463e-21], [6.69332009e-20, 6.69758180e-20, 6.69641246e-20], [2.29213459e-19, 2.29359418e-19, 2.29319357e-19]])

In [38]: matrix = np.ones((3,3)) matrix.shape

Out[38]: (3, 3)

In [39]: Tau=matrix*tau Tau

Out[39]: array([[0.0001, 0.0001, 0.0001], [0.0001, 0.0001, 0.0001], [0.0001, 0.0001, 0.0001]])

file:///Users/pennyandersson/Downloads/SWE3.html Sida 10 av 145 SWE3 2020-10-07 8:21 fm

In [40]: # test when alpha = 0.05, if the convergence gap g<=0.0001 for i in range(3): for j in range(3): if g[i,j]-Tau[i,j]<=0: print('True') else: print('False')

True True True True True True True True True

In [41]: # for swap instrument, 3-months Euribor, tenors from and incl. 3 må nader are considered as coupon bonds r_c=np.array(E3Data.loc[3:29,'Quote']) # swap rates print(r_c)

[-0.248 -0.27 -0.299 -0.322 -0.347 -0.347 -0.363 -0.373 -0.377 -0 .38 -0.371 -0.346 -0.31 -0.271 -0.229 -0.184 -0.139 -0.094 -0.05 -0 .008 0.094 0.157 0.14 0.092 0.016 -0.053]

In [42]: r_c.shape

Out[42]: (26,)

In [43]: # the tenor of 50Y IRS 3M has J=50*4=200 (pay every 3 months), when there is no payment exchanging then cash-flow c=0 u_i=np.linspace(0.25,50.,200) u_i

file:///Users/pennyandersson/Downloads/SWE3.html Sida 11 av 145 SWE3 2020-10-07 8:21 fm

Out[43]: array([ 0.25, 0.5 , 0.75, 1. , 1.25, 1.5 , 1.75, 2. , 2. 25, 2.5 , 2.75, 3. , 3.25, 3.5 , 3.75, 4. , 4.25, 4. 5 , 4.75, 5. , 5.25, 5.5 , 5.75, 6. , 6.25, 6.5 , 6. 75, 7. , 7.25, 7.5 , 7.75, 8. , 8.25, 8.5 , 8.75, 9. , 9.25, 9.5 , 9.75, 10. , 10.25, 10.5 , 10.75, 11. , 11. 25, 11.5 , 11.75, 12. , 12.25, 12.5 , 12.75, 13. , 13.25, 13. 5 , 13.75, 14. , 14.25, 14.5 , 14.75, 15. , 15.25, 15.5 , 15. 75, 16. , 16.25, 16.5 , 16.75, 17. , 17.25, 17.5 , 17.75, 18. , 18.25, 18.5 , 18.75, 19. , 19.25, 19.5 , 19.75, 20. , 20. 25, 20.5 , 20.75, 21. , 21.25, 21.5 , 21.75, 22. , 22.25, 22. 5 , 22.75, 23. , 23.25, 23.5 , 23.75, 24. , 24.25, 24.5 , 24. 75, 25. , 25.25, 25.5 , 25.75, 26. , 26.25, 26.5 , 26.75, 27. , 27.25, 27.5 , 27.75, 28. , 28.25, 28.5 , 28.75, 29. , 29. 25, 29.5 , 29.75, 30. , 30.25, 30.5 , 30.75, 31. , 31.25, 31. 5 , 31.75, 32. , 32.25, 32.5 , 32.75, 33. , 33.25, 33.5 , 33. 75, 34. , 34.25, 34.5 , 34.75, 35. , 35.25, 35.5 , 35.75, 36. , 36.25, 36.5 , 36.75, 37. , 37.25, 37.5 , 37.75, 38. , 38. 25, 38.5 , 38.75, 39. , 39.25, 39.5 , 39.75, 40. , 40.25, 40. 5 , 40.75, 41. , 41.25, 41.5 , 41.75, 42. , 42.25, 42.5 , 42. 75, 43. , 43.25, 43.5 , 43.75, 44. , 44.25, 44.5 , 44.75, 45. , 45.25, 45.5 , 45.75, 46. , 46.25, 46.5 , 46.75, 47. , 47. 25, 47.5 , 47.75, 48. , 48.25, 48.5 , 48.75, 49. , 49.25, 49. 5 , 49.75, 50. ])

In [44]: u_i.shape

Out[44]: (200,)

In [45]: l=list(u_i)

file:///Users/pennyandersson/Downloads/SWE3.html Sida 12 av 145 SWE3 2020-10-07 8:21 fm

In [46]: # for FRA tenors, we have maturities in 4m, 5m, 6m and 7m, so we ha ve extend payment dates l.insert(1,1/3)

In [47]: l.insert(2,5/12)

In [48]: l.insert(4,7/12) l

Out[48]: [0.25, 0.3333333333333333, 0.4166666666666667, 0.5, 0.5833333333333334, 0.75, 1.0, 1.25, 1.5, 1.75, 2.0, 2.25, 2.5, 2.75, 3.0, 3.25, 3.5, 3.75, 4.0, 4.25, 4.5, 4.75, 5.0, 5.25, 5.5, 5.75, 6.0, 6.25, 6.5, 6.75, 7.0, 7.25, 7.5, 7.75, 8.0, 8.25, 8.5, 8.75, 9.0, 9.25, 9.5, 9.75, 10.0,

file:///Users/pennyandersson/Downloads/SWE3.html Sida 13 av 145 SWE3 2020-10-07 8:21 fm

In [49]: u_a=np.array(l) # payment dates u_a

Out[49]: array([ 0.25 , 0.33333333, 0.41666667, 0.5 , 0.5833 3333, 0.75 , 1. , 1.25 , 1.5 , 1.75 , 2. , 2.25 , 2.5 , 2.75 , 3. , 3.25 , 3.5 , 3.75 , 4. , 4.25 , 4.5 , 4.75 , 5. , 5.25 , 5.5 , 5.75 , 6. , 6.25 , 6.5 , 6.75 , 7. , 7.25 , 7.5 , 7.75 , 8. , 8.25 , 8.5 , 8.75 , 9. , 9.25 , 9.5 , 9.75 , 10. , 10.25 , 10.5 , 10.75 , 11. , 11.25 , 11.5 , 11.75 , 12. , 12.25 , 12.5 , 12.75 , 13. , 13.25 , 13.5 , 13.75 , 14. , 14.25 , 14.5 , 14.75 , 15. , 15.25 , 15.5 , 15.75 , 16. , 16.25 , 16.5 , 16.75 , 17. , 17.25 , 17.5 , 17.75 , 18. , 18.25 , 18.5 , 18.75 , 19. , 19.25 , 19.5 , 19.75 , 20. , 20.25 , 20.5 , 20.75 , 21. , 21.25 , 21.5 , 21.75 , 22. , 22.25 , 22.5 , 22.75 , 23. , 23.25 , 23.5 , 23.75 , 24. , 24.25 , 24.5 , 24.75 , 25. , 25.25 , 25.5 , 25.75 , 26. , 26.25 , 26.5 , 26.75 , 27. , 27.25 , 27.5 , 27.75 , 28. , 28.25 , 28.5 , 28.75 , 29. , 29.25 , 29.5 , 29.75 , 30. , 30.25 , 30.5 ,

file:///Users/pennyandersson/Downloads/SWE3.html Sida 17 av 145 SWE3 2020-10-07 8:21 fm

30.75 , 31. , 31.25 , 31.5 , 31.75 , 32. , 32.25 , 32.5 , 32.75 , 33. , 33.25 , 33.5 , 33.75 , 34. , 34.25 , 34.5 , 34.75 , 35. , 35.25 , 35.5 , 35.75 , 36. , 36.25 , 36.5 , 36.75 , 37. , 37.25 , 37.5 , 37.75 , 38. , 38.25 , 38.5 , 38.75 , 39. , 39.25 , 39.5 , 39.75 , 40. , 40.25 , 40.5 , 40.75 , 41. , 41.25 , 41.5 , 41.75 , 42. , 42.25 , 42.5 , 42.75 , 43. , 43.25 , 43.5 , 43.75 , 44. , 44.25 , 44.5 , 44.75 , 45. , 45.25 , 45.5 , 45.75 , 46. , 46.25 , 46.5 , 46.75 , 47. , 47.25 , 47.5 , 47.75 , 48. , 48.25 , 48.5 , 48.75 , 49. , 49.25 , 49.5 , 49.75 , 50. ])

In [50]: u_a.shape

Out[50]: (203,)

In [51]: s=4 # frequence of payments/cash flows per year. Pay every 3 months .

In [52]: c_i=r_c/s # the vector of quarter swap rates c_i

Out[52]: array([-0.062 , -0.0675 , -0.07475, -0.0805 , -0.08675, -0.08675, -0.09075, -0.09325, -0.09425, -0.095 , -0.09275, -0.0865 , -0.0775 , -0.06775, -0.05725, -0.046 , -0.03475, -0.0235 , -0.0125 , -0.002 , 0.0235 , 0.03925, 0.035 , 0.023 , 0.004 , -0.01325])

In [53]: c_i.shape

Out[53]: (26,)

file:///Users/pennyandersson/Downloads/SWE3.html Sida 18 av 145 SWE3 2020-10-07 8:21 fm

In [54]: r=r_c/s/100 r

Out[54]: array([-6.200e-04, -6.750e-04, -7.475e-04, -8.050e-04, -8.675e-04, -8.675e-04, -9.075e-04, -9.325e-04, -9.425e-04, -9.500e-04, -9.275e-04, -8.650e-04, -7.750e-04, -6.775e-04, -5.725e-04, -4.600e-04, -3.475e-04, -2.350e-04, -1.250e-04, -2.000e-05, 2.350e-04, 3.925e-04, 3.500e-04, 2.300e-04, 4.000e-05, -1.325e-04])

In [55]: N=len(E3Data.index)-3 # the number of coupon bonds N

Out[55]: 26

In [56]: J=len(u_i)+3 J

Out[56]: 203

In [57]: c_ij=np.zeros((N,J)) c_ij.shape

Out[57]: (26, 203)

In [58]: c_ij[0,0]=c_i[0] # for tenor 3M c_ij[0,0]

Out[58]: -0.062

In [59]: # cash-flows for FRAs c_ij[1,1]=c_i[1] c_ij[2,2]=c_i[2] c_ij[3,3]=c_i[3] c_ij[4,4]=c_i[4] c_ij

Out[59]: array([[-0.062 , 0. , 0. , ..., 0. , 0. , 0. ], [ 0. , -0.0675 , 0. , ..., 0. , 0. , 0. ], [ 0. , 0. , -0.07475, ..., 0. , 0. , 0. ], ..., [ 0. , 0. , 0. , ..., 0. , 0. , 0. ], [ 0. , 0. , 0. , ..., 0. , 0. , 0. ], [ 0. , 0. , 0. , ..., 0. , 0. , 0. ]])

file:///Users/pennyandersson/Downloads/SWE3.html Sida 19 av 145 SWE3 2020-10-07 8:21 fm

In [60]: # for the tenor 1Y c_ij[5,0]=c_ij[5,3]=c_ij[5,5]=c_i[5] c_ij[5,6]=1+c_i[5] c_ij[5,0:9]

Out[60]: array([-0.08675, 0. , 0. , -0.08675, 0. , -0.08675, 0.91325, 0. , 0. ])

In [61]: # for the tenor 15M c_ij[6,0]=c_ij[6,3]=c_ij[6,5]=c_ij[6,6]=c_i[6] c_ij[6,7]=1+c_i[6] c_ij[6,0:9]

Out[61]: array([-0.09075, 0. , 0. , -0.09075, 0. , -0.09075, -0.09075, 0.90925, 0. ])

In [62]: # for the tenor 18M c_ij[7,0]=c_ij[7,3]=c_ij[7,5]=c_ij[7,6]=c_ij[7,7]=c_i[7] c_ij[7,8]=1+c_i[7] c_ij[7,0:15]

Out[62]: array([-0.09325, 0. , 0. , -0.09325, 0. , -0.09325, -0.09325, -0.09325, 0.90675, 0. , 0. , 0. , 0. , 0. , 0. ])

In [63]: # for the tenor 21M c_ij[8,0]=c_ij[8,3]=c_ij[8,5]=c_ij[8,6]=c_ij[8,7]=c_ij[8,8]=c_i[8] c_ij[8,9]=1+c_i[8] c_ij[8,0:15]

Out[63]: array([-0.09425, 0. , 0. , -0.09425, 0. , -0.09425, -0.09425, -0.09425, -0.09425, 0.90575, 0. , 0. , 0. , 0. , 0. ])

In [64]: # for the tenor 2Y c_ij[9,0]=c_ij[9,3]=c_ij[9,5]=c_ij[9,6]=c_ij[9,7]=c_ij[9,8]=c_ij[9, 9]=c_i[9] c_ij[9,10]=1+c_i[9] c_ij[9,0:15]

Out[64]: array([-0.095, 0. , 0. , -0.095, 0. , -0.095, -0.095, -0. 095, -0.095, -0.095, 0.905, 0. , 0. , 0. , 0. ])

file:///Users/pennyandersson/Downloads/SWE3.html Sida 20 av 145 SWE3 2020-10-07 8:21 fm

In [65]: # for the tenor 3Y-50Y for i in range(10,26): c_ij[i,0]=c_ij[i,3]=c_ij[i,5]=c_ij[i,6]=c_ij[i,7]=c_ij[i,8]=c_i j[i,9]=c_ij[i,10]=c_i[i] c_ij

Out[65]: array([[-0.062 , 0. , 0. , ..., 0. , 0. , 0. ], [ 0. , -0.0675 , 0. , ..., 0. , 0. , 0. ], [ 0. , 0. , -0.07475, ..., 0. , 0. , 0. ], ..., [ 0.023 , 0. , 0. , ..., 0. , 0. , 0. ], [ 0.004 , 0. , 0. , ..., 0. , 0. , 0. ], [-0.01325, 0. , 0. , ..., 0. , 0. , 0. ]])

file:///Users/pennyandersson/Downloads/SWE3.html Sida 21 av 145 SWE3 2020-10-07 8:21 fm

In [66]: # some last cash flows for tenor 3Y-50Y c_ij[10,11:14]=c_i[10] # 3Y c_ij[10,14]=1+c_i[10] c_ij[11,11:18]=c_i[11] # 4Y c_ij[11,18]=1+c_i[11] c_ij[12,11:22]=c_i[12] # 5Y c_ij[12,22]=1+c_i[12] c_ij[13,11:26]=c_i[13] # 6Y c_ij[13,26]=1+c_i[13] c_ij[14,11:30]=c_i[14] # 7Y c_ij[14,30]=1+c_i[14] c_ij[15,11:34]=c_i[15] # 8Y c_ij[15,34]=1+c_i[15] c_ij[16,11:38]=c_i[16] # 9Y c_ij[16,38]=1+c_i[16] c_ij[17,11:42]=c_i[17] # 10Y c_ij[17,42]=1+c_i[17] c_ij[18,11:46]=c_i[18] # 11Y c_ij[18,46]=1+c_i[18] c_ij[19,11:50]=c_i[19] # 12Y c_ij[19,50]=1+c_i[19]

c_ij[20,11:62]=c_i[20] # 15Y c_ij[20,62]=1+c_i[20]

c_ij[21,11:82]=c_i[21] # 20Y c_ij[21,82]=1+c_i[21]

c_ij[22,11:102]=c_i[22] # 25Y c_ij[22,102]=1+c_i[22]

c_ij[23,11:122]=c_i[23] # 30Y c_ij[23,122]=1+c_i[23]

c_ij[24,11:162]=c_i[24] # 40Y c_ij[24,162]=1+c_i[24]

c_ij[25,11:202]=c_i[25] # 50Y c_ij[25,202]=1+c_i[25]

file:///Users/pennyandersson/Downloads/SWE3.html Sida 22 av 145 SWE3 2020-10-07 8:21 fm

In [67]: c_ij # NxJ cash-flow matrix

Out[67]: array([[-0.062 , 0. , 0. , ..., 0. , 0. , 0. ], [ 0. , -0.0675 , 0. , ..., 0. , 0. , 0. ], [ 0. , 0. , -0.07475, ..., 0. , 0. , 0. ], ..., [ 0.023 , 0. , 0. , ..., 0. , 0. , 0. ], [ 0.004 , 0. , 0. , ..., 0. , 0. , 0. ], [-0.01325, 0. , 0. , ..., -0.01325, -0.01325, 0. 98675]])

In [68]: c_ij.shape

Out[68]: (26, 203)

In [69]: t_i=np.array(E3Data.loc[3:29,'Days 2']/365) # the maturities of cou pon bonds in years t_i

Out[69]: array([ 0.25479452, 0.34246575, 0.42465753, 0.50684932, 0.5917 8082, 1.00547945, 1.25479452, 1.51232877, 1.76164384, 2.0109 589 , 3.00821918, 4.00821918, 5.00821918, 6.00821918, 7.0082 1918, 8.01369863, 9.0109589 , 10.0109589 , 11.0109589 , 12.0136 9863, 15.01369863, 20.01917808, 25.02465753, 30.03013699, 40.0328 7671, 50.03835616])

In [70]: t_i.shape

Out[70]: (26,)

In [71]: t1_=np.zeros((26,203)) t1_.shape

Out[71]: (26, 203)

file:///Users/pennyandersson/Downloads/SWE3.html Sida 23 av 145 SWE3 2020-10-07 8:21 fm

In [72]: t1_[:,0]=t_i t1_

Out[72]: array([[ 0.25479452, 0. , 0. , ..., 0. , 0. , 0. ], [ 0.34246575, 0. , 0. , ..., 0. , 0. , 0. ], [ 0.42465753, 0. , 0. , ..., 0. , 0. , 0. ], ..., [30.03013699, 0. , 0. , ..., 0. , 0. , 0. ], [40.03287671, 0. , 0. , ..., 0. , 0. , 0. ], [50.03835616, 0. , 0. , ..., 0. , 0. , 0. ]])

In [73]: for y in range (1,203): # computer NxJ time matrix t1_[:,y]=t_i t1_

Out[73]: array([[ 0.25479452, 0.25479452, 0.25479452, ..., 0.25479452, 0.25479452, 0.25479452], [ 0.34246575, 0.34246575, 0.34246575, ..., 0.34246575, 0.34246575, 0.34246575], [ 0.42465753, 0.42465753, 0.42465753, ..., 0.42465753, 0.42465753, 0.42465753], ..., [30.03013699, 30.03013699, 30.03013699, ..., 30.03013699, 30.03013699, 30.03013699], [40.03287671, 40.03287671, 40.03287671, ..., 40.03287671, 40.03287671, 40.03287671], [50.03835616, 50.03835616, 50.03835616, ..., 50.03835616, 50.03835616, 50.03835616]])

In [74]: t1_Mat=t1_.T t1_Mat

Out[74]: array([[ 0.25479452, 0.34246575, 0.42465753, ..., 30.03013699, 40.03287671, 50.03835616], [ 0.25479452, 0.34246575, 0.42465753, ..., 30.03013699, 40.03287671, 50.03835616], [ 0.25479452, 0.34246575, 0.42465753, ..., 30.03013699, 40.03287671, 50.03835616], ..., [ 0.25479452, 0.34246575, 0.42465753, ..., 30.03013699, 40.03287671, 50.03835616], [ 0.25479452, 0.34246575, 0.42465753, ..., 30.03013699, 40.03287671, 50.03835616], [ 0.25479452, 0.34246575, 0.42465753, ..., 30.03013699, 40.03287671, 50.03835616]])

file:///Users/pennyandersson/Downloads/SWE3.html Sida 24 av 145 SWE3 2020-10-07 8:21 fm

In [75]: t2_Mat=np.zeros((203,26)) t2_Mat.shape

Out[75]: (203, 26)

In [76]: t2_Mat[:,0]=u_a t2_Mat

Out[76]: array([[ 0.25 , 0. , 0. , ..., 0. , 0. , 0. ], [ 0.33333333, 0. , 0. , ..., 0. , 0. , 0. ], [ 0.41666667, 0. , 0. , ..., 0. , 0. , 0. ], ..., [49.5 , 0. , 0. , ..., 0. , 0. , 0. ], [49.75 , 0. , 0. , ..., 0. , 0. , 0. ], [50. , 0. , 0. , ..., 0. , 0. , 0. ]])

In [77]: for z in range (1,26): # computer JxN time matrix t2_Mat[:,z]=u_a t2_Mat

Out[77]: array([[ 0.25 , 0.25 , 0.25 , ..., 0.25 , 0.25 , 0.25 ], [ 0.33333333, 0.33333333, 0.33333333, ..., 0.33333333, 0.33333333, 0.33333333], [ 0.41666667, 0.41666667, 0.41666667, ..., 0.41666667, 0.41666667, 0.41666667], ..., [49.5 , 49.5 , 49.5 , ..., 49.5 , 49.5 , 49.5 ], [49.75 , 49.75 , 49.75 , ..., 49.75 , 49.75 , 49.75 ], [50. , 50. , 50. , ..., 50. , 50. , 50. ]])

In [78]: t2_Mat.shape

Out[78]: (203, 26)

In [79]: # The market prices of the N par swap input instruments are taken a s unit (i.e. 1) M=np.ones(N) M.shape

Out[79]: (26,)

file:///Users/pennyandersson/Downloads/SWE3.html Sida 25 av 145 SWE3 2020-10-07 8:21 fm

Test the appropriateness of alpha

In [80]: d2=-omega*u_a d2

Out[80]: array([-0.00920349, -0.01227132, -0.01533916, -0.01840699, -0.0214 7482, -0.02761048, -0.03681397, -0.04601747, -0.05522096, -0.0644 2445, -0.07362795, -0.08283144, -0.09203493, -0.10123843, -0.1104 4192, -0.11964541, -0.12884891, -0.1380524 , -0.14725589, -0.1564 5939, -0.16566288, -0.17486637, -0.18406987, -0.19327336, -0.2024 7685, -0.21168035, -0.22088384, -0.23008733, -0.23929083, -0.2484 9432, -0.25769781, -0.26690131, -0.2761048 , -0.28530829, -0.2945 1178, -0.30371528, -0.31291877, -0.32212226, -0.33132576, -0.3405 2925, -0.34973274, -0.35893624, -0.36813973, -0.37734322, -0.3865 4672, -0.39575021, -0.4049537 , -0.4141572 , -0.42336069, -0.4325 6418, -0.44176768, -0.45097117, -0.46017466, -0.46937816, -0.4785 8165, -0.48778514, -0.49698864, -0.50619213, -0.51539562, -0.5245 9912, -0.53380261, -0.5430061 , -0.5522096 , -0.56141309, -0.5706 1658, -0.57982008, -0.58902357, -0.59822706, -0.60743056, -0.6166 3405, -0.62583754, -0.63504104, -0.64424453, -0.65344802, -0.6626 5152, -0.67185501, -0.6810585 , -0.690262 , -0.69946549, -0.7086 6898, -0.71787248, -0.72707597, -0.73627946, -0.74548296, -0.7546 8645, -0.76388994, -0.77309344, -0.78229693, -0.79150042, -0.8007 0392, -0.80990741, -0.8191109 , -0.8283144 , -0.83751789, -0.8467 2138, -0.85592488, -0.86512837, -0.87433186, -0.88353535, -0.8927 3885, -0.90194234, -0.91114583, -0.92034933, -0.92955282, -0.9387 5631, -0.94795981, -0.9571633 , -0.96636679, -0.97557029, -0.9847 7378, -0.99397727, -1.00318077, -1.01238426, -1.02158775, -1.0307 9125, file:///Users/pennyandersson/Downloads/SWE3.html Sida 26 av 145 SWE3 2020-10-07 8:21 fm

In [82]: dd2 = np.diag(d2) dd2

Out[82]: array([[-0.00920349, 0. , 0. , ..., 0. , 0. , 0. ], [ 0. , -0.01227132, 0. , ..., 0. , 0. , 0. ], [ 0. , 0. , -0.01533916, ..., 0. , 0. , 0. ], ..., [ 0. , 0. , 0. , ..., -1.82229167, 0. , 0. ], [ 0. , 0. , 0. , ..., 0. , -1.83149516, 0. ], [ 0. , 0. , 0. , ..., 0. , 0. , -1.84069866]])

In [83]: dd2.shape

Out[83]: (203, 203)

In [84]: Q2=dd2@c_ij.T Q2

Out[84]: array([[ 5.70616583e-04, 0.00000000e+00, 0.00000000e+00, ..., -2.11680345e-04, -3.68139731e-05, 1.21946286e-04], [ 0.00000000e+00, 8.28314395e-04, 0.00000000e+00, ..., 0.00000000e+00, 0.00000000e+00, 0.00000000e+00], [ 0.00000000e+00, 0.00000000e+00, 1.14660187e-03, ..., 0.00000000e+00, 0.00000000e+00, 0.00000000e+00], ..., [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, ..., 0.00000000e+00, 0.00000000e+00, 2.41453646e-02], [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, ..., 0.00000000e+00, 0.00000000e+00, 2.42673109e-02], [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, ..., 0.00000000e+00, 0.00000000e+00, -1.81630940e+00]])

In [85]: Q2.shape

Out[85]: (203, 26)

file:///Users/pennyandersson/Downloads/SWE3.html Sida 28 av 145 SWE3 2020-10-07 8:21 fm

In [86]: q2=d2@c_ij.T q2

Out[86]: array([ 5.70616583e-04, 8.28314395e-04, 1.14660187e-03, 1.48176 242e-03, 1.86294043e-03, -2.88299427e-02, -3.34892112e-02, -3.71982 190e-02, -4.01364342e-02, -4.21519992e-02, -4.38592472e-02, -3.89859 975e-02, -3.42830125e-02, -3.38228378e-02, -4.37764158e-02, -7.09773 402e-02, -1.18324711e-01, -1.90788416e-01, -2.91060475e-01, -4.20121 061e-01, -9.48005825e-01, -1.90668770e+00, -2.54706677e+00, -2.64121 850e+00, -1.94672290e+00, 6.10421692e-01])

In [87]: q2.shape

Out[87]: (26,)

In [88]: sinh2=0.5*(np.exp(alpha0*u_a)-np.exp(-alpha0*u_a)) sinh2

file:///Users/pennyandersson/Downloads/SWE3.html Sida 29 av 145 SWE3 2020-10-07 8:21 fm

In [90]: H2=(alpha0*(t1_Mat+t2_Mat)+np.exp(-alpha0*(t1_Mat+t2_Mat))-alpha0*n p.abs(t1_Mat-t2_Mat)-np.exp(-alpha0*np.abs(t1_Mat-t2_Mat)))/2 H2

Out[90]: array([[1.57915088e-04, 2.11898971e-04, 2.62294393e-04, ..., 9.71500010e-03, 1.08110436e-02, 1.14758768e-02], [2.10230232e-04, 2.82200108e-04, 3.49395365e-04, ..., 1.29532583e-02, 1.44146791e-02, 1.53011413e-02], [2.62327853e-04, 3.52225303e-04, 4.36213051e-04, ..., 1.61914519e-02, 1.80182756e-02, 1.91263822e-02], ..., [1.16674836e-02, 1.56820702e-02, 1.94457200e-02, ..., 1.32200178e+00, 1.69587551e+00, 1.99172702e+00], [1.16808032e-02, 1.56999732e-02, 1.94679205e-02, ..., 1.32423163e+00, 1.69967382e+00, 1.99806200e+00], [1.16939573e-02, 1.57176539e-02, 1.94898451e-02, ..., 1.32643378e+00, 1.70342495e+00, 2.00432050e+00]])

In [91]: H2.shape

Out[91]: (203, 26)

In [92]: ww=Q2.T@[email protected] ww.shape

Out[92]: (26, 203)

In [93]: b2=np.matrix(ww).I@(M-q2) b2

Out[93]: matrix([[ 7.46544074e+12, 4.75984105e+12, -2.99000368e+12, -5.96377362e+12, 3.50114754e+12, 3.31459157e+10, -7.84767210e+10, -1.05765984e+11, -8.63011786e+10, -8.58010200e+10, -8.28496928e+10, 1.00195283e+10, 1.11328194e+10, 1.22461009e+10, -5.66605365e+10, 7.43709023e+09, 8.00921411e+09, 8.58129236e+09, -4.13841961e+10, 5.08073003e+09, 5.37960473e+09, 5.67847039e+09, -3.09322138e+10, 3.27269712e+09, 3.42854081e+09, 3.58438119e+09, -2.34853999e+10, 1.97467843e+09, 2.05367477e+09, 2.13264616e+09, -1.76958243e+10, 1.11023107e+09, 1.14850572e+09, 1.18677211e+09, -1.28851081e+10, 5.94026031e+08, 6.11998899e+08, 6.30033263e+08, -8.90139474e+09, 3.24908846e+08, 3.33728706e+08, 3.42494705e+08, -5.52513782e+09, 2.18531501e+08, 2.23838460e+08, 2.29142937e+08, -2.69744611e+09, 2.02398129e+08, 2.06844031e+08, 2.11440301e+08, -3.95192350e+08, 2.19067143e+08, 2.23566306e+08, 2.28066824e+08, 2.32530428e+08, 2.37017992e+08, 2.41499294e+08, 2.45881980e+08, 2.50384168e+08, 2.54852539e+08, 2.59332349e+08, 2.63818445e+08, 3.57474009e+09, 1.93758262e+08, 1.96945588e+08, 2.00149137e+08,

file:///Users/pennyandersson/Downloads/SWE3.html Sida 31 av 145 SWE3 2020-10-07 8:21 fm

In [95]: kappa2=(1+alpha0*[email protected]@b2.T)/b2.T*sinh2.T@Q2 kappa2

Out[95]: matrix([[-1.95248054e-18, -3.77907114e-18, -6.53918805e-18, ..., 1.17005935e-12, 1.71622039e-12, 1.04552670e-12], [-3.06231398e-18, -5.92717936e-18, -1.02562082e-17, ..., 1.83514716e-12, 2.69175830e-12, 1.63982737e-12], [ 4.87495313e-18, 9.43558426e-18, 1.63270438e-17, ..., -2.92140402e-12, -4.28505883e-12, -2.61047091e-12], ..., [-2.12203209e-12, -4.10724208e-12, -7.10704491e-12, ..., 1.27166619e-06, 1.86525534e-06, 1.13631924e-06], [-2.10852311e-12, -4.08109514e-12, -7.06180106e-12, ..., 1.26357069e-06, 1.85338102e-06, 1.12908537e-06], [ 2.83265314e-14, 5.48266552e-14, 9.48703518e-14, ..., -1.69751874e-08, -2.48988760e-08, -1.51684713e-08]])

In [96]: kappa2.shape

Out[96]: (203, 26)

In [97]: g2=alpha0/np.abs(1-kappa2*np.exp(alpha0*T)) g2 # all elements in g is greater than tau, therefore we should cho ose g=tau, alpha > a

Out[97]: matrix([[0.05 , 0.05 , 0.05 , ..., 0.05 , 0.05 , 0.05 ], [0.05 , 0.05 , 0.05 , ..., 0.05 , 0.05 , 0.05 ], [0.05 , 0.05 , 0.05 , ..., 0.05 , 0.05 , 0.05 ], ..., [0.05 , 0.05 , 0.05 , ..., 0.05000128, 0.05 000187, 0.05000114], [0.05 , 0.05 , 0.05 , ..., 0.05000127, 0.05 000186, 0.05000113], [0.05 , 0.05 , 0.05 , ..., 0.04999998, 0.04 999997, 0.04999998]])

In [98]: g2.shape

Out[98]: (203, 26)

file:///Users/pennyandersson/Downloads/SWE3.html Sida 33 av 145 SWE3 2020-10-07 8:21 fm

In [99]: matrix = np.ones((203,26)) matrix.shape

Out[99]: (203, 26)

In [100]: Tau=matrix*tau Tau

Out[100]: array([[0.0001, 0.0001, 0.0001, ..., 0.0001, 0.0001, 0.0001], [0.0001, 0.0001, 0.0001, ..., 0.0001, 0.0001, 0.0001], [0.0001, 0.0001, 0.0001, ..., 0.0001, 0.0001, 0.0001], ..., [0.0001, 0.0001, 0.0001, ..., 0.0001, 0.0001, 0.0001], [0.0001, 0.0001, 0.0001, ..., 0.0001, 0.0001, 0.0001], [0.0001, 0.0001, 0.0001, ..., 0.0001, 0.0001, 0.0001]])

In [101]: # test when alpha = 0.05, if the convergence gap g<=0.0001 for i in range(203): for j in range(26): if g2[i,j]-Tau[i,j]<=0: print('True') else: print('False')

# the constraint is unfullfilled, the alpha=0.05 is not appropriate .Thus alpha should greater than 0.05

False False False False False False False False False False False False False False False False False False False False False False False False False

file:///Users/pennyandersson/Downloads/SWE3.html Sida 34 av 145 SWE3 2020-10-07 8:21 fm

False False False False False False False False False False

In [102]: # vi assume alph1=0.123 alpha1=0.123760

In [103]: def ufr_discount_factor(ufr: float, t2: np.array) -> np.array: """Calculate Ultimate Forward Rate (UFR) discount factors. Takes the UFR with a vector of maturities and returns for each of the maturities the discount factor d_UFR = e^(-UFR * t)

Args: ufr: Ultimate Forward Rate (annualized/annual compounding) t2=u_a: cash-flow payment dates (in years) of length J Returns: UFR discount factors as vector of length J """ # Convert annualized ultimate forward rate to log-return ufr = np.log(1 + ufr) return np.exp(-ufr * t2)

file:///Users/pennyandersson/Downloads/SWE3.html Sida 133 av 145 SWE3 2020-10-07 8:21 fm

In [104]: def wilson_function(t1: np.matrix, t2: np.matrix, alpha: float, ufr : float) -> np.array: """Calculate matrix of Wilson functions The Smith-Wilson method requires the calculation of a series of Wilson functions. The Wilson function is calculated for each maturity combination t1 and t2. If t1 and t2 are scalars, the result is a scalar. If t1 and t2 are vectors of shape (m, 1) and (n, 1), then the result is a ma trix of Wilson functions with shape (m, n): W = e^(-UFR * (t1 + t2)) * (α * min(t1, t2) - 0.5 * e^(-α * max(t1, t2)) * (e^(α * min(t1, t2)) - e^(-α * min(t1, t2))))

Args: t1=t_i: time to maturity vector of length N t2=u_a: cash-flow payments dates vector of length J alpha: Convergence speed parameter ufr: Ultimate Forward Rate (continuously compounding) Returns: Wilson-matrix of shape (N, J) as numpy matrix """

# Calculate the minimum and maximum of the two matrices min_t = np.minimum(t1_Mat, t2_Mat) max_t = np.maximum(t1_Mat, t2_Mat)

# Calculate the UFR discount factor ufr_disc = ufr_discount_factor(ufr=ufr, t2=(t1_Mat + t2_Mat)) h=(alpha * min_t - 0.5 * np.exp(-alpha * max_t) * (np.exp(alpha * min_t) - np.exp(-alpha * min_t))) h=h.T W = ufr_disc @ h

return W

file:///Users/pennyandersson/Downloads/SWE3.html Sida 134 av 145 SWE3 2020-10-07 8:21 fm

In [105]: W2=wilson_function(t1_Mat, t2_Mat, alpha1, ufr) W2

Out[105]: array([[ 0.22579338, 0.30099669, 0.37614859, ..., 14.46638634, 14.47167139, 14.47680059], [ 0.22510174, 0.3000747 , 0.3749964 , ..., 14.42207391, 14.42734278, 14.43245627], [ 0.22441223, 0.29915553, 0.37384774, ..., 14.37789722, 14.38314995, 14.38824777], ..., [ 0.03683808, 0.04910747, 0.06136846, ..., 2.36018404, 2.36104629, 2.36188312], [ 0.0365006 , 0.04865758, 0.06080625, ..., 2.33856175, 2.33941611, 2.34024527], [ 0.03616621, 0.04821181, 0.06024919, ..., 2.31713756, 2.31798408, 2.31880565]])

In [106]: W2.shape

Out[106]: (203, 203)

file:///Users/pennyandersson/Downloads/SWE3.html Sida 135 av 145 SWE3 2020-10-07 8:21 fm

In [107]: def fit_parameters(rates: np.array, t1: np.array, t2:np.array, alph a: float, ufr: float) -> np.ndarray: """Calculate Smith-Wilson parameter vector ζ Given the Wilson-matrix, vector of discount factors and prices, the parameter vector can be calculated as follows: ζ =(CWC^T)^-1 * (M - Cμ)

rates=r: Observed quarter coupon/swap rates vector of lengt h N t1=t_i: time to maturity vector of length N t2=u_a: Observed time to maturity vector (in years) of leng th J alpha: Convergence speed parameter ufr: Ultimate Forward Rate (continuously compounding) Returns: Wilson-matrix of shape (N, J) as numpy matrix """

# Calcualte square matrix of Wilson functions, UFR discount vec tor and price vector # The price vector is calculated with zero-coupon rates and ass umed face value of 1 # For the estimation of zeta, t1 and t2 correspond both to the observed maturities

W = wilson_function(t1=t1_Mat, t2=t2_Mat, alpha=alpha, ufr=ufr) mu = ufr_discount_factor(ufr=ufr, t2=u_a)

# Calculate vector of parameters # To invert the Wilson-matrix, conversion to type matrix is req uired zeta = c_ij/100@W@c_ij.T/100@(M-c_ij/100@mu) zeta = np.array(zeta) # Convert back to more general array type

return zeta

In [108]: zeta2=fit_parameters(r, t_i, u_a, alpha1, ufr) zeta2

Out[108]: array([-0.00100417, -0.0010899 , -0.00120327, -0.00129186, -0.0013 8789, 0.01021186, 0.00839523, 0.00661106, 0.00492989, 0.0032 6411, -0.00250847, -0.00683159, -0.00943701, -0.01063196, -0.0103 5993, -0.00857 , -0.00559039, -0.00148348, 0.00354418, 0.0092 462 , 0.02703888, 0.04398782, 0.04373821, 0.03260351, 0.0091 986 , -0.01711288])

file:///Users/pennyandersson/Downloads/SWE3.html Sida 136 av 145 SWE3 2020-10-07 8:21 fm

In [109]: zeta2.shape

Out[109]: (26,)

In [110]: def fit_smithwilson_rates(rates_obs: np.array, t_obs: np.array, t_t arget: np.array, alpha: float, ufr: float) -> np.arr ay: """Calculate zero-coupon yields with Smith-Wilson method based on observed rates. This function expects the rates and initial maturity vector to be before the Last Liquid Point (LLP). The targeted maturity vecto r can contain both, more granular maturity structure (interpolation) or terms after the LLP (extrapolation). The Smith-Wilson method calculated first the Wilson-matrix: W = e^(-UFR * (t1 + t2)) * (α * min(t1, t2) - 0.5 * e^(-α * max(t1, t2)) * (e^(α * min(t1, t2)) - e^(-α * min(t1, t2)))) Given the Wilson-matrix, vector of discount factors and prices, the parameter vector can be calculated as follows: zeta =(CWC^T)^-1 * (m - Cμ) With the Smith-Wilson parameter and Wilson-matrix, the zero-cou pon bond prices can be represented as in matrix notation: M = C * mu + (CWC.T) * zets M : market price of par swap input instruments C = c_ij: NxJ cash-flow matrix In the last case, t can be any maturity vector

Args: rates_obs=r: Initially observed quarter coupon rates vector before LLP of length N t_target=t_i: Initially observed time to maturity vector (i n years) of length N t_obs=u_a: cash-flow payment dates (in years) of length J alpha: Convergence speed parameter ufr: Ultimate Forward Rate (continuously compounding) Returns: Vector of zero-coupon rates with Smith-Wilson interpolated or extrapolated rates """

# Convert list to numpy array and use reshape to convert from 1 -d to 2-d array # E.g. reshape((-1, 1)) converts an input of shape (10,) with s econd dimension # being empty (1-d vector) to shape (10, 1) where second dimens ion is 1 (2-d vector) rates_obs = np.array(rates_obs).reshape((-1, 1)) t_obs = np.array(t_obs).reshape((-1, 1)) file:///Users/pennyandersson/Downloads/SWE3.html Sida 137 av 145 SWE3 2020-10-07 8:21 fm

t_target = np.array(t_target).reshape((-1, 1))

zeta = fit_parameters(rates=rates_obs, t1=t_target, t2=t_obs, a lpha=alpha, ufr=ufr) ufr_disc = ufr_discount_factor(ufr=ufr, t2=t_i) W = wilson_function(t1=t_target, t2=t_obs, alpha=alpha, ufr=ufr )

#Price vector - equivalent to discounting with zero-coupon yiel ds 1/(1 + r)^t # for prices where t_obs = t_target. All other matuirites are i nterpolated or extrapolated

tr= W [:,-1]@ c_ij.T * zeta.T

p=ufr_disc+tr

# Transform price vector to coupon rate vector (1/P)^(1/t) - 1 return np.power(1/p, 1/t_i) - 1

In [111]: sp=fit_smithwilson_rates(r, u_a, t_i, alpha1, ufr) sp.shape

Out[111]: (26,)

In [112]: import matplotlib.pyplot as plt %matplotlib inline

In [113]: E3Data.loc[3:29,'Spot']=sp E3Data.head()

Out[113]: Measured From Days Days Name Quote To date TTM Spot date date 1 2

EURIBOR 2020- 2020- 0 -0.518 2020-04-14 7 9 0.024658 -0.519346 S/W 04-16 04-23

EURIBOR 2020- 2020- -0.404 2020-04-14 32 34 0.093151 -0.404818 1 1M 04-16 05-18

EURIBOR 2020- 2020- NaN 2020-04-14 61 63 0.172603 -0.327859 2 2M 04-16 06-16

EURIBOR 2020- 2020- -0.248 2020-04-14 91 93 0.254795 0.033804 3 3M 04-16 07-16

EUR 1X4 2020- 2020- -0.270 2020-04-14 123 125 0.342466 0.034249 4 FRA 04-16 08-17

file:///Users/pennyandersson/Downloads/SWE3.html Sida 138 av 145 SWE3 2020-10-07 8:21 fm

In [114]: plt.figure(figsize=(15, 6))

Out[114]:

In [115]: plt.plot(E3Data['TTM'], E3Data['Spot'], 'o-c', label= 'Spot rate', lw=1.5) plt.grid(True) plt.xlabel('Term(years)') plt.ylabel('Yield') plt.title('The yield curve for 3-months Euribor by Smith-Wilson at 2020-04-14 (Table 3.9)') plt.legend()

Out[115]:

file:///Users/pennyandersson/Downloads/SWE3.html Sida 139 av 145 SWE3 2020-10-07 8:21 fm

In [116]: # get discount factors for all tenors for l in range(0,29): E3Data.loc[l,'Discount']=np.exp(E3Data.loc[l,'Spot']/(-100)*E3D ata.loc[l,'Days 2']/360).copy() E3Data.Discount[:29]

Out[116]: 0 1.000130 1 1.000382 2 1.000574 3 0.999913 4 0.999881 5 0.999852 6 0.999823 7 0.999793 8 1.000546 9 1.000178 10 0.999845 11 0.999570 12 0.999343 13 0.998923 14 0.998970 15 0.999049 16 0.998953 17 0.998557 18 0.997840 19 0.996979 20 0.996231 21 0.995997 22 0.996615 23 1.002077 24 1.007905 25 1.007477 26 1.002505 27 0.987844 28 0.991173 Name: Discount, dtype: float64

In [117]: plt.figure(figsize=(15, 6))

Out[117]:

file:///Users/pennyandersson/Downloads/SWE3.html Sida 140 av 145 SWE3 2020-10-07 8:21 fm

In [118]: plt.plot(E3Data['TTM'], E3Data['Discount'], 'o-y', label= 'SW disco unt factors', lw=1.5) plt.grid(True) plt.xlabel('Term(years)') plt.ylabel('Discount factor') plt.title('The discount factors for 3-monts Euribor by Smith-Wilson technique at 2020-04-14 (Table 3.9)')

Out[118]: Text(0.5, 1.0, 'The discount factors for 3-monts Euribor by Smith- Wilson technique at 2020-04-14')

In [119]: E3Data.loc[0,'Forward']=(1-E3Data.loc[0,'Discount'])/E3Data.loc[0,' Discount']*36000 /9 # assign forward rate for over-night to first r ow of 'Forward' E3Data.head()

Out[119]: Measured From To Days Days Name Quote TTM Spot Discount date date date 1 2

EURIBOR 2020-04- 2020- 2020- 0 -0.518 7 9 0.024658 -0.519346 1.000130 S/W 14 04-16 04-23

EURIBOR 2020-04- 2020- 2020- -0.404 32 34 0.093151 -0.404818 1.000382 1 1M 14 04-16 05-18

EURIBOR 2020-04- 2020- 2020- NaN 61 63 0.172603 -0.327859 1.000574 2 2M 14 04-16 06-16

EURIBOR 2020-04- 2020- 2020- -0.248 91 93 0.254795 0.033804 0.999913 3 3M 14 04-16 07-16

EUR 1X4 2020-04- 2020- 2020- -0.270 123 125 0.342466 0.034249 0.999881 4 FRA 14 04-16 08-17

file:///Users/pennyandersson/Downloads/SWE3.html Sida 141 av 145 SWE3 2020-10-07 8:21 fm

In [120]: E3Data['Days 2'].shift(1).head()

Out[120]: 0 NaN 1 9.0 2 34.0 3 63.0 4 93.0 Name: Days 2, dtype: float64

In [121]: E3Data['DeltaT'] = E3Data['Days 2'] - E3Data['Days 2'].shift(1) # g et delta time=time difference

In [122]: E3Data.head()

Out[122]: Measured From To Days Days Name Quote TTM Spot Discount date date date 1 2

EURIBOR 2020-04- 2020- 2020- 0 -0.518 7 9 0.024658 -0.519346 1.000130 S/W 14 04-16 04-23

EURIBOR 2020-04- 2020- 2020- -0.404 32 34 0.093151 -0.404818 1.000382 1 1M 14 04-16 05-18

EURIBOR 2020-04- 2020- 2020- NaN 61 63 0.172603 -0.327859 1.000574 2 2M 14 04-16 06-16

EURIBOR 2020-04- 2020- 2020- -0.248 91 93 0.254795 0.033804 0.999913 3 3M 14 04-16 07-16

EUR 1X4 2020-04- 2020- 2020- -0.270 123 125 0.342466 0.034249 0.999881 4 FRA 14 04-16 08-17

In [123]: # get forward rates for all tenors for f in range(1,29): E3Data.loc[f,'Forward']=(E3Data.loc[f-1,'Discount']-E3Data.loc[ f,'Discount'])/E3Data.loc[f,'Discount']*36000/E3Data.loc[f,'DeltaT' ].copy() E3Data.Forward[:29]

file:///Users/pennyandersson/Downloads/SWE3.html Sida 142 av 145 SWE3 2020-10-07 8:21 fm

Out[123]: 0 -0.519313 1 -0.363542 2 -0.237608 3 0.793557 4 0.035545 5 0.034488 6 0.034916 7 0.034579 8 -0.179266 9 0.145414 10 0.127582 11 0.108965 12 0.089899 13 0.041587 14 -0.004708 15 -0.007779 16 0.009520 17 0.039041 18 0.070561 19 0.085344 20 0.074115 21 0.023136 22 -0.060934 23 -0.179231 24 -0.113936 25 0.008379 26 0.097727 27 0.146338 28 -0.033106 Name: Forward, dtype: float64

file:///Users/pennyandersson/Downloads/SWE3.html Sida 143 av 145 SWE3 2020-10-07 8:21 fm

In [124]: plt.plot(E3Data['TTM'], E3Data['Spot'], 'o-c', label= 'Spot rate', lw=1.5) plt.plot(E3Data['TTM'], E3Data['Forward'],'o-m', label= 'Forward ra te', lw=1.5) plt.grid(True) plt.xlabel('Term(years)') plt.ylabel('Yield') plt.title('The yield curve for 3-months Euribor by Smith-Wilson at 2020-04-14 (Table 3.9)') plt.legend()

Out[124]:

In [125]: E3Data.head()

Out[125]: Measured From To Days Days Name Quote TTM Spot Discount date date date 1 2

EURIBOR 2020-04- 2020- 2020- 0 -0.518 7 9 0.024658 -0.519346 1.000130 S/W 14 04-16 04-23

EURIBOR 2020-04- 2020- 2020- -0.404 32 34 0.093151 -0.404818 1.000382 1 1M 14 04-16 05-18

EURIBOR 2020-04- 2020- 2020- NaN 61 63 0.172603 -0.327859 1.000574 2 2M 14 04-16 06-16

EURIBOR 2020-04- 2020- 2020- -0.248 91 93 0.254795 0.033804 0.999913 3 3M 14 04-16 07-16

EUR 1X4 2020-04- 2020- 2020- -0.270 123 125 0.342466 0.034249 0.999881 4 FRA 14 04-16 08-17

In [126]: E3Data.to_excel(r'/Users/pennyandersson/Desktop/Analytical Finance/ thesis/my work/E3DataSW.xlsx', sheet_name='EoDataSW', index = False)

file:///Users/pennyandersson/Downloads/SWE3.html Sida 144 av 145 Appendix F

The calculation of 6-months Euribor with the Smith Wilson model in Python

191 SWE6 2020-10-07 8:22 fm

Applying Smith-Wilson technique to 6-months Euribor

In [1]: import pandas as pd import math import numpy as np

In [2]: # UFR rate for 2020 by EIOPA ufr=0.0375 alpha0=0.05 # the minst alpha

In [3]: LLP=20 # the last liquid point for a euro T=60 # the convergence point for a euro

In [4]: tau=0.0001 # the convergence tolerance

In [5]: E6Data = pd.read_csv('E6DataSW per 2020-04-14.csv', sep=';') #impor t 6-months Euribor rates index E6Data.tail()

Out[5]: Name Quote Measured date From date To date Days

38 EUR 27Y IRS 0.135 2020-04-14 2020-04-16 2047-04-16 9863

39 EUR 28Y IRS 0.124 2020-04-14 2020-04-16 2048-04-16 10229

40 EUR 29Y IRS 0.113 2020-04-14 2020-04-16 2049-04-16 10594

41 EUR 30Y IRS 0.102 2020-04-14 2020-04-16 2050-04-18 10961

42 EUR 40Y IRS 0.020 2020-04-14 2020-04-16 2060-04-16 14612

Solve the following optimal problem in order to get the ! (! should be ≥ 0.05) "#$#"#%& !

\ '()*&+, ,- ! ≥ 0.05 \ ! . .(!) = ≤ / = 0.0001, ! = 0.05 |1 − 0&!1 | where

′ 1 + ! 2) file:///Users/pennyandersson/Downloads/SWE6.html 0 = Sida 1 av 107 SWE6 2020-10-07 8:22 fm

′ 1 + !( 2) 0 = ′ sin ℎ[!( ]2) \ !( !( ⎡ & 1 − &− 1 ⎤ ⎢ !( !( ⎥ 1 ⎢ & 2 − &− 2 ⎥ sin ℎ[!(] = ⎢ ⎥ , 2 ⎢ ⋮ ⎥ ! ! ⎣ & (" − &− (" ⎦ \

2 = 5Δ4 \ ! ( 7 !|( 8| !(( + 7) + &− ( + ) − !|( − 7| − &− − 6((, 7) = 2 \ ′ ) = (2 62)−1(9 − :) \ ; = log(1 + <=>) \ ;( ⎡ &− 1 ⎤ ⎢ ;( ⎥ ⎢ &− 2 ⎥ 5 = &?9[−;(] = ⎢ ⎥ ⎢ ⋮ ⎥ ⎣ &−;(@ ⎦

⟹ ;( ⎡ &− 1 0 ⋯ 0 ⎤ ⎢ ;( ⎥ 0 &− 2 ⋯ 0 5 ⎢ ⎥ Δ = ⎢ ⎥ ⎢ ⋮ ⋮ ⋱ ⋮ ⎥ ; ⎣ 0 0 ⋯ &− (@ ⎦ In this case, for 3-months Euribor rates, every tenor can be seen as a coupon bond. Frequence is every three months has a cash flow. Thus for each coupon bond has several cash flows. Therefore cash-flow matrix 4 is an NxJ cash flow matrix.

⟹ −;(1 ⎡ ⎤ ⎡ & 0 ⋯ 0 ⎤ +1,1 +1,2 ⋯ +1,* ⋯ +1,@ ⎢ ⎥ ⎢ ⎥ −;(2 0 & ⋯ 0 +2,1 +2,2 ⋯ +2,* ⋯ +2,@ 2 5 4 ⎢ ⎥ ⎢ ⎥ = Δ = ⎢ ⎥ ⎢ ⎥ ⎢ ⋮ ⋮ ⋱ ⋮ ⎥ ⎢ ⋮ ⋮ ⋱ ⋮ ⋮ ⋯ ⎥ ⎣ −;(@ ⎦ 0 0 ⋯ & ⎣ +A,1 +A,2 ⋯ +A,* ⋯ +A,@ ⎦ ⎡ : ⎤ ⎢ 1 ⎥ ⎢ :2 ⎥ ′ ′ : = ⎢ ⎥ = 2 ) = 4 5 ⎢ ⋮ ⎥ ⎣ :A ⎦

file:///Users/pennyandersson/Downloads/SWE6.html Sida 2 av 107 SWE6 2020-10-07 8:22 fm

where @ is the number of the observed duration to maturity or in other words the number of dates of cash-flow and A is the number of financial instruments.

In this case, ; is known therefore 2 is known.

Moreover, !'s lower bound is 0.05, then we can first test the appropriateness of !. When ! = 0.05 if the convergence gap .(!) ≤ / (/ = 0.0001) then ! = 0.05 is apposite in this case. Otherwise ! > 0.05 and .(!) = /.

since all maturities are over 6 months this case only incl. coupon bonds

In [6]: r_c=np.array(E6Data['Quote']) # swap rates r_c

Out[6]: array([-0.195, -0.223, -0.25 , -0.269, -0.288, -0.307, -0.316, -0. 326, -0.335, -0.337, -0.338, -0.339, -0.336, -0.294, -0.287, -0. 262, -0.227, -0.191, -0.154, -0.114, -0.075, -0.036, 0.003, 0. 04 , 0.075, 0.105, 0.13 , 0.15 , 0.164, 0.174, 0.18 , 0. 182, 0.181, 0.178, 0.172, 0.165, 0.156, 0.146, 0.135, 0. 124, 0.113, 0.102, 0.02 ])

In [7]: r_c.shape

Out[7]: (43,)

file:///Users/pennyandersson/Downloads/SWE6.html Sida 3 av 107 SWE6 2020-10-07 8:22 fm

In [8]: t_i=np.array(E6Data['Days']/365) # the maturities of zero coupon bo nds in years t_i

Out[8]: array([ 0.50684932, 0.59178082, 0.6739726 , 0.76438356, 0.8438 3562, 0.92054795, 1.00547945, 1.09041096, 1.17260274, 1.2547 9452, 1.33972603, 1.42465753, 1.51232877, 2.0109589 , 3.0082 1918, 4.00821918, 5.00821918, 6.00821918, 7.00821918, 8.0136 9863, 9.0109589 , 10.0109589 , 11.0109589 , 12.01369863, 13.0191 7808, 14.01643836, 15.01369863, 16.01643836, 17.01643836, 18.0164 3836, 19.02191781, 20.01917808, 21.01917808, 22.01917808, 23.0191 7808, 24.02739726, 25.02465753, 26.02191781, 27.02191781, 28.0246 5753, 29.02465753, 30.03013699, 40.03287671])

In [9]: t_i.shape

Out[9]: (43,)

In [10]: N=len(t_i) # the number of coupon bonds N

Out[10]: 43

Test the appropriateness of alpha

In [11]: omega=np.log(1 + ufr) # computer the ultimate forward intensity omega

Out[11]: 0.0368139731227164

In [12]: s=2 # frequence of payments/cash flows per year. Pay every 3 months .

file:///Users/pennyandersson/Downloads/SWE6.html Sida 4 av 107 SWE6 2020-10-07 8:22 fm

In [13]: c_i=r_c/s # the vector of semi swap rates c_i

Out[13]: array([-0.0975, -0.1115, -0.125 , -0.1345, -0.144 , -0.1535, -0.15 8 , -0.163 , -0.1675, -0.1685, -0.169 , -0.1695, -0.168 , -0.14 7 , -0.1435, -0.131 , -0.1135, -0.0955, -0.077 , -0.057 , -0.03 75, -0.018 , 0.0015, 0.02 , 0.0375, 0.0525, 0.065 , 0.07 5 , 0.082 , 0.087 , 0.09 , 0.091 , 0.0905, 0.089 , 0.08 6 , 0.0825, 0.078 , 0.073 , 0.0675, 0.062 , 0.0565, 0.05 1 , 0.01 ])

In [14]: c_i.shape

Out[14]: (43,)

In [15]: r=r_c/s/100 r

Out[15]: array([-9.750e-04, -1.115e-03, -1.250e-03, -1.345e-03, -1.440e-03, -1.535e-03, -1.580e-03, -1.630e-03, -1.675e-03, -1.685e-03, -1.690e-03, -1.695e-03, -1.680e-03, -1.470e-03, -1.435e-03, -1.310e-03, -1.135e-03, -9.550e-04, -7.700e-04, -5.700e-04, -3.750e-04, -1.800e-04, 1.500e-05, 2.000e-04, 3.750e-04, 5.250e-04, 6.500e-04, 7.500e-04, 8.200e-04, 8.700e-04, 9.000e-04, 9.100e-04, 9.050e-04, 8.900e-04, 8.600e-04, 8.250e-04, 7.800e-04, 7.300e-04, 6.750e-04, 6.200e-04, 5.650e-04, 5.100e-04, 1.000e-04])

file:///Users/pennyandersson/Downloads/SWE6.html Sida 5 av 107 SWE6 2020-10-07 8:22 fm

In [16]: # the tenor of 40Y IRS has J=40*2=80 (pay every 6 months), when th ere is no payment exchanging then cash-flow c=0 u_i=np.linspace(0.5,40.,80) u_i

Out[16]: array([ 0.5, 1. , 1.5, 2. , 2.5, 3. , 3.5, 4. , 4.5, 5. , 5.5, 6. , 6.5, 7. , 7.5, 8. , 8.5, 9. , 9.5, 10. , 10.5, 11. , 11.5, 12. , 12.5, 13. , 13.5, 14. , 14.5, 15. , 15.5, 16. , 16.5, 17. , 17.5, 18. , 18.5, 19. , 19.5, 20. , 20.5, 21. , 21.5, 22. , 22.5, 23. , 23.5, 24. , 24.5, 25. , 25.5, 26. , 26.5, 27. , 27.5, 28. , 28.5, 29. , 29.5, 30. , 30.5, 31. , 31.5, 32. , 32.5, 33. , 33.5, 34. , 34.5, 35. , 35.5, 36. , 36.5, 37. , 37.5, 38. , 38.5, 39. , 39.5, 40. ])

In [17]: l=list(u_i)

In [18]: # for FRA tenors, we have maturities in 7m, 8m, 9m, 10m, 11m,13m,14 m,15m,16m and 17m so we have extend payment dates l.insert(1,7/12) l.insert(2,8/12) l.insert(3,9/12) l.insert(4,10/12) l.insert(5,11/12) l.insert(7,13/12) l.insert(8,14/12) l.insert(9,15/12) l.insert(10,16/12) l.insert(11,17/12)

In [19]: l

Out[19]: [0.5, 0.5833333333333334, 0.6666666666666666, 0.75, 0.8333333333333334, 0.9166666666666666, 1.0, 1.0833333333333333, 1.1666666666666667, 1.25, 1.3333333333333333, 1.4166666666666667, 1.5, 2.0, file:///Users/pennyandersson/Downloads/SWE6.html Sida 6 av 107 SWE6 2020-10-07 8:22 fm

Out[20]: array([ 0.5 , 0.58333333, 0.66666667, 0.75 , 0.8333 3333, 0.91666667, 1. , 1.08333333, 1.16666667, 1.25 , 1.33333333, 1.41666667, 1.5 , 2. , 2.5 , 3. , 3.5 , 4. , 4.5 , 5. , 5.5 , 6. , 6.5 , 7. , 7.5 , 8. , 8.5 , 9. , 9.5 , 10. , 10.5 , 11. , 11.5 , 12. , 12.5 , 13. , 13.5 , 14. , 14.5 , 15. , 15.5 , 16. , 16.5 , 17. , 17.5 , 18. , 18.5 , 19. , 19.5 , 20. , 20.5 , 21. , 21.5 , 22. , 22.5 , 23. , 23.5 , 24. , 24.5 , 25. , 25.5 , 26. , 26.5 , 27. , 27.5 , 28. , 28.5 , 29. , 29.5 , 30. , 30.5 , 31. , 31.5 , 32. , 32.5 , 33. , 33.5 , 34. , 34.5 , 35. , 35.5 , 36. , 36.5 , 37. , 37.5 , 38. , 38.5 , 39. , 39.5 , 40. ])

In [21]: u_a.shape

Out[21]: (90,)

In [22]: J=len(u_a) J

Out[22]: 90

In [23]: c_ij=np.zeros((N,J)) c_ij.shape

Out[23]: (43, 90)

file:///Users/pennyandersson/Downloads/SWE6.html Sida 9 av 107 SWE6 2020-10-07 8:22 fm

In [24]: c_ij[0,0]=c_i[0] # for tenor 6M c_ij[0,0]

Out[24]: -0.0975

In [25]: # cash-flows for FRAs c_ij[1,1]=c_i[1] c_ij[2,2]=c_i[2] c_ij[3,3]=c_i[3] c_ij[4,4]=c_i[4]

c_ij[5,5]=c_i[5] c_ij[6,6]=c_i[6] c_ij[7,7]=c_i[7] c_ij[8,8]=c_i[8]

c_ij[9,9]=c_i[9] c_ij[10,10]=c_i[10] c_ij[11,11]=c_i[11] c_ij[12,12]=c_i[12]

In [26]: # for the tenor 2Y c_ij[13,0]=c_ij[13,3]=c_ij[13,6]=c_ij[13,12]=c_i[13] c_ij[13,13]=1+c_i[13] c_ij[13,0:30]

Out[26]: array([-0.147, 0. , 0. , -0.147, 0. , 0. , -0.147, 0. , 0. , 0. , 0. , 0. , -0.147, 0.853, 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ])

file:///Users/pennyandersson/Downloads/SWE6.html Sida 10 av 107 SWE6 2020-10-07 8:22 fm

In [27]: # for the tenor 3Y-40Y for i in range(14,43): c_ij[i,0]=c_ij[i,3]=c_ij[i,6]=c_ij[i,12]=c_i[i] c_ij

Out[27]: array([[-0.0975, 0. , 0. , ..., 0. , 0. , 0. ] , [ 0. , -0.1115, 0. , ..., 0. , 0. , 0. ] , [ 0. , 0. , -0.125 , ..., 0. , 0. , 0. ] , ..., [ 0.0565, 0. , 0. , ..., 0. , 0. , 0. ] , [ 0.051 , 0. , 0. , ..., 0. , 0. , 0. ] , [ 0.01 , 0. , 0. , ..., 0. , 0. , 0. ] ])

In [28]: x=np.array(range(16,92,2)) x

Out[28]: array([16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90])

In [29]: for i in range(14,43): for j in range(16,90,2): c_ij[i,13:j]=c_i[i] c_ij[i,j]=1+c_i[i]

In [30]: c_ij

Out[30]: array([[-0.0975, 0. , 0. , ..., 0. , 0. , 0. ] , [ 0. , -0.1115, 0. , ..., 0. , 0. , 0. ] , [ 0. , 0. , -0.125 , ..., 0. , 0. , 0. ] , ..., [ 0.0565, 0. , 0. , ..., 0.0565, 1.0565, 0. ] , [ 0.051 , 0. , 0. , ..., 0.051 , 1.051 , 0. ] , [ 0.01 , 0. , 0. , ..., 0.01 , 1.01 , 0. ] ])

file:///Users/pennyandersson/Downloads/SWE6.html Sida 11 av 107 SWE6 2020-10-07 8:22 fm

In [31]: c_ij[42,89]=1+c_i[42] c_ij # NxJ cash-flow matrix

Out[31]: array([[-0.0975, 0. , 0. , ..., 0. , 0. , 0. ] , [ 0. , -0.1115, 0. , ..., 0. , 0. , 0. ] , [ 0. , 0. , -0.125 , ..., 0. , 0. , 0. ] , ..., [ 0.0565, 0. , 0. , ..., 0.0565, 1.0565, 0. ] , [ 0.051 , 0. , 0. , ..., 0.051 , 1.051 , 0. ] , [ 0.01 , 0. , 0. , ..., 0.01 , 1.01 , 1.01 ] ])

In [32]: t1_=np.zeros((43,90)) t1_.shape

Out[32]: (43, 90)

In [33]: t1_[:,0]=t_i t1_

Out[33]: array([[ 0.50684932, 0. , 0. , ..., 0. , 0. , 0. ], [ 0.59178082, 0. , 0. , ..., 0. , 0. , 0. ], [ 0.6739726 , 0. , 0. , ..., 0. , 0. , 0. ], ..., [29.02465753, 0. , 0. , ..., 0. , 0. , 0. ], [30.03013699, 0. , 0. , ..., 0. , 0. , 0. ], [40.03287671, 0. , 0. , ..., 0. , 0. , 0. ]])

file:///Users/pennyandersson/Downloads/SWE6.html Sida 12 av 107 SWE6 2020-10-07 8:22 fm

In [34]: for y in range (1,90): # computer NxJ time matrix t1_[:,y]=t_i t1_

Out[34]: array([[ 0.50684932, 0.50684932, 0.50684932, ..., 0.50684932, 0.50684932, 0.50684932], [ 0.59178082, 0.59178082, 0.59178082, ..., 0.59178082, 0.59178082, 0.59178082], [ 0.6739726 , 0.6739726 , 0.6739726 , ..., 0.6739726 , 0.6739726 , 0.6739726 ], ..., [29.02465753, 29.02465753, 29.02465753, ..., 29.02465753, 29.02465753, 29.02465753], [30.03013699, 30.03013699, 30.03013699, ..., 30.03013699, 30.03013699, 30.03013699], [40.03287671, 40.03287671, 40.03287671, ..., 40.03287671, 40.03287671, 40.03287671]])

In [35]: t1_Mat=t1_.T t1_Mat

Out[35]: array([[ 0.50684932, 0.59178082, 0.6739726 , ..., 29.02465753, 30.03013699, 40.03287671], [ 0.50684932, 0.59178082, 0.6739726 , ..., 29.02465753, 30.03013699, 40.03287671], [ 0.50684932, 0.59178082, 0.6739726 , ..., 29.02465753, 30.03013699, 40.03287671], ..., [ 0.50684932, 0.59178082, 0.6739726 , ..., 29.02465753, 30.03013699, 40.03287671], [ 0.50684932, 0.59178082, 0.6739726 , ..., 29.02465753, 30.03013699, 40.03287671], [ 0.50684932, 0.59178082, 0.6739726 , ..., 29.02465753, 30.03013699, 40.03287671]])

In [36]: t1_Mat.shape

Out[36]: (90, 43)

In [37]: t2_Mat=np.zeros((90,43)) t2_Mat.shape

Out[37]: (90, 43)

file:///Users/pennyandersson/Downloads/SWE6.html Sida 13 av 107 SWE6 2020-10-07 8:22 fm

In [38]: t2_Mat[:,0]=u_a t2_Mat

Out[38]: array([[ 0.5 , 0. , 0. , ..., 0. , 0. , 0. ], [ 0.58333333, 0. , 0. , ..., 0. , 0. , 0. ], [ 0.66666667, 0. , 0. , ..., 0. , 0. , 0. ], ..., [39. , 0. , 0. , ..., 0. , 0. , 0. ], [39.5 , 0. , 0. , ..., 0. , 0. , 0. ], [40. , 0. , 0. , ..., 0. , 0. , 0. ]])

In [39]: for z in range (1,43): # computer JxN time matrix t2_Mat[:,z]=u_a t2_Mat

Out[39]: array([[ 0.5 , 0.5 , 0.5 , ..., 0.5 , 0.5 , 0.5 ], [ 0.58333333, 0.58333333, 0.58333333, ..., 0.58333333, 0.58333333, 0.58333333], [ 0.66666667, 0.66666667, 0.66666667, ..., 0.66666667, 0.66666667, 0.66666667], ..., [39. , 39. , 39. , ..., 39. , 39. , 39. ], [39.5 , 39.5 , 39.5 , ..., 39.5 , 39.5 , 39.5 ], [40. , 40. , 40. , ..., 40. , 40. , 40. ]])

In [40]: t2_Mat.shape

Out[40]: (90, 43)

In [41]: # The market prices of the N par swap input instruments are taken a s unit (i.e. 1) M=np.ones(N) M.shape

Out[41]: (43,)

file:///Users/pennyandersson/Downloads/SWE6.html Sida 14 av 107 SWE6 2020-10-07 8:22 fm

In [42]: sinh=0.5*(np.exp(alpha0*u_a)-np.exp(-alpha0*u_a)) sinh

Out[42]: array([0.0250026 , 0.0291708 , 0.03333951, 0.03750879, 0.04167872, 0.04584938, 0.05002084, 0.05419316, 0.05836642, 0.0625407 , 0.06671606, 0.07089258, 0.07507033, 0.10016675, 0.12532578, 0.15056313, 0.1758946 , 0.201336 , 0.22690325, 0.25261232, 0.27847928, 0.30452029, 0.33075165, 0.35718973, 0.38385107, 0.41075233, 0.43791032, 0.46534202, 0.49306457, 0.52109531, 0.54945174, 0.5781516 , 0.60721283, 0.63665358, 0.66649226, 0.69674753, 0.72743828, 0.7585837 , 0.79020327, 0.82231673, 0.85494417, 0.88810598, 0.92182289, 0.95611596, 0.99100664, 1.02651673, 1.06266842, 1.09948432, 1.13698743, 1.17520119, 1.2141495 , 1.25385668, 1.29434757, 1.33564747, 1.37778219, 1.42077807, 1.46466198, 1.50946136, 1.55520419, 1.60191908, 1.64963522, 1.69838244, 1.7481912 , 1.79909264, 1.85111856, 1.9043015 , 1.95867469, 2.01427211, 2.07112852, 2.12927946, 2.18876126, 2.2496111 , 2.31186703, 2.37556795, 2.44075368, 2.50746496, 2.57574348, 2.64563193, 2.71717399, 2.79041437, 2.86539884, 2.94217429, 3.02078869, 3.10129118, 3.18373208, 3.26816291, 3.35463645, 3.44320675, 3.53392917, 3.62686041] )

In [43]: sinh.shape

Out[43]: (90,)

In [44]: d=-omega*u_a d

file:///Users/pennyandersson/Downloads/SWE6.html Sida 15 av 107 SWE6 2020-10-07 8:22 fm

In [46]: dd = np.diag(d) dd

Out[46]: array([[-0.01840699, 0. , 0. , ..., 0. , 0. , 0. ], [ 0. , -0.02147482, 0. , ..., 0. , 0. , 0. ], [ 0. , 0. , -0.02454265, ..., 0. , 0. , 0. ], ..., [ 0. , 0. , 0. , ..., -1.43574495, 0. , 0. ], [ 0. , 0. , 0. , ..., 0. , -1.45415194, 0. ], [ 0. , 0. , 0. , ..., 0. , 0. , -1.47255892]])

In [47]: dd.shape

Out[47]: (90, 90)

In [48]: Q=dd@c_ij.T Q

Out[48]: array([[ 1.79468119e-03, 0.00000000e+00, 0.00000000e+00, ..., -1.03999474e-03, -9.38756315e-04, -1.84069866e-04], [ 0.00000000e+00, 2.39444217e-03, 0.00000000e+00, ..., 0.00000000e+00, 0.00000000e+00, 0.00000000e+00], [ 0.00000000e+00, 0.00000000e+00, 3.06783109e-03, ..., 0.00000000e+00, 0.00000000e+00, 0.00000000e+00], ..., [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, ..., -8.11195898e-02, -7.32229925e-02, -1.43574495e-02], [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, ..., -1.53631152e+00, -1.52831369e+00, -1.46869346e+00], [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, ..., 0.00000000e+00, 0.00000000e+00, -1.48728451e+00]])

In [49]: Q.shape

Out[49]: (90, 43)

file:///Users/pennyandersson/Downloads/SWE6.html Sida 17 av 107 SWE6 2020-10-07 8:22 fm

In [50]: q=d@c_ij.T q

Out[50]: array([ 1.79468119e-03, 2.39444217e-03, 3.06783109e-03, 3.71360 954e-03, 4.41767677e-03, 5.18003280e-03, 5.81660775e-03, 6.50073 409e-03, 7.19406391e-03, 7.75394309e-03, 8.29541528e-03, 8.83995 530e-03, 9.27712123e-03, -4.25109355e-02, 6.89664229e+00, 6.16922 119e+00, 5.15083165e+00, 4.10334527e+00, 3.02676204e+00, 1.86288 828e+00, 7.28111362e-01, -4.06665554e-01, -1.54144247e+00, -2.61802 570e+00, -3.63641524e+00, -4.50932056e+00, -5.23674166e+00, -5.81867 854e+00, -6.22603436e+00, -6.51700280e+00, -6.69158386e+00, -6.74977 755e+00, -6.72068070e+00, -6.63339017e+00, -6.45880911e+00, -6.25513 120e+00, -5.99325960e+00, -5.70229116e+00, -5.38222588e+00, -5.06216 060e+00, -4.74209531e+00, -4.42203003e+00, -3.52337333e+00])

In [51]: q.shape

Out[51]: (43,)

In [52]: H=(alpha0*(t1_Mat+t2_Mat)+np.exp(-alpha0*(t1_Mat+t2_Mat))-alpha0*np .abs(t1_Mat-t2_Mat)-np.exp(-alpha0*np.abs(t1_Mat-t2_Mat)))/2 H

Out[52]: array([[6.23061946e-04, 7.26360962e-04, 8.25910948e-04, ..., 1.91423581e-02, 1.94295650e-02, 2.16218232e-02], [7.25845175e-04, 8.46355905e-04, 9.62501924e-04, ..., 2.23324941e-02, 2.26675814e-02, 2.52253122e-02], [8.28201038e-04, 9.65867925e-04, 1.09860324e-03, ..., 2.55225114e-02, 2.59054850e-02, 2.88287327e-02], ..., [2.17365040e-02, 2.53786734e-02, 2.89032813e-02, ..., 1.16425950e+00, 1.19806092e+00, 1.48477802e+00], [2.18255355e-02, 2.54826278e-02, 2.90216789e-02, ..., 1.17134490e+00, 1.20555303e+00, 1.49752024e+00], [2.19123688e-02, 2.55840155e-02, 2.91371533e-02, ..., 1.17825536e+00, 1.21286016e+00, 1.50996402e+00]])

In [53]: H.shape

Out[53]: (90, 43)

file:///Users/pennyandersson/Downloads/SWE6.html Sida 18 av 107 SWE6 2020-10-07 8:22 fm

In [54]: ww=Q.T@[email protected] ww.shape

Out[54]: (43, 90)

In [55]: b=np.matrix(ww).I@(M-q) b

Out[55]: matrix([[ 1.24880103e+11, 1.00134556e+11, 2.48591598e+10, -6.47551578e+10, -9.04185067e+10, -3.93977983e+10, 5.25358751e+10, 6.13005148e+10, -2.00163715e+10, -5.53427886e+10, 1.38341878e+10, 4.26162587e+10, -2.37938460e+10, 2.56556215e+09, 3.15166360e+07, -2.44911251e+09, -1.49557879e+08, -7.19455029e+07, 6.61761110e+07, 2.64886276e+07, 4.12367383e+07, -8.12854731e+07, -1.32472936e+08, -2.43547051e+07, -1.08261532e+06, -1.15054429e+08, -2.73672335e+07, -7.33455237e+07, -1.65964600e+08, -2.27524457e+07, -6.20629196e+07, -1.29358915e+08, 2.19645325e+07, -2.91353278e+07, 4.56951666e+07, 1.28474528e+07, 3.11753788e+06, 2.34512626e+07, -3.00660077e+06, -3.47639763e+07, -2.82970968e+07, -4.95398171e+07, -1.01828532e+07, -1.49935586e+07, -5.65804559e+06, -2.72960404e+07, 6.83423834e+06, -1.82578572e+07, -5.45697483e+07, 2.91764408e+07, 2.73535029e+07, 1.00426653e+08, -2.38202055e+07, -9.73139021e+07, 2.40629117e+07, 4.39290649e+07, -1.69777952e+07, -5.82706557e+07, -9.14002062e+07, 9.13903332e+07, -6.13260744e+07, 2.56949056e+07, 1.55263771e+07, 6.23507577e+06, 1.35161261e+07, 4.69025251e+07, -4.45202326e+07, -6.01320155e+06, -3.34364579e+07, -6.95279527e+07, -1.41416110e+08, -5.65941936e+07, -9.12182158e+07, -9.90796343e+07, 1.03949324e+08, -2.03657064e+07, 5.96631359e+06, -2.99871173e+07, 5.92957954e+07, -1.13160912e+07, 8.90916972e+06, -5.45920807e+07, -4.06432644e+07, 1.36684767e+07, 1.27938851e+07, -3.65157144e+07, 2.57015479e+07, -1.09139497e+08, -3.26217681e+03, 2.70261721e+03]])

In [56]: b.shape

Out[56]: (1, 90)

file:///Users/pennyandersson/Downloads/SWE6.html Sida 19 av 107 SWE6 2020-10-07 8:22 fm

In [57]: kappa=(1+alpha0*[email protected]@b.T)/b.T*sinh.T@Q kappa

Out[57]: matrix([[ 9.81088948e-15, 1.52717410e-14, 2.23628133e-14, ..., -2.50881551e-09, -2.37396944e-09, -2.54815217e-09], [ 1.22353855e-14, 1.90457387e-14, 2.78891777e-14, ..., -3.12880140e-09, -2.96063177e-09, -3.17785906e-09], [ 4.92850483e-14, 7.67176609e-14, 1.12339695e-13, ..., -1.26030462e-08, -1.19256463e-08, -1.28006541e-08], ..., [-1.12258617e-11, -1.74743026e-11, -2.55880824e-11, ..., 2.87064857e-06, 2.71635437e-06, 2.91565855e-06], [-3.75572803e-07, -5.84620853e-07, -8.56075740e-07, ..., 9.60405145e-02, 9.08784425e-02, 9.75463699e-02], [ 4.53332749e-07, 7.05662859e-07, 1.03332074e-06, ..., -1.15925088e-01, -1.09694243e-01, -1.17742722e-01]])

In [58]: kappa.shape

Out[58]: (90, 43)

In [59]: g=alpha0/np.abs(1-kappa*np.exp(alpha0*T)) g # all elements in g is greater than tau, therefore we should choo se g=tau, alpha > a

Out[59]: matrix([[0.05 , 0.05 , 0.05 , ..., 0.05 , 0.05 , 0.05 ], [0.05 , 0.05 , 0.05 , ..., 0.05 , 0.05 , 0.05 ], [0.05 , 0.05 , 0.05 , ..., 0.04999999, 0.04 999999, 0.04999999], ..., [0.05 , 0.05 , 0.05 , ..., 0.05000288, 0.05 000273, 0.05000293], [0.04999962, 0.04999941, 0.04999914, ..., 0.05381985, 0.06 058092, 0.0521229 ], [0.05000046, 0.05000071, 0.05000104, ..., 0.01502215, 0.01 560906, 0.01485917]])

In [60]: g.shape

Out[60]: (90, 43)

file:///Users/pennyandersson/Downloads/SWE6.html Sida 20 av 107 SWE6 2020-10-07 8:22 fm

In [61]: matrix = np.ones((90,43)) matrix.shape

Out[61]: (90, 43)

In [62]: Tau=matrix*tau Tau

Out[62]: array([[0.0001, 0.0001, 0.0001, ..., 0.0001, 0.0001, 0.0001], [0.0001, 0.0001, 0.0001, ..., 0.0001, 0.0001, 0.0001], [0.0001, 0.0001, 0.0001, ..., 0.0001, 0.0001, 0.0001], ..., [0.0001, 0.0001, 0.0001, ..., 0.0001, 0.0001, 0.0001], [0.0001, 0.0001, 0.0001, ..., 0.0001, 0.0001, 0.0001], [0.0001, 0.0001, 0.0001, ..., 0.0001, 0.0001, 0.0001]])

In [63]: # test when alpha = 0.05, if the convergence gap g<=0.0001 for i in range(90): for j in range(43): if g[i,j]-Tau[i,j]<=0: print('True') else: print('False')

# the constraint is unfullfilled, the alpha=0.05 is not appropriate .Thus alpha should greater than 0.05

False False False False False False False False False False False False False False False False False False False False False False False False False

file:///Users/pennyandersson/Downloads/SWE6.html Sida 21 av 107 SWE6 2020-10-07 8:22 fm

False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False

In [64]: # vi assume alph1=0.123 alpha1=0.123760

file:///Users/pennyandersson/Downloads/SWE6.html Sida 93 av 107 SWE6 2020-10-07 8:22 fm

In [65]: def ufr_discount_factor(ufr: float, t2: np.array) -> np.array: """Calculate Ultimate Forward Rate (UFR) discount factors. Takes the UFR with a vector of maturities and returns for each of the maturities the discount factor d_UFR = e^(-UFR * t)

Args: ufr: Ultimate Forward Rate (annualized/annual compounding) t2=u_a: cash-flow payment dates (in years) of length J Returns: UFR discount factors as vector of length J """ # Convert annualized ultimate forward rate to log-return ufr = np.log(1 + ufr) return np.exp(-ufr * t2)

file:///Users/pennyandersson/Downloads/SWE6.html Sida 94 av 107 SWE6 2020-10-07 8:22 fm

In [66]: def wilson_function(t1: np.matrix, t2: np.matrix, alpha: float, ufr : float) -> np.array: """Calculate matrix of Wilson functions The Smith-Wilson method requires the calculation of a series of Wilson functions. The Wilson function is calculated for each maturity combination t1 and t2. If t1 and t2 are scalars, the result is a scalar. If t1 and t2 are vectors of shape (m, 1) and (n, 1), then the result is a ma trix of Wilson functions with shape (m, n): W = e^(-UFR * (t1 + t2)) * (α * min(t1, t2) - 0.5 * e^(-α * max(t1, t2)) * (e^(α * min(t1, t2)) - e^(-α * min(t1, t2))))

Args: t1=t_i: time to maturity vector of length N t2=u_a: cash-flow payments dates vector of length J alpha: Convergence speed parameter ufr: Ultimate Forward Rate (continuously compounding) Returns: Wilson-matrix of shape (N, J) as numpy matrix """

# Calculate the minimum and maximum of the two matrices min_t = np.minimum(t1_Mat, t2_Mat) max_t = np.maximum(t1_Mat, t2_Mat)

# Calculate the UFR discount factor ufr_disc = ufr_discount_factor(ufr, t2=t1_Mat + t2_Mat) h=(alpha * min_t - 0.5 * np.exp(-alpha * max_t) * (np.exp(alpha * min_t) - np.exp(-alpha * min_t))) h=h.T W = ufr_disc @ h

return W

file:///Users/pennyandersson/Downloads/SWE6.html Sida 95 av 107 SWE6 2020-10-07 8:22 fm

In [67]: W=wilson_function(t1_Mat, t2_Mat, alpha1, ufr) W

Out[67]: array([[ 0.83198465, 0.97038894, 1.10867431, ..., 29.5470874 , 29.58973783, 29.62988185], [ 0.82943617, 0.96741652, 1.1052783 , ..., 29.45658083, 29.49910062, 29.53912166], [ 0.8268955 , 0.96445319, 1.10189268, ..., 29.36635149, 29.40874103, 29.44863949], ..., [ 0.20163841, 0.23518184, 0.26869645, ..., 7.16098262, 7.17131931, 7.18104854], [ 0.1979608 , 0.23089245, 0.2637958 , ..., 7.03037623, 7.04052439, 7.05007618], [ 0.19435027, 0.22668129, 0.25898453, ..., 6.90215192, 6.91211499, 6.92149257]])

In [68]: W.shape

Out[68]: (90, 90)

file:///Users/pennyandersson/Downloads/SWE6.html Sida 96 av 107 SWE6 2020-10-07 8:22 fm

In [69]: def fit_parameters(rates: np.array, t1: np.array, t2:np.array, alph a: float, ufr: float) -> np.ndarray: """Calculate Smith-Wilson parameter vector ζ Given the Wilson-matrix, vector of discount factors and prices, the parameter vector can be calculated as follows: ζ =(CWC^T)^-1 * (M - Cμ)

rates=r: Observed quarter coupon/swap rates vector of lengt h N t1=t_i: time to maturity vector of length N t2=u_a: Observed time to maturity vector (in years) of leng th J alpha: Convergence speed parameter ufr: Ultimate Forward Rate (continuously compounding) Returns: Wilson-matrix of shape (N, J) as numpy matrix """

# Calcualte square matrix of Wilson functions, UFR discount vec tor and price vector # The price vector is calculated with zero-coupon rates and ass umed face value of 1 # For the estimation of zeta, t1 and t2 correspond both to the observed maturities

W = wilson_function(t1=t1_Mat, t2=t2_Mat, alpha=alpha, ufr=ufr) mu = ufr_discount_factor(ufr=ufr, t2=u_a)

# Calculate vector of parameters # To invert the Wilson-matrix, conversion to type matrix is req uired zeta = c_ij/100@W@c_ij.T/100@(M-c_ij/100@mu) zeta = np.array(zeta) # Convert back to more general array type

return zeta

file:///Users/pennyandersson/Downloads/SWE6.html Sida 97 av 107 SWE6 2020-10-07 8:22 fm

In [70]: zeta=fit_parameters(r, t_i, u_a, alpha1, ufr) zeta

Out[70]: array([-0.01817073, -0.02071621, -0.02315331, -0.02483665, -0.0265 0946, -0.02817179, -0.02890885, -0.02973233, -0.03045958, -0.0305 4757, -0.03054436, -0.03054089, -0.0301779 , 0.04258744, -1.1059 4271, -1.00574355, -0.86546472, -0.72117793, -0.57288317, -0.4125 6451, -0.25625381, -0.09994312, 0.05636758, 0.20466234, 0.3449 4116, 0.46518016, 0.56537932, 0.64553865, 0.70165018, 0.7417 2985, 0.76577765, 0.77379358, 0.76978561, 0.75776171, 0.7337 1391, 0.70565815, 0.66958645, 0.62950678, 0.58541915, 0.5413 3152, 0.49724389, 0.45315626, 0.16847326])

In [72]: zeta.shape

Out[72]: (43,)

In [75]: def fit_smithwilson_rates(rates_obs: np.array, t_obs: np.array, t_t arget: np.array, alpha: float, ufr: float) -> np.arr ay: """Calculate zero-coupon yields with Smith-Wilson method based on observed rates. This function expects the rates and initial maturity vector to be before the Last Liquid Point (LLP). The targeted maturity vecto r can contain both, more granular maturity structure (interpolation) or terms after the LLP (extrapolation). The Smith-Wilson method calculated first the Wilson-matrix: W = e^(-UFR * (t1 + t2)) * (α * min(t1, t2) - 0.5 * e^(-α * max(t1, t2)) * (e^(α * min(t1, t2)) - e^(-α * min(t1, t2)))) Given the Wilson-matrix, vector of discount factors and prices, the parameter vector can be calculated as follows: zeta =(CWC^T)^-1 * (m - Cμ) With the Smith-Wilson parameter and Wilson-matrix, the zero-cou pon bond prices can be represented as in matrix notation: M = C * mu + (CWC.T) * zets M : market price of par swap input instruments C = c_ij: NxJ cash-flow matrix In the last case, t can be any maturity vector

file:///Users/pennyandersson/Downloads/SWE6.html Sida 98 av 107 SWE6 2020-10-07 8:22 fm

Args: rates_obs=r: Initially observed quarter coupon rates vector before LLP of length N t_target=t_i: Initially observed time to maturity vector (i n years) of length N t_obs=u_a: cash-flow payment dates (in years) of length J alpha: Convergence speed parameter ufr: Ultimate Forward Rate (continuously compounding) Returns: Vector of zero-coupon rates with Smith-Wilson interpolated or extrapolated rates """

# Convert list to numpy array and use reshape to convert from 1 -d to 2-d array # E.g. reshape((-1, 1)) converts an input of shape (10,) with s econd dimension # being empty (1-d vector) to shape (10, 1) where second dimens ion is 1 (2-d vector) rates_obs = np.array(rates_obs).reshape((-1, 1)) t_obs = np.array(t_obs).reshape((-1, 1)) t_target = np.array(t_target).reshape((-1, 1))

zeta = fit_parameters(rates=rates_obs, t1=t_target, t2=t_obs, a lpha=alpha, ufr=ufr) ufr_disc = ufr_discount_factor(ufr=ufr, t2=t_i) W = wilson_function(t1=t_target, t2=t_obs, alpha=alpha, ufr=ufr )

#Price vector - equivalent to discounting with zero-coupon yiel ds 1/(1 + r)^t # for prices where t_obs = t_target. All other matuirites are i nterpolated or extrapolated

tr= W [:,-1]@ c_ij.T *zeta.T

p=ufr_disc+tr

# Transform price vector to coupon rate vector (1/P)^(1/t) - 1 return np.power(1/p, 1/t_target) - 1

file:///Users/pennyandersson/Downloads/SWE6.html Sida 99 av 107 SWE6 2020-10-07 8:22 fm

In [76]: sp=fit_smithwilson_rates(r, u_a, t_i, alpha1, ufr) sp

Out[76]: array([[-6.38506885e-02, -8.60827441e-02, -1.09798985e-01, ..., -9.99297515e-01, -9.98989457e-01, -9.53611254e-01], [-5.49438169e-02, -7.41993861e-02, -9.48147254e-02, ..., -9.98008395e-01, -9.97280704e-01, -9.27921272e-01], [-4.84083993e-02, -6.54539623e-02, -8.37512454e-02, ..., -9.95748241e-01, -9.94411083e-01, -9.00665770e-01], ..., [-1.15153154e-03, -1.57067568e-03, -2.02899192e-03, ..., -1.19085566e-01, -1.13474174e-01, -5.22103884e-02], [-1.11299702e-03, -1.51812571e-03, -1.96112317e-03, ..., -1.15337793e-01, -1.09891790e-01, -5.05071844e-02], [-8.35016254e-04, -1.13901820e-03, -1.47147153e-03, ..., -8.78299240e-02, -8.36208801e-02, -3.81315463e-02]])

In [77]: sp.shape

Out[77]: (43, 43)

In [78]: import matplotlib.pyplot as plt %matplotlib inline

In [80]: plt.figure(figsize=(15, 6))

Out[80]:

In [81]: E6Data['Days'].shift(1).head()

Out[81]: 0 NaN 1 185.0 2 216.0 3 246.0 4 279.0 Name: Days, dtype: float64

In [82]: E6Data['DeltaT'] = E6Data['Days'] - E6Data['Days'].shift(1) # get d elta time=time difference

In [83]: E6Data['TTM']=E6Data['Days']/365 E6Data.loc[0,'DeltaT']=187

file:///Users/pennyandersson/Downloads/SWE6.html Sida 100 av 107 SWE6 2020-10-07 8:22 fm

In [93]: E6Data['Spot']=sp[:,-1]/100 E6Data.head()

Out[93]: Measured From To Name Quote Days DeltaT TTM Spot Discount date date date

EURIBOR 2020-04- 2020- 2020- 0 -0.195 185 187.0 0.506849 -0.009536 1.0 6M 14 04-16 10-16

EUR 1X7 2020-04- 2020- 2020- -0.223 216 31.0 0.591781 -0.009279 1.0 1 FRA 14 04-16 11-16

EUR 2X8 2020-04- 2020- 2020- -0.250 246 30.0 0.673973 -0.009007 1.0 2 FRA 14 04-16 12-16

EUR 3X9 2020-04- 2020- 2021- -0.269 279 33.0 0.764384 -0.008695 1.0 3 FRA 14 04-16 01-18

EUR 2020-04- 2020- 2021- 4X10 -0.288 308 29.0 0.843836 -0.008419 1.0 4 14 04-16 02-16 FRA

In [94]: plt.plot(E6Data['TTM'], E6Data['Spot'], 'o-c', label= 'Spot rate', lw=1.5) plt.grid(True) plt.xlabel('Term(years)') plt.ylabel('Yield') plt.title('The yield curve for 6-months Euribor by Smith-Wilson at 2020-04-14 (Table 4.0)') plt.legend()

Out[94]:

file:///Users/pennyandersson/Downloads/SWE6.html Sida 101 av 107 SWE6 2020-10-07 8:22 fm

In [100]: # get discount factors for all tenors for l in range(0,43): E6Data.loc[l,'Discount']=np.exp(-(E6Data.loc[l,'Spot']/100)*E6D ata.loc[l,'Days']/360).copy() E6Data.Discount[:43]

Out[100]: 0 1.000049 1 1.000056 2 1.000062 3 1.000067 4 1.000072 5 1.000076 6 1.000080 7 1.000084 8 1.000087 9 1.000090 10 1.000093 11 1.000096 12 1.000099 13 1.000110 14 1.000123 15 1.000131 16 1.000136 17 1.000139 18 1.000142 19 1.000143 20 1.000145 21 1.000146 22 1.000147 23 1.000148 24 1.000149 25 1.000149 26 1.000150 27 1.000150 28 1.000151 29 1.000151 30 1.000152 31 1.000152 32 1.000152 33 1.000152 34 1.000153 35 1.000153 36 1.000153 37 1.000153 38 1.000153 39 1.000154 40 1.000154 41 1.000154 42 1.000155 Name: Discount, dtype: float64

file:///Users/pennyandersson/Downloads/SWE6.html Sida 102 av 107 SWE6 2020-10-07 8:22 fm

In [101]: plt.plot(E6Data['TTM'], E6Data['Discount'], 'o-y', label= 'SW disco unt factors', lw=1.5) plt.grid(True) plt.xlabel('Term(years)') plt.ylabel('Discount factor') plt.title('The discount factors for 6-monts Euribor by Smith-Wilson technique at 2020-04-14 (Table 4.0)') plt.legend()

Out[101]:

In [102]: # get the forward rate for tenor Euribor 6M E6Data.loc[0,'Forward']=(1-E6Data.loc[0,'Discount'])/E6Data.loc[0,' Discount']*36000/E6Data.loc[0,'DeltaT'].copy() E6Data.head()

Out[102]: Measured From To Name Quote Days DeltaT TTM Spot Discount date date date

EURIBOR 2020-04- 2020- 2020- 0 -0.195 185 187.0 0.506849 -0.009536 1.000049 6M 14 04-16 10-16

EUR 1X7 2020-04- 2020- 2020- -0.223 216 31.0 0.591781 -0.009279 1.000056 1 FRA 14 04-16 11-16

EUR 2X8 2020-04- 2020- 2020- -0.250 246 30.0 0.673973 -0.009007 1.000062 2 FRA 14 04-16 12-16

EUR 3X9 2020-04- 2020- 2021- -0.269 279 33.0 0.764384 -0.008695 1.000067 3 FRA 14 04-16 01-18

EUR 2020-04- 2020- 2021- 4X10 -0.288 308 29.0 0.843836 -0.008419 1.000072 4 14 04-16 02-16 FRA

file:///Users/pennyandersson/Downloads/SWE6.html Sida 103 av 107 SWE6 2020-10-07 8:22 fm

In [103]: # get forward rates for all tenors for f in range(1,43): E6Data.loc[f,'Forward']=(E6Data.loc[f-1,'Discount']-E6Data.loc[ f,'Discount'])/E6Data.loc[f,'Discount']*36000/E6Data.loc[f,'DeltaT' ].copy() E6Data.Forward[:43]

Out[103]: 0 -0.009434 1 -0.007746 2 -0.007044 3 -0.006369 4 -0.005765 5 -0.005266 6 -0.004805 7 -0.004374 8 -0.003998 9 -0.003671 10 -0.003374 11 -0.003106 12 -0.002864 13 -0.002238 14 -0.001319 15 -0.000747 16 -0.000480 17 -0.000334 18 -0.000245 19 -0.000188 20 -0.000149 21 -0.000120 22 -0.000100 23 -0.000084 24 -0.000071 25 -0.000061 26 -0.000054 27 -0.000047 28 -0.000042 29 -0.000037 30 -0.000033 31 -0.000030 32 -0.000027 33 -0.000025 34 -0.000023 35 -0.000021 36 -0.000019 37 -0.000018 38 -0.000017 39 -0.000015 40 -0.000014 41 -0.000013 42 -0.000010 Name: Forward, dtype: float64

file:///Users/pennyandersson/Downloads/SWE6.html Sida 104 av 107 SWE6 2020-10-07 8:22 fm

In [104]: plt.plot(E6Data['TTM'], E6Data['Discount'], 'o-y', label= 'SW disco unt factors', lw=1.5) plt.grid(True) plt.xlabel('Term(years)') plt.ylabel('Discount factor') plt.title('The discount factors for 6-monts Euribor by Smith-Wilson technique at 2020-04-14 (Table 4.0)') plt.legend()

Out[104]:

file:///Users/pennyandersson/Downloads/SWE6.html Sida 105 av 107 SWE6 2020-10-07 8:22 fm

In [105]: plt.plot(E6Data['TTM'], E6Data['Spot'], 'o-c', label= 'Spot rate', lw=1.5) plt.plot(E6Data['TTM'], E6Data['Forward'],'o-m', label= 'Forward ra te', lw=1.5) plt.grid(True) plt.xlabel('Term(years)') plt.ylabel('Yield') plt.title('The yield curve for 6-months Euribor by Smith-Wilson at 2020-04-14 (Table 4.0)') plt.legend()

Out[105]:

In [106]: E6Data.head()

Out[106]: Measured From To Name Quote Days DeltaT TTM Spot Discount date date date

EURIBOR 2020-04- 2020- 2020- 0 -0.195 185 187.0 0.506849 -0.009536 1.000049 6M 14 04-16 10-16

EUR 1X7 2020-04- 2020- 2020- -0.223 216 31.0 0.591781 -0.009279 1.000056 1 FRA 14 04-16 11-16

EUR 2X8 2020-04- 2020- 2020- -0.250 246 30.0 0.673973 -0.009007 1.000062 2 FRA 14 04-16 12-16

EUR 3X9 2020-04- 2020- 2021- -0.269 279 33.0 0.764384 -0.008695 1.000067 3 FRA 14 04-16 01-18

EUR 2020-04- 2020- 2021- 4X10 -0.288 308 29.0 0.843836 -0.008419 1.000072 4 14 04-16 02-16 FRA

In [107]: E6Data.to_excel(r'/Users/pennyandersson/Desktop/Analytical Finance/ thesis/my work/E6DataSW.xlsx', sheet_name='EoDataSW', index = False)

file:///Users/pennyandersson/Downloads/SWE6.html Sida 106 av 107 Appendix G

Criteria for a Masters Thesis

In this appendix, I am going to describe how thesis objectives meet the requirements of the Swedish National Agency for Higher Education for a Master’s degree (2 years).

G.1 Objective 1: Knowledge and understanding

In this thesis, I started with the introduction of importance of yield curves on valuation of financial instruments. Therefore, we need to find a better method/model to construct an ac- curate and smooth yield curve. To achieve this goal, I have reviewed the literature on three methods, namely Bootstrapping, the Smith Wilson and the extended Nelson Siegel, and have presented these three methods mathematically. I compared Bootstrapping with the ENS from a more theoretical perspective. Besides I also adopted the real market data for the calculation to obtain yield and forward curves by using Bootstrapping and the SW. Finally, I have made a conclusion based on the performance abilities of the methods.

G.2 Objective 2: Methodological knowledge

In this thesis, I have discussed three different yield curve estimation models in detail to observe their performance capabilities. To understand the models plainly I have reviewed relevant the- oretical knowledge in chapter 2. Furthermore, I have described these models mathematically and implemented two of them with actual market data in chapter 3. At the end, I have made a conclusion based on the performance abilities of the methods in chapter 4.

G.3 Objective 3: Critically and Systematically Integrate Know- ledge

With the support of my supervisor, Jan Röman, I got the information which I needed through different sources in order to construct and develop the concept. I have compared the results between these models to observe their performance capabilities.

224 G.4 Objective 4: Ability to Critically, Independently and Creatively Identify and Carry out Advanced Tasks

I used actual market data on Bootstrapping and the SW to construct yield and forward curves and compared their performance capabilities. I demonstrated a significant ability to present al- gorithms and to implement calculation in Python. Moreover, identify and formulate problems and issues, within a given time frame.

G.5 Objective 5: Ability in both national and international contexts, Present and Discuss Conclusions and Know- ledge

I have described the results numerically in the tables and, I have shown graphs which is based on the results to illustrate the performance abilities of the models. I tried my best to write the whole thesis in a simple and easy language so the reader who has basic knowledge in financial mathematics can understand and conceive it.

G.6 Objective 6: Scientific, Social and Ethical Aspects

This thesis will help the reader to understand the process of obtaining yield curves by three different models within interbank market as well as what an accurate and smooth yield curve means to banks. The comparative results showed the advantages and disadvantages among those three models. In addition, this study can be further used to investigate other yield curve estimation models to find a simple implementing model which can constructs a yield curve as accurate as possible and as smooth as possible.

225