Hedging in a finite-state model (Binary Trees)

Today’s post is about hedging in a world where there are only a few outcomes. It demonstrates a lot of principles that are important in asset pricing, and it’s also a frequent topic for interview questions so almost got included as one of those!

A very basic approximation for a stock is a binary tree, as in the diagram shown below. The stock is worth 100 today, and after some time (say a year) it will be worth either 110 with probability p or 90 with probability (1-p). In this very basic model, we assume no other values are possible – the stock either does well and goes up by 10, or it does badly and goes down by 10. Furthermore, we assume that there is a risk-free yearly interest rate r at which we can deposit money in the bank and receive (1+r) times our initial deposit in a year.

The two possibilities for a stock's evolution in the binary tree model
The two possibilities for a stock’s evolution in the binary tree model

We’re going to try and price options in this model. Let’s say we’ve got a call option to buy the stock in a year’s time for 100. How much is this worth? Because of the simple state of the world, we can enumerate the two possibilities – either the stock is worth 110, in which case the call option to buy it for 100 is worth 10, or the stock is worth 90, and the option is worthless. We’ll try and simulate that payoff using a combination of cash-in-the-bank and the stock itself, and then by no-arbitrage the price must be the same today.

Our portfolio consists of \alpha stocks S and \beta cash-in-the-bank. The value of the cash will certainly be (1+r)\beta in a year, while the stock will be 110 \alpha or 90 \alpha depending on the state, and we want the sum of these two to equal the option payoff (in either the up or the down scenario), which gives us two simultaneous equations

    \[(1+r) \beta + 110 \alpha = 10\]

    \[(1+r) \beta + 90 \alpha = 0\]


    \[\alpha = 0.5\]

    \[\beta = {-45 \over (1+r)}\]

This says that a portfolio containing half of a stock and minus 45 pounds in the bank will exactly replicate the payoff of the option in either world state. The value of this portfolio today is just 0.5*100 – 45/(1+r), and I’ve plotted that as a function of r below.

The price of a call option on a stock in the two-state world given above
The price of a call option on a stock as a function of the risk-free rate in the two-state world given above

This gives meaningless prices if r > 0.1 (the price of the option must be between 0 and 10/(1+r) as these are the discounted values of the least/most that it can pay out at expiry). What does this mean intuitively? Well, if r > 0.1 then we have an arbitrage: 100 in the bank will *always* yield more than the stock at expiry, so we should short the stock as much as possible and put the proceeds in the bank. If r < -0.1 the situation is exactly reversed

The important point about all of this was that the option price DOESN’T depend on the relative chances of the stock increasing to 110 or falling to 90. As long as both of these are strictly greater than zero and less than one, then ANY set of probabilities will lead to the same price for the option. This is the discrete analogue of a result I presented before (here) – that the expected growth of the stock in the real world doesn’t matter to the option’s price, it is the risk-free rate that affects its price. Indeed, it is possible to derive the continuous result using a binary tree by letting the time period go to zero, I won’t attempt it here but the derivation can be found in many textbooks (eg. on wikipedia).

Things really get interesting when we try to extend the model in a slightly different way. Often banks will be interested in models that have not just a diffusive component, but also a ‘jump’ component, which gives a finite chance that a price will fall suddenly by a large amount (I’ll present one such model in the near future). Unlike a straight-forward Black-Scholes model, because these jumps happen suddenly and unexpectedly they are very difficult to hedge, and are meant to represent market crashes that can result in sudden sharp losses for banks.

In our simple tree model, this can be incorporated by moving to a three-branch model, shown below

The three possibilities for a stock's evolution in the three-branch tree model
The three possibilities for a stock’s evolution in the three-branch tree model

We have the same two branches as before, but an additional state now exists in which the stock price crashes to 50 with probability q. In this case, again trying to price an option to buy the stock for 100 gives three simultaneous equations

    \[(1+r) \beta + 110 \alpha = 10\]

    \[(1+r) \beta + 90 \alpha = 0\]

    \[(1+r) \beta + 50 \alpha = 0\]

Unlike before, we can’t find a single alpha and beta that will replicate the payoff in all three world states, as we have three equations and only two unknowns. Consequently, the best we will be able to to is sub-replicate or super-replicate the payoff. That is, find portfolios that either always pay equal to or greater than the option, or always pay less than or equal to the option. These will give bounds on the lowest and highest arbitrage-free option prices, but that’s as far as arbitrage-free prices will take us (in fact ANY of the prices between this limit is arbitrage-free) – choosing an actual price will require knowing the probabilities of p and q and deciding on our personal risk-premium.

In the simple three-state model, lower and upper bounds can be calculated by ignoring the second and third equation respectively above, and they give the limits shown in the graph below. Once again, as r \to 0.1 they converge, but note that a case where r < -0.1 is now possible, as the ‘crash’ option means that the stock can still pay out less than the bank account

The limiting values given by the no-arbitrage requirement on the price of a call option as a function of the risk-free rate in the three-branch tree model given above
The limiting values given by the no-arbitrage requirement on the price of a call option as a function of the risk-free rate in the three-branch tree model given above

This is what’s called an incomplete market. The securities that exist in the market aren’t sufficient to hedge us against all future possible states of the universe. In this case, we can’t uniquely determine prices by risk-neutral pricing – sice we can’t hedge out all of the risk, risk preferences of investors will play a part in determining the market-clearing prices of securities. Most models that are used in the industry are incomplete in this way – I’ll be looking at some examples of this soon which will include models involving jump processes and stochastic volatility.

Forwards vs. Futures

I’ve covered Forwards and Futures in previous posts, and now that I’ve covered the basics of Stochastic Interest Rates as well, we can have a look at the difference between Forwards and Futures Contracts from a financial perspective.

As discussed before, the price of a Forward Contract is enforceable by arbitrage if the underlying is available and freely storable and there are Zero Coupon Bonds available to the Forward Contract delivery time. In this case, the forward price is

F(t,T) = S(t) \cdot {1 \over {\rm ZCB}(t,T)}

In this post I’m going to assume a general interest rate model, which in particular may well be stochastic. In such cases, the price of a ZCB at the present time is given by

