from Interest rate model by Sandeep
Hull and White interest rate model

hullwhite.m
% Implementation of Hull-White interest rate tree assuming symmetrical
% branching
% Author : Sandeep Gore
% Date : 21st June 2007 V 1.0

sigma = 0.01;a = 0.1;dt = 1;
% M = -a*dt;
% V = sigma^2*dt;
M = exp(-a*dt)-1;
V = sigma^2*(1-exp(-2*a*dt))/(2*a);
dr = sqrt(3*V);
% dr = 0.0173;
jmax = ceil(-0.184/M); jmin = -jmax;
% jmax = 2; jmin = -jmax;
maxnodes = length(jmax:-1:jmin);
numlevels = 3;
n = 0:numlevels-1;
numnodes = 2*n+1;

% Calculate the no. of nodes at each time step
numnodes(numnodes>maxnodes) = maxnodes;

% The probabilities of upward, straight and downward transition from initial
% time step to the next time step 
prob{1}(1,1) = 1/6;
prob{1}(2,1) = 2/3;
prob{1}(3,1) = 1/6;

R{1} = 0;
nextnodes{1} = (1:3)';

for i = 2:numlevels
    j = floor(numnodes(i)/2);
    jrange = -j:1:j;
    
    R{i} = jrange.*dr;
    nodes = 1:numnodes(i);
%   Probabilities of transition in case of standard nodes
    prob{i}(1, nodes) = 1/6+(1/2)*(jrange.^2*M^2 + jrange*M);    % Up probability
    prob{i}(2, nodes) = 2/3-jrange.^2*M^2;                       % Middle probability
    prob{i}(3, nodes) = fliplr(prob{i}(1,:));                    % Down probability
    
    % Map the nodes in next stage that are connected by nodes in this
    % stage. The elements of each column represent the nodes in next step
    % connected by each of the nodes in current time step, starting from
    % bottom, going up. Hence the first column of nextnodes{i} indicates
    % the nodes connected by first node in current step starting from
    % bottom of the tree to the nodes in next step. 
    
    nextnodes{i} = [nodes; nodes+1; nodes+2];
    
    % Remember the number of nodes in a time step where term structure
    % introduces non-standard branching symmetrically
    if j == jmax
        flatnumnodes = 1:numnodes(i-1);
    end

    % Calculate probabilities at modified(non-standard) branches. 
    % The modified branches at top and bottom edges are mirror images of each other

    if j >= jmax
        prob{i}(1,1) = 1/6+(1/2)*((-j).^2*M^2 - (-j)*M);
        prob{i}(2,[1 end]) = -1/3-(-j)^2*M^2 + 2*(-j)*M;
        prob{i}(3,1) = 7/6 + (1/2)*((-j).^2*M^2 - 3*(-j)*M);
        prob{i}(1,end) = prob{i}(3,1);
        prob{i}(3,end) = prob{i}(1,1);
        
        % Remember the nodes in next step that are connected by nodes in
        % current step in case of non-standard branching.
       
        nextnodes{i} = [flatnumnodes; flatnumnodes+1; flatnumnodes+2];
        temp  = [nextnodes{i}(:, 1) nextnodes{i}(:, end)];
        nextnodes{i} = [temp(:, 1) nextnodes{i} temp(:, 2)];
    end
    
end

% Define term structure and price of bond
% Note : dT and the time spacing in term structure must be same. Else, use
% interpolation
t = 0:5;
termrate = 0.08 - 0.05*exp(-0.18*t);
price = exp(-termrate(2:end).*t(2:end));

% Determine the term structure that matches with the initial term
% structure.

% Initial shift(alpha0) and interest rate. 
shift = zeros(1, numlevels + 1);
shift(1) = termrate(2);                     
R{1} = R{1} + shift(1);
Q = R;
Q{1} = 1;
temp = prob;

for i = 2:numlevels 
    % Calculate value of Q at each node of the term structure
    temp{i-1} = flipud(temp{i-1});
    for j  = 1:numnodes(i)
        % Find out which nodes from previous time step are connected to the
        % node referred by j in current time step. 
        [r,c] = find(nextnodes{i-1} == j);
       
        % Map the connecting nodes from previous time step to corresponding
        % probabilities of connection and calculate the value of Q
        Q{i}(1,j) = sum(temp{i-1}(nextnodes{i-1} == j)'.*exp(-R{i-1}(c)*dt).*Q{i-1}(c));
    end  
    
    shift(i) = (log(cumsum(Q{i}*exp(-R{i}(:)*dt)))-log(price(i)))/dt;
    R{i} = R{i} + shift(i);
end

   

    

Contact us at files@mathworks.com