0

I have essentially copied the code from the Matlab Example file BermudanSwaption.m in an effort to calibrate the Hull White one factor model to some given market data. As I use a subset about 30 or fewer swaptions for my calibration set, I am able to arrive at an interior solution. But when I use a larger set of instruments, I get a weird error:

Below is the code:

ValuationDate = '10-01-2014';
Settle = datenum(ValuationDate);

% Zero rate data is market data, bootstrapped from Bloomberg and Reuters quotes

CurveDates = [735874;
      735882;
      735906;
      735936;
      735950;
      736040;
      736133;
      736224;
      736314;
      736424;
      736606;
      736788;
      736971;
      737153;
      737336;
      737518;
      737701;
      737884;
      738069;
      738251;
      738433;
      738615;
      738797;
      738979;
      739162;
      739345;
      739528;
      739710;
      739893;
      740075;
      740260;
      740442;
      740624;
      740806;
      740989;
      741171;
      741354;
      741536;
      741719;
      741901;
      742084;
      742269;
      742451;
      742633;
      742815;
      742997;
      743180;
      743362;
      743545;
      743728;
      743911;
      744093;
      744278;
      744460;
      744642;
      744824;
      745006;
      745189;
      745372;
      745554;
      745737;
      745919;
      746102;
      746284;
      746469;
      746651;
      746833;
      747015;
      747198;
      747380;
      747563;
      747745;
      747928;
      748111;
      748296;
      748478;
      748660;
      748842;
      749024;
      749206;
      749389;
      749572;
      749755;
      749937;
      750120;
      750302;
      750487];
  ZeroRates = 1.0e-03*[0.0172;
    0.0188;
    0.0191;
    0.0221;
    0.0249;
    0.0244;
    0.0269;
    0.0333;
    0.0423;
    0.0571;
    0.0789;
    0.1021;
    0.1253;
    0.1435;
    0.1617;
    0.1749;
    0.1881;
    0.1973;
    0.2064;
    0.2158;
    0.2253;
    0.2311;
    0.2370;
    0.2429;
    0.2488;
    0.2547;
    0.2607;
    0.2640;
    0.2672;
    0.2706;
    0.2738;
    0.2772;
    0.2807;
    0.2842;
    0.2877;
    0.2913;
    0.2948;
    0.2964;
    0.2979;
    0.2995;
    0.3011;
    0.3026;
    0.3043;
    0.3060;
    0.3077;
    0.3095;
    0.3112;
    0.3118;
    0.3125;
    0.3132;
    0.3138;
    0.3146;
    0.3152;
    0.3160;
    0.3167;
    0.3175;
    0.3183;
    0.3186;
    0.3189;
    0.3192;
    0.3196;
    0.3199;
    0.3202;
    0.3206;
    0.3209;
    0.3213;
    0.3217;
    0.3217;
    0.3216;
    0.3216;
    0.3216;
    0.3216;
    0.3216;
    0.3216;
    0.3216;
    0.3216;
    0.3216;
    0.3217;
    0.3217;
    0.3218;
    0.3218;
    0.3219;
    0.3219;
    0.3220;
    0.3220;
    0.3221;
    0.3221];

Compounding = 2; 

 RateSpec = intenvset('Compounding', 2,'ValuationDate', ValuationDate,'StartDates', ValuationDate,'EndDates', CurveDates,'Rates', ZeroRates);