{\rm ZCB}(t,T) = {\mathbb E}\Big[ \exp{\Big\{\int_t^T r(t') dt'\Big\} } \Big]

Futures Contracts are a bit more complicated, and we need to extend our earlier description in the case that there are interest rates. The basic description was given before, but additionally in the presence of interest rates, any deposit that is in either party’s account is delivered to the OTHER party at the end of each time period. So, taking the example from the previous post, on day 4 we had $4 on account with the exchange – if rates on that day were 10% p.a., over that day the $4 balance would accrue about 10c interest, which would be paid to the other party.

Let’s say we’re at time s, and want to calculate the Futures price to time T. Our replication strategy is now as follows, following the classic proof due to Cox, Ingersall and Ross but in continuous time. Futures Contracts are free to enter into and break out of due to the margin in each account, so entering X Futures Contracts at time t and closing them at time t+dt will lead to a net receipt (or payment if negative) of \inline {\rm X}\cdot\big[ H(t+dt,T) - H(t,T)\big]. From t+dt to T, we invest (borrow) this amount at the short rate and thus recieve (need to pay)

{\rm X}\cdot\big[ H(t+\tau,T) - H(t,T)\big]\cdot\prod_t^T \big( 1 + r(t)\tau \big)

and now moving to continuous time

{\rm X}\cdot\big[ H(t+dt,T) - H(t,T)\big]\cdot\int_t^T e^{ r(t)}\ dt

We follow this strategy in continuous time, constantly opening contracts and closing them in the following time period [I’m glossing over discrete vs. continuous time here – as long as the short rate corresponds to the discrete time step involved this shouldn’t be a problem], and investing our profits and financing our losses both at the corresponding short rate. We choose a different X for each period [t,t+td] so that \inline {\rm X}(t) = \int_s^t \exp{\{r(t')\}}dt'. We also invest an amount H(s,T) at time s at the short rate, and continually roll this over so that it is worth \inline H(s,T)\cdot \int_s^T \exp{\{r(t)\}}dt at time T

Only the final step of this strategy costs money to enter, so the net price of the portfolio and trading strategy is H(s,T). The net payoff at expiry is

H(s,T)\cdot \int_s^T e^{r(t)}dt + \sum_s^T {\rm X}\cdot[H(t+dt,T)-H(t,T))]\cdot\int_t^T e^{r(t)}dt

= H(s,T)\cdot \int_s^T e^{r(t)}dt + \sum_s^T \int_s^t e^{r(t)}dt\cdot[H(t+dt,T)-H(t,T))]\cdot\int_t^T e^{r(t)}dt

= H(s,T)\cdot \int_s^T e^{r(t)}dt + \int_s^T e^{r(t)}dt \cdot \sum_s^T [H(t+dt,T)-H(t,T))]

= H(s,T)\cdot \int_s^T e^{r(t)}dt + \int_s^T e^{r(t)}dt \cdot [H(T,T)-H(s,T))]= H(T,T) \cdot \int_s^T e^{r(t)}dt

And H(T,T) is S(T), so the net payoff of a portfolio costing H(s,T) is

= S(T) \cdot \int_s^T e^{r(t)}dt

