Code covered by the BSD License  

Highlights from
Trinomial tree swaption pricing

Trinomial tree swaption pricing

by

 

This function generates swaption prices under the Hull-White trinomial tree model.

trintree_swaption_HW(U, Curve, opt_type, model, a)
function [SwaptionTree, SwapHWTree] = trintree_swaption_HW(U, Curve, opt_type, model, a)

% This function generates the Swaption price, from a portfolio
% of underlying swaps' cash-flow. The Bermudian type swaptions are
% can be exercised at the underlying cash-flow dates. The cash-flow
% structure allows varying notionals, but only the first and last coupon
% might be irregular. 

% Reminder: this swap pricing function includes the fraction
% of the current coupon if the settlement is the start date
% the floating leg is determined by the current fwd rate.
% The function cannot determine fwd rates back in the past
% (i.e. before the settlement). If the running coupon
% is to be excluded, just set the start date fwd. The cash-flow
% stream is basically determined by the Maturity time.

% The option exposure is assumed to be long (option buyer) with the convention that
% a negative fixed leg cash-flow (fix payer) entails call option exposure. 
% On the other side, a positive fixed leg cash-flow (fix reciever) is associated
% to a long put swaption exposure.
%
% input
% U : code, date, principal, coupon, basis, period.
% Curve : interest rate curve object
% opt_type : 
%       'vanilla'
%       'bermudan'
%       'swap' (no option)
% model :
%       'EV' (extended Vasicek)
%       'BK' (Black-Karasinski)
% a : parameter vector (3 dim vector)

items=unique(U(:,1));
n_item=size(items,1);
CouponRate=cell(size(items));
Principal=cell(size(items));
oggi=Curve.Settle;
Maturity=zeros(size(items));
Basis=zeros(size(items));
Period=zeros(size(items));
EndMonthRule=0;
Face=ones(size(items)); % fictious notional to allow irregular cash-flows
Settle=zeros(size(items));
StartDate=zeros(size(items));
FstCpnDate=zeros(size(items));
LstCpnDate=zeros(size(items));
FixCpn=zeros(size(items));
SwaptionTree=cell(n_item,1);
SwapHWTree=cell(n_item,1);

%--------------------------------------------------------------
% generate the cash-flow matrix
%--------------------------------------------------------------
for i=1:n_item

	H=U(U(:,1)==items(i),:);
    [~,u]=sort(H(:,2));
    H=H(u,:);
    StartDate(i)=H(1,2);
    Settle(i)=max(oggi,H(1,2));
    H(1,:)=[]; % it assumes that the cash-flow portfolio contains the (empty) cash-flow start
    CouponRate(i)={[H(:,2),H(:,3)]}; % matrix: [dates, coupon]
    Principal(i)={[H(:,2),H(:,3)]}; % matrix: [dates, coupon]
    Maturity(i)=H(end,2);
    Basis(i)=H(1,5);
    Period(i)=H(1,6);
    FstCpnDate(i)=H(1,2);
    LstCpnDate(i)=H(end,2);
    FixCpn(i)=H(1,4)/100;
    
end

[CFlowAmounts, CFlowDates, ~, ~, CFPrincipal]= cfamounts(CouponRate, Settle,Maturity,...
    'StartDate',StartDate,'FirstCouponDate',FstCpnDate,'LastCouponDate',...
    LstCpnDate,'Face',Face,'Basis',Basis,...
    'EndMonthRule',EndMonthRule,'BusinessDayConvention','previous','Period',Period);%<<--------------------------------------

%--------------------------------------------------------------
% cash-flowadjustments
%--------------------------------------------------------------

CFlowAmounts=CFlowAmounts-CFPrincipal; % this assumes that CF is stripped
CFlowAmounts(:,2)=CFlowAmounts(:,2)+CFlowAmounts(:,1); % this assumes that if the first coupon is irregular it is paid in stub
CFlowAmounts(:,1)=0; % it zeroes the accrued interest
u=CFlowDates(:,2)==oggi;
CFlowAmounts(u,2)=nan;
CFlowDates(u,2)=nan;

%--------------------------------------------------------------
% begin iterations
%--------------------------------------------------------------

