No BSD License  

Highlights from
Visualize dynamic hedging

image thumbnail

Visualize dynamic hedging

by

 

28 Jan 2008 (Updated )

(via an interactive GUI)

hedgedemo
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

Contact us