InstrumentMaturity = datenum('12-Sep-2044');

 % Swaption Vol data from Bloomberg

  SwaptionBlackVol = [  0.5940    0.5550    0.4450    0.3710    0.3400    0.3110    0.2910    0.2750    0.2630    0.2520    0.2250    0.2140    0.2080    0.2050;
    0.5630    0.5470    0.4420    0.3690    0.3360    0.3090    0.2900    0.2740    0.2630    0.2520    0.2260    0.2150    0.2090    0.2060;
    0.5760    0.5330    0.4400    0.3730    0.3410    0.3150    0.2970    0.2820    0.2700    0.2590    0.2330    0.2220    0.2170    0.2140;
    0.5840    0.5020    0.4240    0.3730    0.3480    0.3240    0.3060    0.2920    0.2810    0.2710    0.2430    0.2300    0.2230    0.2190;
    0.5630    0.4750    0.4100    0.3700    0.3450    0.3230    0.3070    0.2940    0.2830    0.2740    0.2470    0.2330    0.2260    0.2210;
    0.5510    0.4520    0.3980    0.3660    0.3410    0.3220    0.3070    0.2950    0.2850    0.2760    0.2500    0.2360    0.2290    0.2240;
    0.4630    0.4010    0.3660    0.3440    0.3250    0.3100    0.2990    0.2890    0.2790    0.2720    0.2470    0.2320    0.2260    0.2210;
    0.4230    0.3750    0.3480    0.3290    0.3140    0.3030    0.2930    0.2840    0.2760    0.2690    0.2420    0.2300    0.2240    0.2190;
    0.3700    0.3470    0.3280    0.3110    0.2960    0.2880    0.2800    0.2730    0.2680    0.2620    0.2360    0.2240    0.2190    0.2150;
    0.3420    0.3250    0.3100    0.2970    0.2850    0.2770    0.2700    0.2640    0.2590    0.2540    0.2280    0.2180    0.2140    0.2110;
    0.3230    0.3010    0.2900    0.2810    0.2720    0.2650    0.2590    0.2540    0.2500    0.2470    0.2230    0.2130    0.2090    0.2060;
    0.3010    0.2860    0.2760    0.2670    0.2580    0.2530    0.2480    0.2450    0.2420    0.2390    0.2160    0.2060    0.2030    0.2000;
    0.2850    0.2750    0.2650    0.2560    0.2480    0.2440    0.2400    0.2370    0.2350    0.2320    0.2100    0.2000    0.1970    0.1940;
    0.2710    0.2600    0.2510    0.2440    0.2380    0.2340    0.2310    0.2290    0.2260    0.2240    0.2040    0.1940    0.1910    0.1890;
    0.2580    0.2470    0.2400    0.2350    0.2300    0.2270    0.2240    0.2210    0.2190    0.2170    0.1980    0.1890    0.1860    0.1840;
    0.2460    0.2370    0.2320    0.2270    0.2240    0.2210    0.2180    0.2150    0.2130    0.2110    0.1980    0.1840    0.1820    0.1800;
    0.2040    0.1980    0.1950    0.1920    0.1900    0.1890    0.1890    0.1880    0.1880    0.1870    0.1720    0.1660    0.1640    0.1620;
    0.1790    0.1750    0.1740    0.1730    0.1730    0.1710    0.1710    0.1700    0.1690    0.1690    0.1530    0.1510    0.1500    0.1480;
    0.1650    0.1650    0.1660    0.1670    0.1680    0.1670    0.1670    0.1680    0.1680    0.1680    0.1550    0.1580    0.1560    0.1530;
    0.1530    0.1570    0.1590    0.1620    0.1640    0.1650    0.1660    0.1670    0.1680    0.1690    0.1560    0.1650    0.1620    0.1590];

% The tenors for the underlying swaps and the options on them

SwaptionExerciseDates = cellstr(['1M ';'2M ';'3M '; '6M ';'9M ';'1Y ';'18M';'2Y ';'3Y ';'4Y ';'5Y ';'6Y ';'7Y ';'8Y ';'9Y ';'10Y';'15Y';'20Y';'25Y';'30Y']);
SwaptionTenors = cellstr(['1Y ';
    '2Y ';
    '3Y ';
    '4Y ';
    '5Y ';
    '6Y ';
    '7Y ';
    '8Y ';
    '9Y ';
    '10Y';
    '15Y';
    '20Y';
    '25Y';
    '30Y']);

testmat = zeros(length(SwaptionExerciseDates),1);
% Here I construct a matrix of exercise dates
for i = 1:length(SwaptionExerciseDates)
    if SwaptionExerciseDates{i}(end)=='Y'
        testmat(i) = addtodate(Settle,str2double(SwaptionExerciseDates{i}(1:end-1)),'year');
    elseif SwaptionExerciseDates{i}(end)=='M'
        testmat(i)=addtodate(Settle,str2double(SwaptionExerciseDates{i}(1:end-1)),'month');
    end
end
EurExDates= testmat;
EurExDatesFull = repmat(testmat,1,length(SwaptionTenors));


testmat2 = zeros(length(SwaptionExerciseDates),length(SwaptionTenors));

% Here I construct a matix of maturity dates

for i = 1:size(EurExDatesFull,1) 
    for j = 1:size(EurExDatesFull,2)
        if SwaptionTenors{j}(end)=='Y'
            testmat2(i,j) =  addtodate(EurExDatesFull(i,j),str2double(SwaptionTenors{j}(1:end-1)),'year');
    elseif SwaptionTenors{j}(end)=='M'
            testmat2(i,j)=   addtodate(EurExDatesFull(i,j),str2double(SwaptionTenors{j}(1:end-1)),'month');
        end

    end