for i=1:n_item

    if CFlowDates(i,1)==oggi,
        T=CFlowDates(i,~isnan(CFlowDates(i,:)))';
        CFlowT=CFlowAmounts(i,~isnan(CFlowDates(i,:)));
        if strcmp(opt_type,'bermudan')
            % if the settlement date is greater than the first historical option date
            % we need to adjust the cash-flow stream in order to exclude a swap payment
            % which cannot be part of the Bermudian structure.
            FwdDates=T(2);
            CFlowT(i,2)=0;
        else
            % otherwise, the vanilla option is just an ordinary swap
            FwdDates=0;
        end
    else
        FwdDates=CFlowDates(i,1);
        T=[oggi;CFlowDates(i,~isnan(CFlowDates(i,:)))'];
        CFlowT=[0,CFlowAmounts(i,~isnan(CFlowDates(i,:)))];
    end
    %--------------------------------------------------------
    % Generate the tree matching portfolio cash-flow times
    %--------------------------------------------------------

    switch model
        case 'EV'
            T_plus=addtodate(T(end),3,'month');% let the Tree end at the max coupon date
            TimeSpec=hwtimespec(oggi,[T(2:end);T_plus],Curve.Compounding);
            TimeSpec.Basis=Basis(i);
            RateSpec=Curve.toRateSpec([T(2:end);T_plus]);
            VolSpec = hwvolspec(Curve.Settle, [Curve.Settle;T_plus],...
                abs(a(1:2)),T_plus, a(3));
            Tree=hwtree(VolSpec,RateSpec,TimeSpec,'method','HW2000');
        case 'BK'
            T_plus=addtodate(T(end),3,'month');% let the Tree end at the max coupon date
            TimeSpec=bktimespec(oggi,[T(2:end);T_plus],Curve.Compounding);
            TimeSpec.Basis=Basis(i);
            RateSpec=Curve.toRateSpec([T(2:end);T_plus]);
            VolSpec = bkvolspec(Curve.Settle, [Curve.Settle;T_plus],...
                abs(a(1:2)),T_plus, a(3));
            Tree=bktree(VolSpec,RateSpec,TimeSpec,'method','HW2000');
        otherwise
            return
    end

    %--------------------------------------------------------
    % Begin the pricing iterations
    %--------------------------------------------------------

    [~,~,Status]=trintreeshape(Tree);
    tk=length(Status);
    SwapTree = mktrintree(tk,1,Status(1:tk),0);
    SwapTree2 = mktrintree(tk,1,Status(1:tk),0);

        for j=tk:-1:2

            Probs=zeros([Status(j-1) Status(j)]);
            iMat=sub2ind([Status(j-1) Status(j)],repmat((1:Status(j-1))',1,3),...
                [Tree.Connect{j-1}'-1, Tree.Connect{j-1}', Tree.Connect{j-1}'+1]);
            Probs(iMat)=Tree.Probs{j-1}';
            Bond=1./Tree.FwdTree{j-1};
            FloatCpn=(Tree.FwdTree{j-1}-1)/(Tree.tObs(j)-Tree.tObs(j-1));
            
            %FloatLeg=(CFlowT(:,j)*FTree.RateTree{j-1})';% no need of alpha here because already fixed in cfamounts
            FloatLeg=(CFlowT(:,j)*FloatCpn)';% no need of alpha here because already fixed in cfamounts
            FixedLeg=repmat((CFlowT(:,j).*FixCpn(i))',Status(j-1),1);
            SwapTree2(j-1)={(Probs*SwapTree2{j}'-(FloatLeg-FixedLeg))'.*Bond};

            switch opt_type
                case 'vanilla'
                    % generate the state-matrix via backward induction
                    % the first term is the expected present value of the state vector at time t-1, 
                    % representing the swap value at time t+1. The second term is the expected
                    % present value of the coupon fraction cash-flow at time t+1 
                    SwapTree(j-1)={(Probs*SwapTree{j}'-(FloatLeg-FixedLeg))'.*Bond};
                    % adjust the backward induction procedure to determine the tree for a swaption portfolio
                    swaption_op=1-(repmat((FwdDates==T(j-1)),1,Status(j-1)) & SwapTree2{j-1}<=0);
                    SwapTree(j-1)={SwapTree2{j-1}.*swaption_op};
                case 'bermudan'
                    SwapTree(j-1)={(Probs*SwapTree{j}'-(FloatLeg-FixedLeg))'.*Bond};
                    % adjust the backward induction procedure to determine the tree for a swaption portfolio
                    swaption_op=1-(repmat((FwdDates<=T(j-1)),1,Status(j-1)) & SwapTree2{j-1}<=0);
                    SwapTree(j-1)={max([SwapTree{j-1};SwapTree2{j-1}.*swaption_op])};
                case 'swap'
                    SwapTree(j-1)={(Probs*SwapTree{j}'-(FloatLeg-FixedLeg))'.*Bond};
                otherwise
                    return
            end

        end
    % cut the dead branches
    SwapTree(end)=[];
    % output
    SwaptionTree(i)={SwapTree};
    SwapHWTree(i)={Tree};

end

end

Contact us