Documentation |
On this page… |
---|
Sensitivity of Bond Prices to Interest Rates Bond Portfolio for Hedging Duration and Convexity Bond Prices and Yield Curve Parallel Shifts Bond Prices and Yield Curve Nonparallel Shifts |
Macaulay and modified duration measure the sensitivity of a bond's price to changes in the level of interest rates. Convexity measures the change in duration for small shifts in the yield curve, and thus measures the second-order price sensitivity of a bond. Both measures can gauge the vulnerability of a bond portfolio's value to changes in the level of interest rates.
Alternatively, analysts can use duration and convexity to construct a bond portfolio that is partly hedged against small shifts in the term structure. If you combine bonds in a portfolio whose duration is zero, the portfolio is insulated, to some extent, against interest rate changes. If the portfolio convexity is also zero, this insulation is even better. However, since hedging costs money or reduces expected return, you need to know how much protection results from hedging duration alone compared to hedging both duration and convexity.
This example demonstrates a way to analyze the relative importance of duration and convexity for a bond portfolio using some of the SIA-compliant bond functions in Financial Toolbox™ software. Using duration, it constructs a first-order approximation of the change in portfolio price to a level shift in interest rates. Then, using convexity, it calculates a second-order approximation. Finally, it compares the two approximations with the true price change resulting from a change in the yield curve.
Step 1. Define three bonds using values for the settlement date, maturity date, face value, and coupon rate. For simplicity, accept default values for the coupon payment periodicity (semiannual), end-of-month payment rule (rule in effect), and day-count basis (actual/actual). Also, synchronize the coupon payment structure to the maturity date (no odd first or last coupon dates). Any inputs for which defaults are accepted are set to empty matrices ([]) as placeholders where appropriate.
Settle = '19-Aug-1999'; Maturity = ['17-Jun-2010'; '09-Jun-2015'; '14-May-2025']; Face = [100; 100; 1000]; CouponRate = [0.07; 0.06; 0.045];
Also, specify the yield curve information.
Yields = [0.05; 0.06; 0.065];
Step 2. Use Financial Toolbox functions to calculate the price, modified duration in years, and convexity in years of each bond.
The true price is quoted (clean) price plus accrued interest.
[CleanPrice, AccruedInterest] = bndprice(Yields, CouponRate,... Settle, Maturity, 2, 0, [], [], [], [], [], Face); Durations = bnddury(Yields, CouponRate, Settle, Maturity, 2, 0,... [], [], [], [], [], Face); Convexities = bndconvy(Yields, CouponRate, Settle, Maturity, 2, 0,... [], [], [], [], [], Face); Prices = CleanPrice + AccruedInterest;
Step 3. Choose a hypothetical amount by which to shift the yield curve (here, 0.2 percentage point or 20 basis points).
dY = 0.002;
Weight the three bonds equally, and calculate the actual quantity of each bond in the portfolio, which has a total value of $100,000.
PortfolioPrice = 100000; PortfolioWeights = ones(3,1)/3; PortfolioAmounts = PortfolioPrice * PortfolioWeights ./ Prices;
Step 4. Calculate the modified duration and convexity of the portfolio. Note that the portfolio duration or convextity is a weighted average of the durations or convexities of the individual bonds. Calculate the first- and second-order approximations of the percent price change as a function of the change in the level of interest rates.
PortfolioDuration = PortfolioWeights' * Durations;
PortfolioConvexity = PortfolioWeights' * Convexities;
PercentApprox1 = -PortfolioDuration * dY * 100;
PercentApprox2 = PercentApprox1 + ...
PortfolioConvexity*dY^2*100/2.0;
Step 5. Estimate the new portfolio price using the two estimates for the percent price change.
PriceApprox1 = PortfolioPrice + ... PercentApprox1 * PortfolioPrice/100; PriceApprox2 = PortfolioPrice + ... PercentApprox2 * PortfolioPrice/100;
Step 6. Calculate the true new portfolio price by shifting the yield curve.
[CleanPrice, AccruedInterest] = bndprice(Yields + dY,... CouponRate, Settle, Maturity, 2, 0, [], [], [], [], [],... Face); NewPrice = PortfolioAmounts' * (CleanPrice + AccruedInterest);
Step 7. Compare the results. The analysis results are as follows:
The original portfolio price was $100,000.
The yield curve shifted up by 0.2 percentage point or 20 basis points.
The portfolio duration and convexity are 10.3181 and 157.6346, respectively. These will be needed for Bond Portfolio for Hedging Duration and Convexity.
The first-order approximation, based on modified duration, predicts the new portfolio price (PriceApprox1) will be $97,936.37.
The second-order approximation, based on duration and convexity, predicts the new portfolio price (PriceApprox2) will be $97,967.90.
The true new portfolio price (NewPrice) for this yield curve shift is $97,967.51.
The estimate using duration and convexity is quite good (at least for this fairly small shift in the yield curve), but only slightly better than the estimate using duration alone. The importance of convexity increases as the magnitude of the yield curve shift increases. Try a larger shift (dY) to see this effect.
The approximation formulas in this example consider only parallel shifts in the term structure, because both formulas are functions of dY, the change in yield. The formulas are not well-defined unless each yield changes by the same amount. In actual financial markets, changes in yield curve level typically explain a substantial portion of bond price movements. However, other changes in the yield curve, such as slope, may also be important and are not captured here. Also, both formulas give local approximations whose accuracy deteriorates as dY increases in size. You can demonstrate this by running the program with larger values of dY.
This example constructs a bond portfolio to hedge the portfolio of Sensitivity of Bond Prices to Interest Rates It assumes a long position in (holding) the portfolio, and that three other bonds are available for hedging. It chooses weights for these three other bonds in a new portfolio so that the duration and convexity of the new portfolio match those of the original portfolio. Taking a short position in the new portfolio, in an amount equal to the value of the first portfolio, partially hedges against parallel shifts in the yield curve.
Recall that portfolio duration or convexity is a weighted average of the durations or convexities of the individual bonds in a portfolio. As in the previous example, this example uses modified duration in years and convexity in years. The hedging problem therefore becomes one of solving a system of linear equations, which is an easy to do in MATLAB^{®} software.
Step 1. Define three bonds available for hedging the original portfolio. Specify values for the settlement date, maturity date, face value, and coupon rate. For simplicity, accept default values for the coupon payment periodicity (semiannual), end-of-month payment rule (rule in effect), and day-count basis (actual/actual). Also, synchronize the coupon payment structure to the maturity date (that is, no odd first or last coupon dates). Set any inputs for which defaults are accepted to empty matrices ([]) as placeholders where appropriate. The intent is to hedge against duration and convexity and constrain total portfolio price.
Settle = '19-Aug-1999'; Maturity = ['15-Jun-2005'; '02-Oct-2010'; '01-Mar-2025']; Face = [500; 1000; 250]; CouponRate = [0.07; 0.066; 0.08];
Also, specify the yield curve for each bond.
Yields = [0.06; 0.07; 0.075];
Step 2. Use Financial Toolbox functions to calculate the price, modified duration in years, and convexity in years of each bond.
The true price is quoted (clean price plus accrued interest.
[CleanPrice, AccruedInterest] = bndprice(Yields,CouponRate,... Settle, Maturity, 2, 0, [], [], [], [], [], Face); Durations = bnddury(Yields, CouponRate, Settle, Maturity,... 2, 0, [], [], [], [], [], Face); Convexities = bndconvy(Yields, CouponRate, Settle,... Maturity, 2, 0, [], [], [], [], [], Face); Prices = CleanPrice + AccruedInterest;
Step 3. Set up and solve the system of linear equations whose solution is the weights of the new bonds in a new portfolio with the same duration and convexity as the original portfolio. In addition, scale the weights to sum to 1; that is, force them to be portfolio weights. You can then scale this unit portfolio to have the same price as the original portfolio. Recall that the original portfolio duration and convexity are 10.3181 and 157.6346, respectively. Also, note that the last row of the linear system ensures that the sum of the weights is unity.
A = [Durations' Convexities' 1 1 1]; b = [ 10.3181 157.6346 1]; Weights = A\b;
Step 4. Compute the duration and convexity of the hedge portfolio, which should now match the original portfolio.
PortfolioDuration = Weights' * Durations; PortfolioConvexity = Weights' * Convexities;
Step 5. Finally, scale the unit portfolio to match the value of the original portfolio and find the number of bonds required to insulate against small parallel shifts in the yield curve.
PortfolioValue = 100000; HedgeAmounts = Weights ./ Prices * PortfolioValue;
As required, the duration and convexity of the new portfolio are 10.3181 and 157.6346, respectively.
The hedge amounts for bonds 1, 2, and 3 are -57.37, 71.70, and 216.27, respectively.
Notice that the hedge matches the duration, convexity, and value ($100,000) of the original portfolio. If you are holding that first portfolio, you can hedge by taking a short position in the new portfolio.
Just as the approximations of the first example are appropriate only for small parallel shifts in the yield curve, the hedge portfolio is appropriate only for reducing the impact of small level changes in the term structure.
Often bond portfolio managers want to consider more than just the sensitivity of a portfolio's price to a small shift in the yield curve, particularly if the investment horizon is long. This example shows how MATLAB software can help you to visualize the price behavior of a portfolio of bonds over a wide range of yield curve scenarios, and as time progresses toward maturity.
This example uses Financial Toolbox bond pricing functions to evaluate the impact of time-to-maturity and yield variation on the price of a bond portfolio. It plots the portfolio value and shows the behavior of bond prices as yield and time vary.
Step 1. Specify values for the settlement date, maturity date, face value, coupon rate, and coupon payment periodicity of a four-bond portfolio. For simplicity, accept default values for the end-of-month payment rule (rule in effect) and day-count basis (actual/actual). Also, synchronize the coupon payment structure to the maturity date (no odd first or last coupon dates). Any inputs for which defaults are accepted are set to empty matrices ([]) as placeholders where appropriate.
Settle = '15-Jan-1995'; Maturity = datenum(['03-Apr-2020'; '14-May-2025'; ... '09-Jun-2019'; '25-Feb-2019']); Face = [1000; 1000; 1000; 1000]; CouponRate = [0; 0.05; 0; 0.055]; Periods = [0; 2; 0; 2];
Also, specify the points on the yield curve for each bond.
Yields = [0.078; 0.09; 0.075; 0.085];
Step 2. Use Financial Toolbox functions to calculate the true bond prices as the sum of the quoted price plus accrued interest.
[CleanPrice, AccruedInterest] = bndprice(Yields,... CouponRate,Settle, Maturity, Periods,... [], [], [], [], [], [], Face); Prices = CleanPrice + AccruedInterest;
Step 3. Assume the value of each bond is $25,000, and determine the quantity of each bond such that the portfolio value is $100,000.
BondAmounts = 25000 ./ Prices;
Step 4. Compute the portfolio price for a rolling series of settlement dates over a range of yields. The evaluation dates occur annually on January 15, beginning on 15-Jan-1995 (settlement) and extending out to 15-Jan-2018. Thus, this step evaluates portfolio price on a grid of time of progression (dT) and interest rates (dY).
dy = -0.05:0.005:0.05; % Yield changes D = datevec(Settle); % Get date components dt = datenum(D(1):2018, D(2), D(3)); % Get evaluation dates [dT, dY] = meshgrid(dt, dy); % Create grid NumTimes = length(dt); % Number of time steps NumYields = length(dy); % Number of yield changes NumBonds = length(Maturity); % Number of bonds % Preallocate vector Prices = zeros(NumTimes*NumYields, NumBonds);
Now that the grid and price vectors have been created, compute the price of each bond in the portfolio on the grid one bond at a time.
for i = 1:NumBonds [CleanPrice, AccruedInterest] = bndprice(Yields(i)+... dY(:), CouponRate(i), dT(:), Maturity(i), Periods(i),... [], [], [], [], [], [], Face(i)); Prices(:,i) = CleanPrice + AccruedInterest; end
Scale the bond prices by the quantity of bonds.
Prices = Prices * BondAmounts;
Reshape the bond values to conform to the underlying evaluation grid.
Prices = reshape(Prices, NumYields, NumTimes);
Step 5. Plot the price of the portfolio as a function of settlement date and a range of yields, and as a function of the change in yield (dY). This plot illustrates the interest rate sensitivity of the portfolio as time progresses (dT), under a range of interest rate scenarios. With the following graphics commands, you can visualize the three-dimensional surface relative to the current portfolio value (that is, $100,000).
figure % Open a new figure window surf(dt, dy, Prices) % Draw the surface
Add the base portfolio value to the existing surface plot.
hold on % Add the current value for reference basemesh = mesh(dt, dy, 100000*ones(NumYields, NumTimes));
Make it transparent, plot it so the price surface shows through, and draw a box around the plot.
set(basemesh, 'facecolor', 'none'); set(basemesh, 'edgecolor', 'm'); set(gca, 'box', 'on');
Plot the x-axis using two-digit year (YY format) labels for ticks.
dateaxis('x', 11);
Add axis labels and set the three-dimensional viewpoint. MATLAB produces the figure.
xlabel('Evaluation Date (YY Format)'); ylabel('Change in Yield'); zlabel('Portfolio Price'); hold off view(-25,25);
MATLAB three-dimensional graphics allow you to visualize the interest rate risk experienced by a bond portfolio over time. This example assumed parallel shifts in the term structure, but it might similarly have allowed other components to vary, such as the level and slope.
Key rate duration enables you to determine the sensitivity of the price of a bond to nonparallel shifts in the yield curve. This example uses bndkrdur to construct a portfolio to hedge the interest rate risk of a U.S. Treasury bond maturing in 20 years.
Settle = datenum('2-Dec-2008'); CouponRate = 5.500/100; Maturity = datenum('15-Aug-2028'); Price = 128.68;
The interest rate risk of this bond is hedged with the following four on-the-run Treasury bonds:
The 30-year bond.
Maturity_30 = datenum('15-May-2038');
Coupon_30 = .045;
Price_30 = 124.69;
The ten-year note.
Maturity_10 = datenum('15-Nov-2018');
Coupon_10 = .0375;
Price_10 = 109.35;
The five-year note.
Maturity_05 = datenum('30-Nov-2013');
Coupon_05 = .02;
Price_05 = 101.67;
The two-year note.
Maturity_02 = datenum('30-Nov-2010');
Coupon_02 = .01250;
Price_02 = 100.72;
You can get the Treasury spot or zero curve from: http://www.treas.gov/offices/domestic-finance/debt-management/interest-rate/yield.shtml.
ZeroDates = daysadd(Settle,[30 90 180 360 360*2 360*3 360*5 ...
360*7 360*10 360*20 360*30]);
ZeroRates = ([0.09 0.07 0.44 0.81 0.90 1.16 1.71 2.13 2.72 3.51 3.22]/100)';
Step 1. Compute the key rate durations for both the bond and the hedging portfolio:
BondKRD = bndkrdur([ZeroDates ZeroRates], CouponRate, Settle,... Maturity,'keyrates',[2 5 10 20]); HedgeMaturity = [Maturity_02;Maturity_05;Maturity_10;Maturity_30]; HedgeCoupon = [Coupon_02;Coupon_05;Coupon_10;Coupon_30]; HedgeKRD = bndkrdur([ZeroDates ZeroRates], HedgeCoupon,... Settle, HedgeMaturity, 'keyrates',[2 5 10 20]);
Step 2. Compute the dollar durations for each of the instruments and each of the key rates (assuming holding 100 bonds):
PortfolioDD = 100*Price* BondKRD; HedgeDD = bsxfun(@times, HedgeKRD,[Price_30;Price_10;Price_05;Price_02]);
Step 3. Compute the number of bonds to sell short to obtain a key rate duration that is 0 for the entire portfolio:
NumBonds = PortfolioDD/HedgeDD;
NumBonds = 3.8973 6.1596 23.0282 80.0522
These results indicate selling 4, 6, 23 and 80 bonds respectively of the 2-, 5-, 10-, and 30-year bonds achieves a portfolio that is neutral with respect to the 2-, 5-, 10-, and 30-year spot rates.
The option sensitivity measures familiar to most option traders are often referred to as the greeks: delta, gamma, vega, lambda, rho, and theta. Delta is the price sensitivity of an option with respect to changes in the price of the underlying asset. It represents a first-order sensitivity measure analogous to duration in fixed income markets. Gamma is the sensitivity of an option's delta to changes in the price of the underlying asset, and represents a second-order price sensitivity analogous to convexity in fixed income markets. Vega is the price sensitivity of an option with respect to changes in the volatility of the underlying asset. See Pricing and Analyzing Equity Derivatives or the Glossary for other definitions.
The greeks of a particular option are a function of the model used to price the option. However, given enough different options to work with, a trader can construct a portfolio with any desired values for its greeks. For example, to insulate the value of an option portfolio from small changes in the price of the underlying asset, one trader might construct an option portfolio whose delta is zero. Such a portfolio is then said to be "delta neutral." Another trader may want to protect an option portfolio from larger changes in the price of the underlying asset, and so might construct a portfolio whose delta and gamma are both zero. Such a portfolio is both delta and gamma neutral. A third trader may want to construct a portfolio insulated from small changes in the volatility of the underlying asset in addition to delta and gamma neutrality. Such a portfolio is then delta, gamma, and vega neutral.
Using the Black-Scholes model for European options, this example creates an equity option portfolio that is simultaneously delta, gamma, and vega neutral. The value of a particular greek of an option portfolio is a weighted average of the corresponding greek of each individual option. The weights are the quantity of each option in the portfolio. Hedging an option portfolio thus involves solving a system of linear equations, an easy process in MATLAB.
Step 1. Create an input data matrix to summarize the relevant information. Each row of the matrix contains the standard inputs to Financial Toolbox Black-Scholes suite of functions: column 1 contains the current price of the underlying stock; column 2 the strike price of each option; column 3 the time to-expiry of each option in years; column 4 the annualized stock price volatility; and column 5 the annualized dividend rate of the underlying asset. Note that rows 1 and 3 are data related to call options, while rows 2 and 4 are data related to put options.
DataMatrix = [100.000 100 0.2 0.3 0 % Call 119.100 125 0.2 0.2 0.025 % Put 87.200 85 0.1 0.23 0 % Call 301.125 315 0.5 0.25 0.0333] % Put
Also, assume the annualized risk-free rate is 10% and is constant for all maturities of interest.
RiskFreeRate = 0.10;
For clarity, assign each column of DataMatrix to a column vector whose name reflects the type of financial data in the column.
StockPrice = DataMatrix(:,1); StrikePrice = DataMatrix(:,2); ExpiryTime = DataMatrix(:,3); Volatility = DataMatrix(:,4); DividendRate = DataMatrix(:,5);
Step 2. Based on the Black-Scholes model, compute the prices, and the delta, gamma, and vega sensitivity greeks of each of the four options. Note that the functions blsprice and blsdelta have two outputs, while blsgamma and blsvega have only one. The price and delta of a call option differ from the price and delta of an otherwise equivalent put option, in contrast to the gamma and vega sensitivities, which are valid for both calls and puts.
[CallPrices, PutPrices] = blsprice(StockPrice, StrikePrice,... RiskFreeRate, ExpiryTime, Volatility, DividendRate); [CallDeltas, PutDeltas] = blsdelta(StockPrice,... StrikePrice, RiskFreeRate, ExpiryTime, Volatility,... DividendRate); Gammas = blsgamma(StockPrice, StrikePrice, RiskFreeRate,... ExpiryTime, Volatility , DividendRate)'; Vegas = blsvega(StockPrice, StrikePrice, RiskFreeRate,... ExpiryTime, Volatility , DividendRate)';
Extract the prices and deltas of interest to account for the distinction between call and puts.
Prices = [CallPrices(1) PutPrices(2) CallPrices(3)... PutPrices(4)]; Deltas = [CallDeltas(1) PutDeltas(2) CallDeltas(3)... PutDeltas(4)];
Step 3. Now, assuming an arbitrary portfolio value of $17,000, set up and solve the linear system of equations such that the overall option portfolio is simultaneously delta, gamma, and vega-neutral. The solution computes the value of a particular greek of a portfolio of options as a weighted average of the corresponding greek of each individual option in the portfolio. The system of equations is solved using the back slash (\) operator discussed in Solving Simultaneous Linear Equations.
A = [Deltas; Gammas; Vegas; Prices];
b = [0; 0; 0; 17000];
OptionQuantities = A\b; % Quantity (number) of each option.
Step 4. Finally, compute the market value, delta, gamma, and vega of the overall portfolio as a weighted average of the corresponding parameters of the component options. The weighted average is computed as an inner product of two vectors.
PortfolioValue = Prices * OptionQuantities; PortfolioDelta = Deltas * OptionQuantities; PortfolioGamma = Gammas * OptionQuantities; PortfolioVega = Vegas * OptionQuantities;
The output for these computations is:
Option Price Delta Gamma Vega Quantity 1 6.3441 0.5856 0.0290 17.4293 22332.6131 2 6.6035 -0.6255 0.0353 20.0347 6864.0731 3 4.2993 0.7003 0.0548 9.5837 -15654.8657 4 22.7694 -0.4830 0.0074 83.5225 -4510.5153 Portfolio Value: $17000.00 Portfolio Delta: 0.00 Portfolio Gamma: -0.00 Portfolio Vega : 0.00
You can verify that the portfolio value is $17,000 and that the option portfolio is indeed delta, gamma, and vega neutral, as desired. Hedges based on these measures are effective only for small changes in the underlying variables.
This example illustrates some of the term-structure analysis functions found in Financial Toolbox software. Specifically, it illustrates how to derive implied zero (spot) and forward curves from the observed market prices of coupon-bearing bonds. The zero and forward curves implied from the market data are then used to price an interest rate swap agreement.
In an interest rate swap, two parties agree to a periodic exchange of cash flows. One of the cash flows is based on a fixed interest rate held constant throughout the life of the swap. The other cash flow stream is tied to some variable index rate. Pricing a swap at inception amounts to finding the fixed rate of the swap agreement. This fixed rate, appropriately scaled by the notional principal of the swap agreement, determines the periodic sequence of fixed cash flows.
In general, interest rate swaps are priced from the forward curve such that the variable cash flows implied from the series of forward rates and the periodic sequence of fixed-rate cash flows have the same current value. Thus, interest rate swap pricing and term structure analysis are intimately related.
Step 1. Specify values for the settlement date, maturity dates, coupon rates, and market prices for 10 U.S. Treasury Bonds. This data allows you to price a five-year swap with net cash flow payments exchanged every six months. For simplicity, accept default values for the end-of-month payment rule (rule in effect) and day-count basis (actual/actual). To avoid issues of accrued interest, assume that all Treasury Bonds pay semiannual coupons and that settlement occurs on a coupon payment date.
Settle = datenum('15-Jan-1999'); BondData = {'15-Jul-1999' 0.06000 99.93 '15-Jan-2000' 0.06125 99.72 '15-Jul-2000' 0.06375 99.70 '15-Jan-2001' 0.06500 99.40 '15-Jul-2001' 0.06875 99.73 '15-Jan-2002' 0.07000 99.42 '15-Jul-2002' 0.07250 99.32 '15-Jan-2003' 0.07375 98.45 '15-Jul-2003' 0.07500 97.71 '15-Jan-2004' 0.08000 98.15};
BondData is an instance of a MATLAB cell array, indicated by the curly braces ({}).
Next assign the date stored in the cell array to Maturity, CouponRate, and Prices vectors for further processing.
Maturity = datenum(char(BondData{:,1}));
CouponRate = [BondData{:,2}]';
Prices = [BondData{:,3}]';
Period = 2; % semiannual coupons
Step 2. Now that the data has been specified, use the term structure function zbtprice to bootstrap the zero curve implied from the prices of the coupon-bearing bonds. This implied zero curve represents the series of zero-coupon Treasury rates consistent with the prices of the coupon-bearing bonds such that arbitrage opportunities will not exist.
ZeroRates = zbtprice([Maturity CouponRate], Prices, Settle);
The zero curve, stored in ZeroRates, is quoted on a semiannual bond basis (the periodic, six-month, interest rate is doubled to annualize). The first element of ZeroRates is the annualized rate over the next six months, the second element is the annualized rate over the next 12 months, and so on.
Step 3. From the implied zero curve, find the corresponding series of implied forward rates using the term structure function zero2fwd.
ForwardRates = zero2fwd(ZeroRates, Maturity, Settle);
The forward curve, stored in ForwardRates, is also quoted on a semiannual bond basis. The first element of ForwardRates is the annualized rate applied to the interval between settlement and six months after settlement, the second element is the annualized rate applied to the interval from six months to 12 months after settlement, and so on. This implied forward curve is also consistent with the observed market prices such that arbitrage activities will be unprofitable. Since the first forward rate is also a zero rate, the first element of ZeroRates and ForwardRates are the same.
Step 4. Now that you have derived the zero curve, convert it to a sequence of discount factors with the term structure function zero2disc.
DiscountFactors = zero2disc(ZeroRates, Maturity, Settle);
Step 5. From the discount factors, compute the present value of the variable cash flows derived from the implied forward rates. For plain interest rate swaps, the notional principle remains constant for each payment date and cancels out of each side of the present value equation. The next line assumes unit notional principle.
PresentValue = sum((ForwardRates/Period) .* DiscountFactors);
Step 6. Compute the swap's price (the fixed rate) by equating the present value of the fixed cash flows with the present value of the cash flows derived from the implied forward rates. Again, since the notional principle cancels out of each side of the equation, it is simply assumed to be 1.
SwapFixedRate = Period * PresentValue / sum(DiscountFactors);
The output for these computations is:
Zero Rates Forward Rates 0.0614 0.0614 0.0642 0.0670 0.0660 0.0695 0.0684 0.0758 0.0702 0.0774 0.0726 0.0846 0.0754 0.0925 0.0795 0.1077 0.0827 0.1089 0.0868 0.1239 Swap Price (Fixed Rate) = 0.0845
All rates are in decimal format. The swap price, 8.45%, would likely be the mid-point between a market-maker's bid/ask quotes.