end

EurMatFull = testmat2;

% I construct an index of all the swaptions that I intend to use for calibration     
relidx = find(EurMatFull <= InstrumentMaturity);

SwaptionBlackPrices = zeros(size(SwaptionBlackVol)); 
SwaptionStrike = zeros(size(SwaptionBlackVol)); 
 % back out the swaption strikes and prices from the implied vol data.
for iSwaption=1:length(SwaptionExerciseDates) 
 for iTenor=1:length(SwaptionTenors) 
 [~,SwaptionStrike(iSwaption,iTenor)] = swapbyzero(RateSpec,[NaN 0],Settle, EurMatFull(iSwaption,iTenor),... 
 'StartDate',EurExDatesFull(iSwaption,iTenor),'LegReset',[1 2],'Basis',2); 
 SwaptionBlackPrices(iSwaption,iTenor) = swaptionbyblk(RateSpec,'call', SwaptionStrike(iSwaption,iTenor),Settle, ... 
 EurExDatesFull(iSwaption,iTenor), EurMatFull(iSwaption,iTenor),SwaptionBlackVol(iSwaption,iTenor)); 
 end 
end 

TimeSpec = hwtimespec(Settle,daysadd(Settle,30*(1:370),6), 12);

% construct an index of some random collection of instruments
B = (214:224);

HW1Fobjfun4 = @(x) SwaptionBlackPrices(relidx(B)) - ... 
 swaptionbyhw(hwtree(hwvolspec(ValuationDate,testmat,x(2),testmat,x(1),'spline'), RateSpec, TimeSpec), 'call',SwaptionStrike(relidx(B)),EurExDatesFull(relidx(B)), 0,EurExDatesFull(relidx(B)), EurMatFull(relidx(B)),'Basis',2, 'SwapReset',12); 
options = optimset('disp','iter','MaxFunEvals',1000,'TolFun',1e-5); 
x0 = [.1 .01]; 
lb = [0 0]; 
ub = [1 1]; 
HW1Fparams = lsqnonlin(HW1Fobjfun4,x0,lb,ub,options)

In the results, when I just use instruments numbered 214:224, I am able to find a local minima: HW1Fparams(1) = 0.0801 , HW1Fparams(2) = 0.0002

however when I use instruments say 150:224 I get the following error:

"subscript indices must be real positive integers or logicals" error in cummswapcfbytrintree (line 23)

This is a Matlab created file. Does anyone know what's going wrong here? How do I go about diagnosing/debugging in the error is in some Matlab created file. The usual techniques of checking which variable or which index is being given a zero or double value are not at my disposal anymore. Thanks.

enter image description here

enter image description here

Amatya
  • 1,203
  • 6
  • 32
  • 52
  • It seems like your code requires the financial toolbox, so I can't look into it myself, but what happens when you try to follow the general approach to solving this problem: http://stackoverflow.com/q/20054047/983722 – Dennis Jaheruddin Dec 16 '14 at 14:42
  • @DennisJaheruddin I've seen that answer before but I dont know how to implement the techniques described in that answer. The error message describes that the line "PTree{jpObs-1} ..." has an index issue but when I do F9 or which for a variable there I get nothing. These functions seem to be called locally by matlab functions in the financial toolbox so I don't know how to spot which variable or function has the bad index. – Amatya Dec 16 '14 at 15:00
  • 1
    It sounds like you are either not using `dbstop if error`, or that there is a `try`-`catch` statement wrapped around your code. Please try `dbstop if caught error` if that may be the case. If all else fails, it may help to manually put a breakpoint on the line and inspect all relevant variables. --- If you really cannot stop the code at the point where the error occurs, then just put a breakpoint in the first line of your own code and step through it with f10 untill you find the last line you can run without error. (And inspect the variables carefully there) – Dennis Jaheruddin Dec 16 '14 at 15:03
  • 1
    @DennisJaheruddin I was able to track everything to a Financial Toolbox Tree structure's field called Connect. It's a cell containing arrays that are never supposed to be less than 2. Subtracting 1 from that array tells you the index of the future nodes in the tree that succeed the current node. I found that at the time of the error (18th iteration of lsqnonlin), connect had some arrays with some elements equal to 1, giving an index value 0 and causing an error. Now I have to figure out how these codes are generating future trees as they go through a lsqnonlin and why connect becomes 1. – Amatya Dec 16 '14 at 21:50

0 Answers0