# Matlab Demo of comparing Euribor vs France's CAC 40 spanning 5 years

(Last Updated On: August 2, 2010)

Matlab Demo of comparing Euribor vs France’s CAC 40 spanning 5 years

This is a demo excersise of Matlab’s help:

1.

Load the data. Load a daily historical data set containing 3-month Euribor rates and closing index levels of France’s CAC 40 spanning the time interval February 7, 2001 to April 24, 2006:

2.

Simulate risk-neutral sample paths. Simulate risk-neutral sample paths of the CAC 40 index using a geometric Brownian motion (GBM) model:

where r(t) represents evolution of the risk-free rate of return.

Furthermore, assume that you need to annualize the relevant information derived from the daily data (annualizing the data is optional, but is useful for comparison to other examples), and that each calendar year comprises 250 trading days:

dt = 1 / 250;
returns = price2ret(Dataset.CAC);
sigma = std(returns) * sqrt(250);
yields = Dataset.EB3M;
yields = 360 * log(1 + yields);

3.

Compare the sample paths from two risk-neutral historical simulation approaches. Compare the resulting sample paths obtained from two risk-neutral historical simulation approaches, where the daily Euribor yields serve as a proxy for the risk-free rate of return.
1.

The first approach specifies the risk-neutral return as the sample average of Euribor yields, and therefore assumes a constant (non-dynamic) risk-free return:

nPeriods = length(yields); % Simulated observations
strm = RandStream(‘mt19937ar’,’Seed’,5713);
RandStream.setDefaultStream(strm);
obj = gbm(mean(yields), diag(sigma), ‘StartState’, 100)
[X1,T] = obj.simulate(nPeriods, ‘DeltaTime’, dt);

obj =
Class GBM: Generalized Geometric Brownian Motion
————————————————
Dimensions: State = 1, Brownian = 1
————————————————
StartTime: 0
StartState: 100
Correlation: 1
Drift: drift rate function F(t,X(t))
Diffusion: diffusion rate function G(t,X(t))
Simulation: simulation method/function simByEuler
Return: 0.0278117
Sigma: 0.231875

2.

In contrast, the second approach specifies the risk-neutral return as the historical time series of Euribor yields. It therefore assumes a dynamic, yet deterministic, rate of return; this example does not illustrate stochastic interest rates. To illustrate this dynamic effect, use the ts2func utility:

r = ts2func(yields, ‘Times’, (0:nPeriods – 1)’);

ts2func packages a specified time series array inside a callable function of time and state, and synchronizes it with an optional time vector. For instance:

r(0,100)
ans =
0.0470

evaluates the function at (t = 0, X t = 100) and returns the first observed Euribor yield. However, you can also evaluate the resulting function at any intermediate time t and state Xt:

r(7.5,200)
ans =
0.0472

Furthermore, the following command produces the same result when called with time alone:

r(7.5)
ans =
0.0472

The equivalence of these last two commands highlights some important features.

When you specify parameters as functions, they must evaluate properly when passed a scalar, real-valued sample time (t), and a NVARS-by-1 state vector (Xt). They must also generate an array of appropriate dimensions, which in the first case is a scalar constant, and in the second case is a scalar, piecewise constant function of time alone.

You are not required to use either time (t) or state (Xt). In the current example, the function evaluates properly when passed time followed by state, thereby satisfying the minimal requirements. The fact that it also evaluates correctly when passed only time simply indicates that the function does not require the state vector Xt. The important point to make is that it works when you pass it (t, Xt).

Furthermore, the ts2func function performs a zero-order-hold (ZOH) piecewise constant interpolation. The notion of piecewise constant parameters is pervasive throughout the SDE architecture, and is discussed in more detail in Optimizing Accuracy: About Solution Precision and Error.
4.

Perform a second simulation using the same initial random number state. Complete the comparison by performing the second simulation using the same initial random number state:

strm = RandStream(‘mt19937ar’,’Seed’,5713);
RandStream.setDefaultStream(strm);
obj = gbm(r, diag(sigma), ‘StartState’, 100)
X2 = obj.simulate(nPeriods, ‘DeltaTime’, dt);
obj =
Class GBM: Generalized Geometric Brownian Motion
————————————————
Dimensions: State = 1, Brownian = 1
————————————————
StartTime: 0
StartState: 100
Correlation: 1
Drift: drift rate function F(t,X(t))
Diffusion: diffusion rate function G(t,X(t))
Simulation: simulation method/function simByEuler
Return: function ts2func/vector2Function
Sigma: 0.231875

5.

Compare the two simulation trials. Plot the series of risk-free reference rates to compare the two simulation trials:

subplot(2,1,1)
plot(dates, 100 * yields)
datetick(‘x’), xlabel(‘Date’), …
ylabel(‘Annualized Yield (%)’)
title(‘Risk Free Rate(3-Mo Euribor Continuously-Compounded)’)
subplot(2,1,2)
plot(T, X1, ‘red’, T, X2, ‘blue’)
xlabel(‘Time (Years)’), ylabel(‘Index Level’)
title(‘Constant vs. Dynamic Rate of Return: CAC 40’)
legend({‘Constant Interest Rates’ ‘Dynamic Interest Rates’}, …
‘Location’, ‘Best’)

The paths are close but not exact. The blue line in the last plot uses all the historical Euribor data, and illustrates a single trial of a historical simulation.

NOTE I now post my TRADING ALERTS into my personal FACEBOOK ACCOUNT and TWITTER. Don't worry as I don't post stupid cat videos or what I eat!