function hedgedemo
% HEDGEDEMO GUI-aided illustration of dynamic delta-hedging
% Example hedgedemo
% Author Dimitri Shvorob, dimitri.shvorob@vanderbilt.edu, 1/28/07
close all
global begDate ...
endDate ...
hedgeFreq ...
aBegQuant ...
aPriceDef ...
fPathDef ...
tradeCost ...
carryCost ...
lineColor ...
fillColor ...
aPlot
begDate = today;
endDate = today + 90;
aBegQuant = [1 1 -1 -1]';
tradeCost = [0 0]';
carryCost = [0 0]';
hedgeFreq = 1;
fPathDef = '100 + cumsum(.25*randn(length(T),1))';
aPriceDef = {'X',...
'blsputprice (X'',100,.05,yearfrac(T,T(end)),.25)', ...
'blscallprice(X'',100,.05,yearfrac(T,T(end)),.25)', ...
'100*exp(-.05*yearfrac(T,T(end)))'};
lineColor = {[.50 0 0],[.50 .50 .50]};
fillColor = {[.95 0 0],[.95 .95 .95]};
df = .003;
wf = .30;
hf = [.32 .11 .12 .19];
fillFrame11(guifigure('Factor dynamics (Matlab expression)' ,[df .97 - hf(1) wf hf(1)]))
fillFrame21(guifigure('Prices of hedged assets (Matlab expressions)',[df .94 - sum(hf(1:2)) wf hf(2)]))
fillFrame31(guifigure('Prices of hedge assets (Matlab expressions)',[df .91 - sum(hf(1:3)) wf hf(3)]))
fillFrame41(guifigure('Hedge frequency and transaction costs' ,[df .14 wf hf(4)]))
fillOtherFrames
function fillFrame11(f)
addDatesPanel
addFactorPanel
function addDatesPanel
s = {'Start date','End date'};
d = [begDate endDate];
h = .14;
x = [.01 .47];
y = .78 + [0 .05];
for i = 1:2
guicontrol('text',f,[x(i) y(1) .20 h],s{i},[],[])
guicontrol('edit',f,[x(i) + .18 y(2) .25 h],datestr(d(i),2),@changeDates,i)
end
function changeDates(source,event) %#ok
try
t = datenum(get(source,'String'));
set(source,'Background','w')
if get(source,'UserData') == 1
begDate = t;
else
endDate = t;
end
changeFactorSeries
catch
set(source,'Background',fillColor{1})
beep
end
end
end
function addFactorPanel
global fPathInput fPlot
fPlot = axes('Parent',f, ...
'Position',[.11 .25 .78 .52], ...
'FontSize',8, ...
'Box','on');
set(fPlot,'XLim',[begDate endDate],'XTick',[])
y = .04;
h = .14;
x = [.03 .20 .70];
w = [.16 .49 .20];
fPathInput = guicontrol('edit',f,[x(2) y w(2) h],fPathDef,@changeFactorDef,[]);
guicontrol('pushbutton',f,[x(3) y w(3) h],'Evaluate',@changeFactorDef,[])
guicontrol('text',f,[x(1) y-h/4 w(1) h],'Factor, X(T)',[],[])
function changeFactorDef(source,event) %#ok
fPathDef = get(fPathInput,'String');
changeFactorSeries
end
end
end
function fillFrame21(f)
fillAssetPriceDefFrame(f,{'Hedged asset 1','Hedged asset 2'},0)
end
function fillFrame31(f)
fillAssetPriceDefFrame(f,{'Hedge asset 1','Hedge asset 2'},2)
end
function fillFrame41(f)
global adjQuant
addCostPanel
addFreqPanel
function addCostPanel
h = .20;
x = [.03 .20 .35 .505 .655];
w = [.15 .15 .15 .15 .155];
s = {'Hedge asset 1','Hedge asset 2'};
l = {'', ...
{'N(0)', 'if fixed'}, ...
{'N(0)', 'if flexible'}, ...
{'Trading', 'cost, %'}, ...
{'Borrowing', 'rate, %'}};
c = {'', ...
@changeInitialAssetQuantity, '', ...
@changeTradeCost, ...
@changeCarryCost};
n = [nan(2,1) aBegQuant(3:4) aBegQuant(3:4) tradeCost carryCost];
for i = 1:2 %#ok
y = .35 + (2-i)*(h + .02);
for j = 1:5
e = guicontrol('edit',f,[x(j) y w(j) h],num2str(n(i,j)),c{j},i);
if j == 1
set(e,'Style','text','String',s{i})
elseif j ==3
adjQuant(i) = e;
end
guicontrol('text',f,[x(j) .81 w(2) .17],l{j},[],[])
end
end
function[f] = validateNumericInput(source)
f = str2double(get(source,'String'));
if isnan(f)
set(source,'Background',fillColor{1})
beep
else
set(source,'Background','w')
end
end
function changeInitialAssetQuantity(source,event) %#ok
i = get(source,'UserData');
s = validateNumericInput(source);
aBegQuant(2 + i,1) = s;
set(adjQuant(i),'String',num2str(s))
end
function changeTradeCost(source,event) %#ok
tradeCost(get(source,'UserData')) = validateNumericInput(source)/100;
end
function changeCarryCost(source,event) %#ok
carryCost(get(source,'UserData')) = validateNumericInput(source);
end
end
function addFreqPanel
guicontrol('text',f,[.05 .1 .15 .20],'Hedge frequency',[],[])
b = uibuttongroup('Visible','on', ...
'Position',[.17 .01 .67 .35], ...
'BackgroundColor','w', ...
'BorderType','none',...
'SelectionChangeFcn',@changeHedgeFrequency, ...
'Units','normalized');
s = {'Never','Initially','Weekly','Daily'};
w = .225;
for i = 1:4 %#ok
x = .045 + (i-1)*(w + .002);
guicontrol('togglebutton',b,[x .10 w .80],s{i},[],i)
end
set(guicontrol('pushbutton',f,[.82 .05 .08 .72],'Go',@constructHedge,''),'Background',fillColor{2})
function constructHedge(source,event) %#ok
changeHedgeAssetSeries
end
function changeHedgeFrequency(source,event) %#ok
hedgeFreq = get(get(source,'SelectedObject'),'UserData');
end
end
end
function fillAssetPriceDefFrame(f,s,delta)
h = .40;
x = [.03 .20 .70];
w = [.15 .49 .20];
for i = 1:2 %#ok
y = .10 + (2-i)*(h + .02);
e(i+delta) = guicontrol('edit',f,[x(2) y w(2) h],aPriceDef{i+delta},@changeAssetPriceDef,i+delta); %#ok
guicontrol('pushbutton',f,[x(3) y w(3) h],'Evaluate',@changeAssetPriceDef,i+delta)
guicontrol('text',f,[x(1) y-.02 w(1) h],s{i},[],[])
end
function changeAssetPriceDef(source,event) %#ok
i = get(source,'UserData');
aPriceDef{i} = get(e(i),'String');
try
changePriceDeltaSeries(i)
set(e(i),'Background','w')
catch
set(e(i),'Background',fillColor{1})
beep
end
end
end
function fillOtherFrames
h = .40;
v = .14;
m = .43;
s = {'Hedge assets: prices and estimated deltas', ...
'Hedge assets: quantities and values'; ...
'Hedged assets: prices and estimated deltas', ...
'Portfolio value and accumulated trading costs'};
aPlot = nan(2,2,2);
for i = 1:2
for j = 1:2
x = df + j*(wf + .004);
y = v + (2-i)*(h + .03);
f = guifigure(s{i,j},[x y wf h]);
for k = 1:2
aPlot(i,j,k) = axes(...
'Parent',f, ...
'Position',[.11 .07 + (2-k)*(m + .02) .78 m], ...
'FontSize',8, ...
'XTick',[], ...
'Box','on');
end
end
end
end
function[varargout] = guifigure(name,pos)
h = figure(...
'Units','normalized', ...
'Position',pos, ...
'Name',name, ...
'NumberTitle','off', ...
'Color','w', ...
'Resize','off', ...
'MenuBar','none');
if nargout > 0
varargout(1) = {h};
end
end
function[varargout] = guicontrol(style,parent,pos,string,callback,data)
h = uicontrol(...
'Parent',parent, ...
'Units','normalized', ...
'Position',pos, ...
'Style',style, ...
'String',string, ...
'Callback',callback, ...
'UserData',data, ...
'FontSize',8,...
'HorizontalAlignment','center', ...
'BackgroundColor','w');
if nargout > 0
varargout(1) = {h};
end
end
function setLegend(h,string,pos)
set(legend(h,string,'Location',pos),'Box','off')
end
function[f] = roundto3(x)
f = fix(x*1000)/1000;
end
function changeFactorSeries %#ok
global T X fPathInput fPlot
try
T = begDate:endDate;
X = eval(fPathDef);
set(fPathInput,'Background','w')
catch
set(fPathInput,'Background',fillColor{1})
beep
end
displayFactorSeries
try
for i = 1:4
changePriceDeltaSeries(i)
end
catch
end
function displayFactorSeries
plot(fPlot,T,X,'LineWidth',2,'Color',lineColor{1})
setLegend(fPlot,'x','NorthWest')
d = [T(1) T(end)];
set(fPlot,'XLim',d,'XTick',d,'XTickLabel',datestr(d,2))
end
end
function changePriceDeltaSeries(i)
global T X ...
aPrice ...
aDelta
aPrice(i,:) = nan; %#ok
aDelta(i,:) = nan; %#ok
switch i
case 1, h = aPlot(2,1,1); legend = true;
case 2, h = aPlot(2,1,2); legend = false;
case 3, h = aPlot(1,1,1); legend = true;
case 4, h = aPlot(1,1,2); legend = false;
end
computePriceSeries
computeDeltaSeries
displayPriceDeltaSeries(h,aPrice(i,:),aDelta(i,:),legend)
changeHedgeAssetSeries
function computePriceSeries
p = eval(aPriceDef{i});
aPrice(i,:) = p(:)';
end
function computeDeltaSeries
X = X - .01; f1 = eval(aPriceDef{i});
X = X + .02; f2 = eval(aPriceDef{i});
X = X - .01;
d = (f2 - f1)./.02;
aDelta(i,:) = d(:)';
end
function displayPriceDeltaSeries(h,f,g,legend)
h = plotyy(h,T,f,T,g);
for j = 1:2 %#ok
set(get(h(j),'Children'),'LineWidth',2,'Color',lineColor{j})
set(h(j),'YColor',lineColor{j},'FontSize',8)
set(h(j),'XLim',[T(1) T(end)],'XTick',[])
end
if legend
setLegend(h(1),'Price','NorthWest')
setLegend(h(2),'Delta','NorthEast')
end
end
end
function changeHedgeAssetSeries %#ok
global T ...
aPrice ...
aDelta ...
adjQuant
n = length(T);
switch hedgeFreq
case 1, hedgeDay = [];
case 2, hedgeDay = 1;
case 3, hedgeDay = 1:7:n;
case 4, hedgeDay = 1:n;
end
changeHedgeQuantSeries
changeHedgeValueSeries
function changeHedgeQuantSeries
global aQuant aChangeQnt
aQuant = repmat(aBegQuant,1,n);
for j = 1:(n-1) %#ok
if ismember(j,hedgeDay)
A = [aDelta(3:4,j) aPrice(3:4,j) ]';
b = [sum(aDelta(1:2,j)) sum(aPrice(1:2,j))]';
aQuant(3:4,j) = -A\b;
else
if j > 1
aQuant(:,j) = aQuant(:,j-1);
end
end
end
aQuant(:,n) = aQuant(:,n-1);
aChangeQnt = diff(aQuant,1,2);
set(adjQuant(1),'String',sprintf('%6.2f',aQuant(3,1)))
set(adjQuant(2),'String',sprintf('%6.2f',aQuant(4,1)))
displayHedgeQuantSeries
function displayHedgeQuantSeries
for i = 1:2 %#ok
h = aPlot(1,2,i);
plot(h,T,roundto3(aQuant(2+i,:)),'LineWidth',2,'Color',lineColor{1});
set (h,'XLim' ,[T(1) T(end)],'XTick',[])
if i == 1
setLegend(h,'Quantity held','NorthWest')
else
xlabel(h,'* rounded to 0.001','FontAngle','italic')
end
end
end
end
function changeHedgeValueSeries
global aQuant aChangeQnt
totalValue = sum(aQuant.*aPrice);
tradeQuant = abs([aQuant(3:4,1) aChangeQnt(3:4,:)]);
tradeValue = tradeQuant.*aPrice(3:4,:);
tcostValue = nan(1,n);
for i = 1:n %#ok
tcostValue(i) = sum(tradeCost.*tradeValue(:,i));
end
cumTradeCost = cumsum(tcostValue);
for i = 1:2 %#ok
h = aPlot(2,2,i);
if i == 1
plot(h,T,0*T,'LineWidth',1,'Color','k')
set(h,'NextPlot','add')
plot(h,T,roundto3(totalValue),'LineWidth',2,'Color',lineColor{2})
set(h,'NextPlot','replace')
setLegend(h,'Portfolio value','NorthWest')
else
plot(h,T,roundto3(cumTradeCost),'LineWidth',2,'Color',lineColor{1})
setLegend(h,'Accumulated trading costs','NorthWest')
xlabel(h,'* rounded to 0.001','FontAngle','italic')
end
set(h,'XLim',[T(1) T(end)],'XTick',[])
end
end
end
end