How does this differ from a portfolio costing the Forward price? Remembering that in Risk-Neutral Valuation, the present value of an asset is equal to the expectation of its future value discounted by a numeraire. In the risk-neutral measure, this numeraire is a unit of cash B continually re-invested at the short rate, which is worth \inline B(t,T) = e^{\int_t^T r(t')dt' }, so we see that the Futures Price is a martingale in the risk-neutral measure (sometimes called the ‘cash measure’ because of its numeraire). So the current value of a Futures Contract on some underlying should be

H(t,T) = {\mathbb E}^{\rm RN}\big[ S(T) | {\cal F}_t \big]

ie. the undiscounted expectation of the future spot in the risk-neutral measure. The Forward Price is instead the expected price in the T-forward measure whose numeraire is a ZCB expiring at time T

F(t,T) = {\mathbb E}^{\rm T}\big[ S(T) | {\cal F}_t \big]

We can express these in terms of each other remembering F(T,T) = S(T) = H(T,T) and using a change of numeraire (post on this soon!). I also use the expression for two correlated lognormal, which I derived at the bottom of this post

\begin{align*} F(t,T) &= {\mathbb E}^{T}\big[ F(T,T) | {\cal F}_t \big] \\ &= {\mathbb E}^{T}\big[ S(T) | {\cal F}_t \big] \\ &= {\mathbb E}^{T}\big[ H(T,T) | {\cal F}_t \big] \\ &= {\mathbb E}^{RN}\big[ H(T,T) {B(t)\over B(T)} {{\rm ZCB}(t,T)\over {\rm ZCB(T,T)}}| {\cal F}_t \big] \\ &= {\rm ZCB}(t,T){\mathbb E}^{RN}\big[ H(T,T) {1\over B(T)}| {\cal F}_t \big] \\ &= {\rm ZCB}(t,T){\mathbb E}^{RN}\big[ H(T,T)\big] {\mathbb E}^{RN}\big[ e^{-\int_t^T r(t')dt'} \big] e^{\sigma_H \sigma_B \rho} \\ &= H(t,T) \cdot e^{\sigma_H \sigma_B \rho} \\ \end{align*}

where \inline \sigma_H is the volatility of the Futures price, and \inline \sigma_B is the volatility of a ZCB – in general the algebra will be rather messy!

As a concrete example, let’s consider the following model for asset prices, with S driven by a geometric brownian motion and rates driven by the Vasicek model discussed before

{dS \over S} = r(t) dt + \sigma_S dW_t

dr = a \big[ \theta - r(t)\big] dt + \sigma_r \widetilde{dW_t}

And (critically) assuming that the two brownian processes are correlated according to rho

dW_t \cdot \widetilde{dW_t} = \rho dt

In this case, the volatility \inline \sigma_B is the volatility of \inline {\mathbb E}\big[ e^{-\int_t^T r(t')dt'}\big], and as I discussed in the post on stochastic rates, this is tractable and lognormally distributed in this model.

We can see that in the case of correlated stochastic rates, these two prices are not the same – which means that Futures and Forward Contracts are fundamentally different financial products.


For two standard normal variates x and y with correlation rho, we have:

\begin{align*} {\mathbb E}\big[ e^ {\sigma_1 x} \big]& = e^ {{1\over 2}\sigma_1^2 } \end{align*}


\begin{align*} {\mathbb E}\big[ e^ {\sigma_1 x + \sigma_2 y} \big]& = {\mathbb E}\big[ e^ {\sigma_1 x + \sigma_2 \rho x + \sigma_2 \sqrt{1-\rho^2}z} \big]\\ & = {\mathbb E}\big[ e^ {(\sigma_1 + \sigma_2 \rho) x + \sigma_2 \sqrt{1-\rho^2}z} \big]\\ & = \big[ e^ {{1\over 2}(\sigma_1 + \sigma_2 \rho)^2 + {1\over 2}(\sigma_2 \sqrt{1-\rho^2})^2} \big]\\ & = \big[ e^ {{1\over 2}\sigma_1^2 + {1\over 2}\sigma_2^2 + \sigma_1 \sigma_2 \rho} \big]\\ & = {\mathbb E}\big[ e^ {\sigma_1 x }\big] {\mathbb E} \big[ e^{\sigma_2 y}\big] e^{ \sigma_1 \sigma_2 \rho} \end{align*}

Put-Call Parity

Put-Call parity is a simple result connecting the prices of puts and calls in a model-independent way via the forward price.

Consider the three graphs below, showing independently the payoff at expiry of a vanilla call, a vanilla put, and a forward contract. We can see that the payoff of a long call plus the payoff of a short put will precisely overlap the forward contract payoff (assuming they have the same strike and expiry…).

The combination of a long call and a short put with the same strike and expiry is equivalent to a forward at the same strike and expiry. This is guaranteed by their payoffs at expiry (making the usual assumptions about tradability of the underlying/forward etc.), since the payoff of holding a long call and a short strike can be exactly hedged by holding a forward contract
The combination of a long call and a short put with the same strike and expiry is equivalent to a forward at the same strike and expiry. This is guaranteed by their payoffs at expiry (making the usual assumptions about tradability of the underlying/forward etc.), since the payoff of holding a long call and a short strike can be exactly hedged by holding a forward contract

This can be seen from the algebra as well:

\begin{align*} C_{\rm call}(T) - C_{\rm put}(T)\ & = \big( S(T) - K \big)^+ - \big( K - S(T) \big)^+ \\ & = S(T) - K \\ & = F(T,T) \end{align*}

If two portfolios have the same payoff, it’s a fundamental rule of derivatives pricing that they must have the same price, which gives the fundamental put-call parity relationship

C_{\rm call}(t) - C_{\rm put}(t)\ = Z(t,T)\cdot\Big( F(t,T) - K\Big)

We can take the BS expressions for put and call prices given in a previous post and observe that they obey the relationship [since \inline \Phi(x) + \Phi(-x) = 1], but importantly this result is model independent. As long as there is a forward contract available with the strike and expiry of the options, then this result MUST hold in ANY model.

One implication of this is that if we use a model to determine the price of a call option, put-call parity fixes the price of the put option to be

C_{\rm put}(t) = C_{\rm call}(t) - Z(t,T)\cdot\Big( F(t,T) - K\Big)

We can actually use this to improve our code. Out-of-the-money options typically require more paths to converge in Monte Carlo simulations because they rely on the detailed behaviour of a few paths that travel a long way. However, we can calculate in-the-money prices quickly and due to put-call parity these will lock the price of the matching out-of-the-money options.

Put-call parity is also an important test of the implementation of a model – if the prices that we are getting out don’t obey this relationship then we’ve done something seriously wrong [as long as both prices have converged!]. An equivalent statement is that the implied BS volatility of matching puts and calls should be exactly the same in any model, since the implied vol is the BS vol that would produce the given price for a put/call, and this is locked by put-call parity.

We can get some other similar relationships between put and call prices that I’ll look at in the future. Also note that put-call parity holds for european-style options, but not for many more complicated path-dependent options or those with early exercise features like American options.

Bootstrapping the Discount Curve from Swap Rates

Today’s post will be a short one about calculation of discount curves from swap rates. I’ve discussed both swaps and discount curves in previous posts, you should read those before this one or it might not make much sense!

Although bonds can be used to calculate discount bond prices, typically swaps are the most liquid products on the market and will go to the longest expiry times (often 80+ years for major currencies), so these are used to calculate many of the points on the discount curve [and often both of these can be done simultaneously to give better reliability].

In the previous post on swaps, I calculated the swap rate X that makes swaps zero-valued at the current time

    \[X = {Z(0,t_0) - Z(0,t_N) \over \sum_{n=0}^{N-1} \tau \cdot Z(0,t_{n+1})}\]

where the t‘s here represent the fixing dates of the swap (although payment is made at the beginning of the following period, so the n‘th period is received at t_{n+1}.

Consider the sequence of times \{t_0 = 0, t_1, t_2, \dots , t_n\} for which a sequence of swaps are quoted on the markets, with swap rates X_i for the swap running from t_0 up to t_i. We can back out the discount factor at each time as follows:

    \[X_0 = {Z(0,0) - Z(0,t_1) \over \tau \cdot Z(0,t_1)}\]

    \[\Rightarrow Z(0,t_1) = {1 \over 1 + \tau X_0 }\]

    \[X_1 = {Z(0,0) - Z(0,t_2) \over \tau \big(Z(0,t_1) + Z(0,t_2)\big) }\]

    \[\Rightarrow Z(0,t_2) = {1 - \tau \cdot X_1 \cdot Z(0,t_1) \over 1 + \tau X_1}\]

and we can see from this the general procedure, calculating another ZCB from each successive swap rate using the expression

    \[Z(0,t_i) = {1 - \sum_{i=1}^{i-1} \big(\tau \cdot X_i \cdot Z(0,t_i) \big) \over 1 + \tau X_{i-1}}\]

These swaps and ZCBs are called co-initial because they both started at the same time t_0.

Now imagine that instead the swaps X_i have the first fixing at time t_i and their final fixing at time t_n for 0 \leq i < n – such swaps are called co-terminal swaps as they start at different times but finish at the same one. Once again we can calculate the discount factors up to a constant factor, this time by working backwards:

    \[X_{n-1} = {Z(0,t_{n-1}) - Z(0,t_n) \over \tau \cdot Z(0,t_n)}\]

    \[\Rightarrow Z(0,t_{n-1}) = Z(0,t_n)\cdot\big( { 1 + \tau X_{n-1} }\big)\]

    \[X_{n-2} = {Z(0,t_{n-2}) - Z(0,t_n) \over \tau \big(Z(0,t_{n-1}) + Z(0,t_n)\big) }\]

    \[\Rightarrow Z(0,t_{n-2}) = Z(0,t_{n})\big( 1 + \tau X_{n-2} ( 1 + \tau X_{n-1}) \big)\]

and so on, the dcfs can be backed out.

To specify the exact values of co-terminal swaps, we need to know at least one dcf exactly. In general the co-initial case will also require this – I implicitly assumed that they started fixing at t=0 where we know Z(0,0) = 1, but for general co-initial swaps we would also have this issue.

Forward Rate Agreements and Swaps

For calibration of discount curves from swap rates, see my post on Bootstrapping the Discount Curve from Swap Rates.

In this post I’m going to introduce two of the fundamental interest rate products, Forward Rate Agreements (FRAs) and Swaps. FRAs allow us to ‘lock in’ a specified interest rate for borrowing between two future times, and Swaps are agreements to exchange a future stream of fixed interest payments for floating ones, or visa-versa. Both are model independent, which means we can statically hedge them today using just Zero Coupon Bonds (ZCBs) – so their prices won’t depend on our models for interest rates or underlying prices etc. ZCBs really are fundamental here – if you haven’t read my earlier post on them yet I recommend starting there!

First, a note about conventions. In other contexts, I’ve used r to be the continuously-compounding rate, such that if I start with $1, by time t it will be worth \exp \bigl( \int_0^t r(t')dt' \bigr) . In the rates world, this would be very confusing, and rates are always quoted as simple annualised rates, so that $1 lent for half a year at 5% would return $1.025 exactly in half a year’s time (note the additional factor of 0.5 coming from the year-fraction of the deposit), and this rates convention will be used throughout this post.

Each ZCB gives us a rate at which we can put money on deposit now for expiry at a specific time, and we can construct a discount curve from the collection of all ZCBs that we have available to us. In the case of a ZCB, we deposit the money now and receive it back at expiry. A Forward Rate Agreement extends the idea of putting money on deposit now for a fixed period of time to putting it on deposit at a future date for a specific period of time. We’ve picked up an extra variable here – our rate r(T) for deposit starting now depends only on time of expiry T, while the FRA rate f(t,T) will depend on the time that we put the money on deposit t as well as the time of expiry T.

An FRA, just like a deposit, involves two cash flows. We pay the counterparty a notional M at time t, and receive our notional M plus interest of (T-t)\cdot f(t,T) \cdot M at time T; where the first term is the Year Fraction, the second is the Forward Rate, and the final is the Notional. Since f will be fixed when we sign the contract, we can hedge these two cash flows exactly at t=0 using ZCBs. The value of the FRA is the value of receiving the second sum minus the cost of making the first payment:

    \[{\rm FRA}_{price} = Z(0,T)\cdot \Bigl[ (T - t)\cdot f(t,T) + 1\Bigr]\cdot M - Z(0,t)\cdot M\]

This agreement is at ‘fair value’ if the forward rate f(t,T) makes {\rm FRA}_{price} = 0, and re-arranging gives

    \[f(t,T) = {1 \over T-t}\ \Bigr( {Z(0,t) \over Z(0,T)} - 1 \Bigl)\]

An FRA allows us to ‘lock-in’ a particular interest rate for some time in the future – this is analogous in rates markets to the forward price of a stock or commodity for future delivery, which was discussed in an earlier post. Note that the price of all FRAs is uniquely determined from the discount curve [although in reality our discount curve will be limited in both temporal resolution and maximum date by the ZCBs or other products available on the market which we can use to build it].

A Swap is an agreement to exchange two cash flows coming from assets, but not the assets themselves. By far the most common is the Interest Rate Swap, in which two parties agree to swap a stream of fixed rate interest rate payments on a notional M of cash for a stream of floating rate payments on the same notional. Although the notional might be quite large, usually only the differences between the payments at each time are exchanged, so the actual payments will be very much smaller. The mechanics are probably best demonstrated by example:

A swap is written on a notional $100Mn, with periods starting in a year and continuing for three years and with payments at the end of each three month period; to pay fixed annualised 5% payments, and floating payments at the three-month deposit rate (fixed at the beginning of each period). What payments actually get made?

The swap starts in a year’s time, but the first payment is made at the end of the first 3-month period, in 15 months time. At this time, the fixed payment will be 5\% \cdot M \cdot (3{\rm m} / 12{\rm m}). The floating payment will be whatever the three-month deposit rate was at 1 year, multiplied by the same prefactors, r_{\rm 1 yr}(0,3{\rm m}) \cdot M \cdot (3{\rm m} / 12{\rm m}) – let’s say that r_{\rm 1 yr}(0,3{\rm m}) is 4% (although of course we won’t know what it is until the beginning of each period, and the payment will be delayed until the end of the period) – then the net cash flow will be $250,000, paid by the person paying fixed to the person paying floating.

The same calculation happens at each time, and a payment is made equal to the difference between the fixed and the floating leg cash flow. Although the notional is huge, we can see that the actual payments are much, much smaller [be alert for newspapers quoting ‘outstanding notional’ to make positions seem large and unsteady!]. The convention for naming Swaps is that if we are receiving fixed payments, we have a receiver’s swap; and if we are receiving floating payments, it is a payer’s swap.

What is the point of this product? Well, if we have a loan on which we are having to pay floating rate interest, using a swap we can exchange that to a fixed rate of interest by making fixed rate payments to the counterparty and receiving floating rate payments back, which match the payments that we’re making on the loan. This is of use to companies, who need to handle interest rate risk and might not want to be exposed to rates rising heavily on money they’re borrowing. A bank holding a large portfolio of fixed rate mortgage loans but required to pay interest to a central bank at floating rate might engage in a swap in the reverse direction to hedge it’s exposure.

How can we price this product? It’s easy to price the fixed payments – since each is known exactly in advance, we can hedge these out using ZCBs. The value of the sum of the fixed payments is

    \[V_{\rm fixed} = M \sum_{n=0}^{N-1} x \cdot Z(0,t_{n+1}) \cdot \tau\]

where x is the fixed rate (5% in our example above), and \tau is the relevant year-fraction for each payment (0.25 in our example about). What about the floating payments? We have to think a little harder here, but it turns out we can use FRA agreements to hedge these exactly as well. The problem is that we don’t know what the three-month deposit rate will be in a year’s time. But we can replicate it: if we borrow an amount N in a year’s time, and put that on deposit for three months, we’ll receive back M \cdot(r_{1 yr}(0,3{\rm m}) + 1)\cdot (3{\rm m}/12{\rm m}) in 15 months. We know from our discussion above that we can enter an FRA to borrow N in a year’s time, and we’ll need to pay M \cdot (f(12{\rm m},15{\rm m})+1) \cdot (3{\rm m}/12{\rm m}) in 15 months time – so we can guarantee to match the payment profile of the floating leg using the forward rates for the periods in question. The value of the floating payments is therefore

    \[V_{\rm floating} = M \sum_{n=0}^{N-1} f(t_n,t_{n+1}) \cdot Z(0,t_{n+1}) \cdot \tau\]

    \[= M \sum_{n=0}^{N-1} Z(0,t_{n+1}) \cdot ({Z(0,t_n)\over Z(0,t_{n+1})} - 1)\]

    \[= M \sum_{n=0}^{N-1} (Z(0,t_n) - Z(0,t_{n+1}))\]

    \[= M \bigl(Z(0,t_0) - Z(0,t_N)\bigr)\]

Since we can fix the price of the two legs exactly by arbitrage right now, we can value the swap by comparing the present value of each leg

    \[V_{\rm swap} = V_{\rm fixed} - V_{\rm floating}\]

    \[= M \sum_{n=0}^{N-1} (x - f(t_n,t_{n+1}))\cdot Z(0,t_n) \cdot\tau\]

    \[= M \Bigl( Z(0,t_N) - Z(0,t_0) + \sum_{n=0}^{N-1} x \cdot Z(0,t_{n+1})\cdot \tau \Bigr)\]

As with FRAs, swaps are said to be at fair value when the values of the fixed and the floating rate match, and the overall value is zero. This is the fixed rate at which we can enter a Swap for free, and occurs when x = X such that

    \[X = { Z(0,t_0) - Z(0,t_N) \over \sum_{n=0}^{N-1} \tau\cdot Z(0,t_{n+1}) }\]

This is called the Swap Rate. It is fully determined by the discount curve, and as we shall see the reverse is also true – the Swap Rate is in 1-to-1 correspondence with discount curve. Of course, after a swap is issued the Swap Rate will change constantly, in which case the actual fixed payment will no longer match X and the swap will have non-zero value. If K is the swap fixed coupon payment and X is the current swap rate, then

    \[V_{\rm swap}= M \Bigl( Z(0,t_N) - Z(0,t_0) + \sum_{n=0}^{N-1} K \cdot Z(0,t_{n+1})\cdot \tau \Bigr)\]

    \[= M \Bigl( {Z(0,t_N) - Z(0,t_0)\over \sum_{n=0}^{N-1} \cdot Z(0,t_{n+1})\cdot \tau} + K \Bigr) \cdot \sum_{n=0}^{N-1} \cdot Z(0,t_{n+1})\cdot \tau\]

    \[V_{\rm swap}= M \cdot (K - X)\cdot \sum_{n=0}^{N-1} Z(0,t_{n+1})\cdot \tau\]

    \[V_{\rm swap}= M \cdot (K - X)\cdot B\]

where B = \sum_{n=0}^{N-1} Z(0,t_{n+1})\cdot \tau is called the annuity of the swap. The value is proportional to the difference between the swap rate and the swap fixed coupon.

Because of the number of institutions that want to handle interest rate risk resulting from loans, IR Swaps are one of the most liquidly traded financial products. Although we’ve derived their price here from the Discount Curve, in practice it is often done the other way around – Swaps often exist up to much higher maturity dates than other products, and Discount Curves at long maturities are instead constructed from the swap rates quoted on the market at these dates. This is a very important procedure, but financially rather trivial. I’m not going to cover it here but will probably come back to it in a short post in the near future.

As well as being important in their own right, FRAs and Swaps (along with ZCBs, of course) are the foundation of the rich field of interest rate derivatives. The right (but not obligation) to enter into an FRA – a call option on an FRA – is called a caplet, and a portfolio of such options on FRAs across different time periods is called a cap, since you have guaranteed a cap on the maximum interest you will have to pay over the whole period to borrow money (a put on an FRA is called a floorlet, and a sequence of these forms a floor, for similar reasons). An option to enter a swap is called a swaption, and these are also heavily traded wherever a borrower might want to re-finance a loan at a later date if interest rates move sharply. The pricing of these products becomes dependent on the underlying model that we assume for interest rates, and I’ll start to deal with them in later posts.


I covered Forward Contracts in a post a week ago, and promised to look at the related Futures Contract soon. These contracts aim to do the same thing – provide a means of ensuring an underlying asset for future delivery at a price determined today – but their dynamics are rather different from those of the Forward Contract.

One of the main criticisms of Forward Contracts is that they are directly written between two parties. This means they are subject to credit risk – if one counterparty goes bankrupt, the contract may not be guaranteed any more. By contrast, a Futures Contract is written via an exchange. This is a central organisation that matches long and short Futures Contract counterparties, and oversees the transaction (and of course, charges a fee for its services). Futures Contracts are standardised in terms of expiry dates and contract terms, which increases liquidity in the market. The counterparty who wants to receive the underlying asset at expiry is said to be the long party, while the one providing it is the short party.

As with a Forward Contract, an underlying asset is specified. Each party must have an account with the exchange in order to enter transactions. Each day, the exchange will quote the current Futures Price, which is the price at which the transaction will happen; but to enter into the contract doesn’t cost either party (beyond the small exchange fee mentioned above). Instead, the counterparties must update their accounts daily to reflect the difference between the initial Futures Price quoted and the current Futures Price quoted. If it is above the initial price, the party who is short the contract must have this difference in their account; and if it is below the initial price, the party who is long must have this difference in their account.

This is probably best demonstrated by a simple example. Let’s say that I want to enter a Futures Contract on Day 0 for delivery of a barrel of oil on Day 5 (realistically this would be a much longer period of months or years, but in order to keep the number of steps in the example down I’m keeping it short here), the current Futures Price quoted for a contract expiring in 5 days is $100. I’m the long party as I want to receive the oil, my counterparty is short as he will be delivering.

Day 1: Futures Price quoted for expiry on Day 5 increases to $101.50. The short party has to deposit $1.50 in his account to cover this increase.

Day 2: Futures Price increases to $103.50. The short party has to deposit another $2 in his account to cover this increase (so it’s now $3.50 total).

Day 3: Futures Price falls to $101. The short party can withdraw $2.50 from his account to leave only $1, which covers the change from day 0.

Day 4: Futures Price for delivery on Day 5 (ie. tomorrow!) crashes to $96. The short party can take all of the money out of his account, and I need to deposit $4 to cover the difference between the current Futures Price and its initial value.

Day 5: Futures Price recovers to $97. I can take $1 out of my account to leave $3 total. Since this is the day the contract expires, we make the transaction today at the initially agreed Futures Price of $100, and the money in my account is returned to me (if the money was in the short party’s account, it would have been returned to him in the same way). Note also that the Futures Price on day 5 for expiry on day 5 must be equal to the spot rate at that time – so this contract obliges me to trade at a price above the current spot rate, just as a Forward Contract at these prices would have done.

There are several points to make. Firstly, I’ve described a Physically Settled Futures Contract here, since I actually took delivery of a barrel of oil. The standardised contracts will specify a grade of oil and a specific delivery location – many exchanges have physical warehouses for these transactions to happen. However, the large majority of Futures Contracts today are Cash Settled: in this case, instead of taking a delivery, I exchange money with the short party to achieve the same financial payoff. In the example above, since we were transacting at $100 while the market price was only $97, I would have to pay $3 to the short party (as we shall see, it’s no coincidence that this was the amount in my account!).

This contract more-or-less eliminates credit risk due to a counterparty defaulting. Consider, for example, that the oil company had defaulted on Day 2. This might seem like bad news for me – at that point, I was expecting to pay $100 for a commodity worth $103.50. The critical point is the account with the exchange. This amount is forfeited if the counterparty wants to leave the transaction or fails to keep topping it up as required, and delivered to the other party. In this case, the short party’s account of $3.50 would have been given to me, and the contract terminated – since the current price was $103.50, I could enter the same contract with a different counterparty without taking any financial loss.

On the other hand, if I’d decided on Day 4 that I no longer wanted to be part of the contract, as it looked like I’d be paying $100 while the contract is only worth $96, I might abscond. However, the exchange still has my $4 on account which it can take and give to the short counterparty, so once again they aren’t hurt by my reneging. The only risk to either party is that there is a large shift in price in a very short time, so that the counterparty is unable to credit a sufficient amount to his account before defaulting.

Although it more-or-less deals with credit risk, this contract does introduce liquidity risk. Considering again Day 2, the company had had to deposit money in their account to cover the position. Even though the contract eventually ends up profitably for the short party, it is conceivable that cash-flow concerns would make them unable to honour their intermediate commitments, in which case they would have to break the contract at that stage and take a loss. For a Forward Contract, as there is no payment until the expiry date this couldn’t happen.

Aside from these issues, this contract seems to be essentially the same as a Forward Contract, since it guaranteed a transaction on Day 5 at $100. However, so far we have ignored interest rates, which turn out to make a subtle difference to the final payoff (and which make the maths interesting!).

I’m going to to another post soon comparing these two contracts in the presence of interest rates, but I’ll tell you the answer right now to whet your appetite: in the presence of deterministic interest rates, the two payoffs are the same. This isn’t surprising – if we know what will happen in the future then we can hedge by replication both of the contracts (Forward Contracts in the way described in the previous post on them; Futures Contracts as I will describe next time – but have a go and try to construct a replication strategy yourself) so that their values are fixed today. However, this is actually quite unrealistic and most real models of interest rates include stochastic interest rates of some type – in this case, the Futures Contract becomes a path-dependent derivative and we can’t construct a static hedge for it at the current time, since we don’t know what the interest rate will look like at each stage! More to come soon.


I’ve mentioned Forwards many times in the blog so far, but haven’t yet given any description of what they are, and it’s about time for a summary! Forwards were probably the first ‘financial derivative’ to be traded, and they still occupy a central role in the field today.

At the most basic level, a Forward Contract is a delayed sale between two parties. The contract is signed now and the sale and the price agreed to, but the transaction only happens at a later date. We can immediately see why these contracts would be popular, as they insulate the people who have signed the contract from risk due to price variations. For example, an airline can foresee fairly accurately its fuel requirements over the next year, so might wish to enter into a Forward Contract with an oil company for a certain amount of fuel to be delivered next year, in order not to be exposed to the risk of price rises. Meanwhile, the oil company knows its costs of production, and might well also decide that as long as the contract price is profitable it is locking in business for the future and avoiding the risk of price falls harming its operations.

The first thing to note is that, unlike options, the contract is binding – both parties are obliged to enter into the transaction at the given date, there is no optionality in this contract. The agreed price has different names, but for consistency with other products quants tend to call it the Strike Price, K.

Forward Contracts are the most simple form of derivative. A derivative is a financial instrument that derives it’s price from some other (‘underlying’) instrument. In the example above, the underlying was the cost of oil, but it could equally well have been foreign exchange rates, stock prices or interest rates – indeed, all of these are different sorts of risks that companies will in general want to hedge out. What is the price of a Forward Contract and how does it depend on the underlying? If the price of oil rises after the contract above had been signed, the airline company would breath a sign of relief – it has locked in the forward price for its oil via the Forward Contract so the contract is clearly a valuable asset for it. By contrast, the oil company will be miffed, as it could have sold the oil on the market for a better price. If prices fall, situations will be reversed. How can we express this mathematically?

As a simple example, I will consider a Forward Contract for me to buy a stock from a bank in a year’s time for $100. We can calculate the price of this contract using a technique called ‘replication’. What we need to do is construct a portfolio that exactly matches the payments implicit in the Forward Contract, and according to the ‘Law of One Price’, the price of these two matching portfolios must be the same. Call now t=0 and the expiry of the contract t=T.

Portfolio 1: 1 Forward Contract on S at strike price $100 and at time T. Transactions are: at time T, I pay $100, and receive one unit of stock. This will be worth S(T), the price of the underlying at that time. There are no net payments at time t=0.

How can we match this? Well, we will need to ensure the receipt of an amount of cash S(T) at time T, and an ideal way of ensuring this is by buying a unit of the stock at t=0 and holding it, since this is guaranteed to be worth S(T) at t=T. We also need to match the payment of the strike price, $100, at t=T. An ideal product to use for this is a Zero Coupon Bond maturing at t=T (this is equivalent to borrowing money and you can see it either way. We’re making all of the usual assumptions about being able to go long and short equally easily etc.). Recall that Zero Coupon Bonds are worth $1 at time t=T, and worth

    \[{\rm ZCB}(0,T) = {\mathbb E} \Bigr[ e^{-\int_0^T r(t')dt'} \Bigl] = e^{-rT}\]

at t=0, with the last equality holding only in the case of constant interest rates. So, we can short 100 ZCBs at t=0, these will mature at t=T when we will have to pay the holder $100. The holder will pay us the present value at t=0, which is 100 \cdot ZCB(0,T). We’ve constructed a portfolio that matches all of the payments of portfolio 1 at t=T:

Portfolio 2: Long 1 underlying stock S, short 100 ZCBs; close all positions at t=T.

How much does it cost to enter into portfolio 2? As we’ve said, this will identically be the price of portfolio 1. The cost is

    \[{\rm Fwd}(0,T) = S(0) - K \cdot {\rm ZCB}(0,T)\]

    \[= {\rm ZCB}(0,T) \cdot \Bigl({S(0) \over {\rm ZCB}(0,T)} - K \Bigr)\]

We can see that this price is a linear function of K – being long a Forward Contract is better if the strike is lower! We see that its price doesn’t depend on any assumptions about the underlying growth rate (the only assumption was that we can readily trade it on the market at the two times t=0 and t=T), and depends instead on the risk-free interest rate r(t). For this reason the contract is described as ‘Model Independent’ – its price doesn’t depend on any assumptions we make about the world, we can enforce it by no arbitrage using prices of things that are available to buy right now. Compare that to the hedging strategy for a vanilla option discussed here, which relied on continuous re-hedging in the future, and is hence open to risk if our model of future volatility and interest rate isn’t perfect (and it won’t be!).

The ‘Forward Price’ is defined as the strike which makes this contract valueless for both parties – the ‘fair price’ – looking at the equation above we can see that this must be

    \[{S(0)\over {\rm ZCB}(0,T)} = S(0)\cdot{\mathbb E}\Bigl[ e^{\int^T_0 r(t') dt'}\Bigr] = S(0)\cdot e^{rT}\]

with the second equality again only valid for constant rates. The Forward Price is exactly the expectation of the underlying stock S in the risk-neutral measure, it appears across quantitative finance and often simplifies algebra, consider for example the following two ways of expressing the BS equation for vanilla option prices:

    \[C_{\rm call}(K,T,\sigma,r,\delta) = S(0)\cdot \Phi(d_1) - \delta(0,T) K \cdot \Phi(d_2)\]

    \[C_{\rm call}(K,T,\sigma,r,\delta) = \delta(0,T) \Bigl( {\rm Fwd}(0,T)\cdot \Phi(d_1) - K \cdot \Phi(d_2) \Bigr)\]

with the various terms as defined in previous posts (nb. the discount factor here from t=0 to t=T is exactly the same as a ZCB expiring at T). I certainly prefer the second form – it is expressed in terms of quantities depending on the same time T, and all of the discounting is handled outside the brackets, so it is much more easily modularised when coding it up.

Compare the payoff of a forward at expiry with that of a call and a put option. How are they related? It turns out that

    \[C_{\rm call}(K,T,\sigma,r,\delta) - C_{\rm put}(K,T,\sigma,r,\delta) = \delta(0,T)\Big({\rm Fwd}(K,T,r,\delta) - K\Big)\]

This result is called put-call parity. It comes about because if we’re long a call and short a put, we will exercise the call only if the price goes up and the counterparty will exercise the put only if the price falls – we’ve effectively locked in a sale at the strike price K at time T – such a strategy is called a synthetic forward. Note this is actually quite a deep result – although the price of both a call and a put option will depend on the model that we assume for the underlying, the difference in the two prices is model-independent and enforceable by arbitrage! If we assume an increased level of volatility over the option lifetimes, it will increase both prices by the same amount.

Payoffs at expiry for a Forward Contract compared to vanilla calls and puts.
Payoffs at expiry for a Forward Contract compared to vanilla calls and puts. Since a Forward Contract obliges to enter a transaction at expiry at strike K, the payoff can now be negative. If strike is $100 as shown above, but spot has fallen to $70, then the contract is worth -$30, as we could have bought the underlying from the market at $70 but are instead obliged to pay $100 to honour our Forward Contract. Similarly, if the price rises, our contract payoff will be positive. By comparing to the vanilla payoffs at expiry, we can see that a long call and a short put will have the same payoff as a Forward Contract, a result called put-call parity.

Up to this point, I’ve made the implicit assumptions that the underlying asset doesn’t pay any income, it’s free to hold it, and we’re able to go long or short with equal ease. Of course, in general, none of these are true. If the asset pays income like dividends, or if there are costs of storage, it is fairly easy to adjust our replication argument above to find a new price for the Forward Contract that takes into account the extra cash flows associated with holding the underlying over the period 0 \textless t \textless T. However, we can’t always go short the underlying asset – a particular case of this will be commodities, where the asset in question may not exist at the current time (ie. if you haven’t dug it out of the ground or transported it to the delivery point at t=0!), in which case there is no reason that the forward price should be related to the spot price in the deterministic way described above – this is because we have violated our assumption about being able to trade the underlying at the two times t=0 and t=T, which was implicitly vital! However, the price of the Forward Price will still converge towards the expected future spot price as we approach t=T even in this case, since a Forward Contract for transaction at the current time is simply a spot transaction!

One final word about Forward Contracts – they are ‘Over The Counter’, which means they are signed between two counterparties directly and thus carry Credit Risk – there is a chance that your counterparty might go bankrupt before the contract expiry, in which case the transaction won’t be completed. If your contract was out-of-the-money, you will still be expected to settle your position with them, while if it was in-the-money they may well not be able to pay you your full dues, so credit risk will decrease the actual value of the contract. There are advanced ways of accounting for this that I deal with in a later post (CVA – Credit Valuation Adjustment); alternatively there is a similar product called the Futures Contract, which I will deal with very soon in another post, which is superficially similar to the Forward Contract (leading to MUCH confusion in the industry!) but also attempts to deal with this credit risk.

The Discount Curve, ZCBs and the Time Value of Money

This is a foundational piece about the time value of money. It will feel a bit more like accountancy rather than mathematical finance, but it’s the absolute bedrock of what we do so definitely worth spending a bit of time on!

$100 today is worth more than $100 in a year’s time. This should be obvious – if I have $100 today, I can put it into a bank account and earn (back in the good old days!) perhaps 3% on it – so in a year’s time I have $103.

For the rest of this post (and in much of finance), I will assume that I can put money on deposit at a risk-free rate r(t), and that it will grow according to the following p.d.e.:

dB = r(t) B dt

note that this has no stochastic component – it’s solution is risk-free, exponential growth so that if I start with \inline B(0) at time 0, by time T it has grown to \inline B(T) = B(0)\exp {\int^T_0 r(t) dt} – compound interest with ‘short rate’ r(t).

Time varying interest rates can be troublesome to work with, a more convenient – but closely related – concept is the Zero Coupon Bond (ZCB). This is a bond that I buy today with a specific maturity date, at which I will get paid exactly $1. It doesn’t pay any interest in between, and since I’ve said that money is more valuable now than later, I expect to pay less than $1 for the coupon now to reflect this. How much less? Well, thinking about the bank account example above, I locked away my $100 to receive $103 a year later – this is just the same as buying 103 ZCBs maturing in a year – so the price of each bond must be 100/103 = $97.09 or there is an arbitrage opportunity. As we can see, there is a 1-to-1 correspondence between interest rate curves and ZCB prices over a period, knowing one allows us to calculate the other in a rather straightforward way,

\delta(0,T) = e^{-\int^T_0 r(t)dt}

where \inline \delta is the price of a ZCB bought now with maturity at T [the above formula is only strictly true in the context of deterministic rates – more on this later]. I’ve added a little doodle here to allow conversion between a (constant) interest rate and time period and a discount factor and also on the PRICERS page – I’ll add functionality for time-varying rates another time.

Rate: %; Time: Years


The collection of all of the ZCB prices over a period is called a discount curve. This tells us how much a payment at a particular time is worth in today’s money. As a bank, if a customer comes to me and asks to borrow $10,000 for five years at 8\% interest, the payments I will receive from him will be $800 per year for the next five years and then the return of the principle. Assuming he doesn’t default on the loan [this is another problem all together… another day!] then I can work out the ‘Net Present Value’ of this loan by taking the price for a ZCB expiring at each of the five payment dates from the discount curve, multiplying by the payment amount, and summing them together. As long as this is over $10,000 I should make a profit – if this profit is enough to compensate me for the credit risk that I’m taking, I will probably go ahead and give him the loan. By way of example, the discount curve for several different constant interest rates over 20 years is shown here:

Example Discount Curves
Examples of discount curves generated by constant interest rates of 3%, 5% and 10% over a 20 year period. Any pre-determined future cash flow can be hedged precisely by using zero coupon bonds at the same times, giving the Net Present Value (NPV) of the cash flow

One of the reasons that these rates are so important is that as I said in Risk Free Valuation, to price derivatives we assume that they grow at the risk-free rate r(t) in the RN measure. This is just the r(t) that we’ve worked with above, and we can back it out from the discount curve:

\delta(0,T) = e^{-\int^T_0 r(t)dt}

-\ln[\delta(0,T)] = \int^T_0 r(t)dt

-{\partial \ln[\delta(0,T)] \over \partial T} = r(T)

-{1 \over \delta(0,T)}{\partial \delta(0,T) \over \partial T} = r(T)

so we can calculate the instantaneous risk-free rate given a discount curve fairly straight-forwardly by taking the local gradient and dividing by the megative of the local value (in general the gradient will be negative, so this should be a positive quantity).

In reality, ZCBs don’t exist. In this context all of the above seems a bit academic! However, they can be built up out of a combination of coupon-bearing bonds. Typically, government bonds will pay a fixed interest rate each year, and have a set maturity year in which they pay both an interest payment and the original premium. The rates won’t be the same – typically longer maturity bonds will have higher rates to compensate for the added risk to the principle for locking it away for so long. Further, there is a secondary market for government debt, so we can see the current prices of these bonds for differing maturities on the market. Imagine we see a bond maturing in a year’s time that will pay 5% interest (it doesn’t matter how old it is – it might have been issued 3 or 20 years ago without affecting us), and because it is due for maturity then, it will also return the $1 principle. So it will pay a single payment, in a year’s time, of $1.05. This is already effectively a ZCB because all but one of the payments have already been made. We can see it’s market price P (lets say for concreteness it is $1.03) and from that calculate the market-implied discount factor

\delta(0,1) = {1.03 \over 1.05} = 0.981

So far, so good. But how can we create a ZCB with longer maturities? The trick here is to combine multiple coupon-bearing bonds. Lets say we can see another bond on the market with maturity in 2 years, that pays yearly 4.5% interest and returns its principle at the end. This will make two payments, $0.045 in a year’s time, then $1.045 in two years. The trick is to buy one of these bonds, and simultaneously sell (0.045/1.05 = 0.047) of the original 1 year bonds [I’m assuming we can both buy and sell fractional amounts of bonds, and that we can short sell bonds. The quantities that banks work with mean the first isn’t usually a problem, the second is also probably ok but more on this later]. This fractional bond will exactly match the payout of the second bond in the first year, so we receive an interest payment on that but need to make a payment for the fraction of the first bond. On the second year, we receive our interest and principle on the second bond – so we’ve paid money initially to set up the two-bond portfolio, we receive a payment at the end of the second year, but all of the intermediate cash flows cancel out: we’ve created a synthetic ZCB with two year maturity. To illustrate how to back out the ZCB price, let’s say the second bond price was $1.06. Cash flows are:

  • We paid $1.06 to buy the second bond at t=0
  • We received (0.045/1.05)*$1.03 for shorting the fist bond at t=0
  • Net payment at t=0 is $1.016
  • All cash flows at t=1 cancel out, as discussed above
  • We receive $1.045 in two years from the second bond

Since we paid $1.016 at t=0 and receive $1.045 in two year’s time, we repeat the about calculation for the two-year discount factor

\delta(0,2) = {1.016 \over 1.045} = 0.972

We can see from this how in general you can put together a full discount curve given a sequence of coupon-bearing bonds. We can formalise this process into a matrix equation involving the bond prices, cash flows and discount factors. First define the following quantities

\tilde{P} = \begin{bmatrix} P_1\\ P_2\\ \vdots\\ P_T \end{bmatrix}; \quad \tilde{D} = \begin{bmatrix} \delta_1\\ \delta_2\\ \vdots\\ \delta_T \end{bmatrix}; \quad \tilde{C} = \begin{bmatrix} C_{11} & 0 & \cdots & 0\\ C_{21} & C_{11} & \cdots & 0\\ \vdots & \vdots & \ddots & \vdots\\ C_{T1} & C_{T2} & \cdots & C_{TT} \end{bmatrix}

where \inline \tilde{P} is the price of the bonds expiring at each time, \inline \tilde{D} is the relevant discount factor, and \inline \tilde{C} is the matrix of cash flows for each bond at each time. These must obey

\tilde{C} \circ \tilde{D} = \tilde{P}

and as long as we have matrix inversion code, we can calculate the discount factors via the inverse relationship

\tilde{D} = \tilde{C}^{-1} \circ \tilde{P}

In reality in large institutions these discount curves are formed considering as many bonds as possible, not just those at yearly intervals, in order to minimise the extrapolation required between time points, but this is a mechanical problem rather than a theoretical one which I overlook here for brevity.