%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Delta Hedging using time and moved based rebalancing times incorporating
%%% transaction costs.
%%% 
%%% Copyright (C) 2009  Sebastian Jaimungal
%%%
%%%
%%% This program is free software: you can redistribute it and/or modify
%%% it under the terms of the GNU General Public License as published by
%%% the Free Software Foundation, either version 3 of the License, or
%%% (at your option) any later version.
%%%
%%% This program is distributed in the hope that it will be useful,
%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%%% GNU General Public License for more details.
%%% 
%%% You should have received a copy of the GNU General Public License
%%% along with this program.  If not, see <http://www.gnu.org/licenses/>.
%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


function DHedge

    Nsims = 50;
    
    % turn to true to plot sample paths
    % turn to false to only show histograms -- reccommended when Nsims is
    % large
    DoSamplePathPlot = true;
    
    % size of moves in delta before rebalancing
    DDelta = 0.05;

    % transaction costs
    transS =  0.001;
    transOpt =  0.005;

    % maturity and number of steps
    T = 1;
    Nsteps = 252;
    
    % model parameters
    mu = 0.1;
    volP = 0.2;
    volI = 0.2;
    S0 = 100;
    K = 100;
    rf = 0.01;
    
    transS =  0.0025;

    
    % grab sample paths
    Spot = SimPath(Nsims, Nsteps, T, S0, mu, volP);
    
    dt = T/Nsteps;
    
    % matrix of time to maturities
    Terms = T - dt*(cumsum(ones(Nsims, Nsteps+1),2) - 1)+1e-10;
    
    % compute Deltas and Gammas with given sample path
    DeltaTimeBased = PutDelta(Spot, K, Terms, rf, volI);
    DeltaMoveBased = DeltaTimeBased;
    
    
    % compute portfolio value through time for each sample path
    PutPrices = PutPrice(Spot, K, Terms, rf, volI);
    
    % compute hedging portfolio
    NumSTimeBased = DeltaTimeBased;
    NumSMoveBased = NumSTimeBased;
   
        
    % store bank account amounts using time-based and move-based hedging
    BankMoveBased = zeros(Nsims, Nsteps+1);
    BankMoveBased(:,1) = PutPrices(1,1) - Spot(1,1) * NumSMoveBased(1,1) ...
                         - abs(NumSMoveBased(1,1)) * Spot(1,1) * transS;
    
    BankTimeBased = BankMoveBased;
    
    % store levels surrounding current delta hedge position
    DeltaBd = zeros(Nsims, 2);
    
    % stores whether a trade is made in move-based approach
    KeepDelta = zeros(Nsims,Nsteps);
    
    for i = 2 : Nsteps+1

        % compute bounding delta-levels
        DeltaBd(:,1) = ( NumSMoveBased(:,i-1)  ) - DDelta;
        DeltaBd(:,2) = DeltaBd(:,1) + 2 * DDelta;

        
        % stores whether or not the delta has moved enough
        RepTimeDelta = NumSTimeBased(:,i);
        
        KeepDelta(:,i-1) =     ( RepTimeDelta > DeltaBd(:,1) ) ...
                            .* ( RepTimeDelta < DeltaBd(:,2));
        
        % update positions if moved enough, otherwise keep old positions
        NumSMoveBased(:,i) =   NumSMoveBased(:,i-1) .* KeepDelta(:,i-1) ...
                              + NumSTimeBased(:,i) .* (1-KeepDelta(:,i-1));
                                  
        DeltaMoveBased(:,i) = NumSMoveBased(:,i);
                          
        % update bank account
        BankMoveBased(:,i) =  BankMoveBased(:,i-1)*exp(rf*dt) ...
                            + ( NumSMoveBased(:,i-1) - NumSMoveBased(:,i) ) .* Spot(:,i) ...
                            - abs( NumSMoveBased(:,i-1) - NumSMoveBased(:,i) ) .* Spot(:,i) * transS;
                        
        BankTimeBased(:,i) =  BankTimeBased(:,i-1)*exp(rf*dt) ...
                            + ( NumSTimeBased(:,i-1) - NumSTimeBased(:,i) ) .* Spot(:,i) ...
                            - abs( NumSTimeBased(:,i-1) - NumSTimeBased(:,i) ) .* Spot(:,i) * transS; 
        
    end
    
    % compute total pnl through the entire sample path
    pnlTimeBased = Spot.* NumSTimeBased + BankTimeBased - PutPrices;
    pnlMoveBased = Spot.* NumSMoveBased + BankMoveBased - PutPrices;
    

    % plot results....
    
    close all;
    
    if DoSamplePathPlot
        
        % Time Based...
        figure

        subplot(3,1,1);
        plot(Spot');
        %xlabel('time', 'Fontsize',12)
        ylabel('Spot Price', 'Fontsize',12)
        title('Time Based -- Spot price paths', 'Fontsize',12)

        subplot(3,1,2);
        plot(pnlTimeBased' )
        %xlabel('time', 'Fontsize',12)
        ylabel('Value', 'Fontsize',12)
        title('Time Based -- Hedged Portfolio Value', 'Fontsize',12)


        subplot(3,1,3);
        plot(DeltaTimeBased')
        xlabel('time', 'Fontsize',12)
        ylabel('Delta', 'Fontsize',12)
        title('Time Based -- Delta Position', 'Fontsize',12)
        
        
        % Move Based
        figure

        subplot(3,1,1);
        plot(Spot');
        %xlabel('time', 'Fontsize',12)
        ylabel('Spot Price', 'Fontsize',12)
        title('Move Based -- Spot price paths', 'Fontsize',12)

        subplot(3,1,2);
        plot(pnlMoveBased' )
        %xlabel('time', 'Fontsize',12)
        ylabel('Value', 'Fontsize',12)
        title('Move Based -- Hedged Portfolio Value', 'Fontsize',12)


        subplot(3,1,3);
        plot(DeltaMoveBased')
        xlabel('time', 'Fontsize',12)
        ylabel('Delta', 'Fontsize',12)
        title('Move Based -- Delta Position', 'Fontsize',12)

    end
        
    % historgram of terminal PnL
    bins = [-5:0.25:5];
    figure
    [ freq1 bins1 ] = hist(pnlTimeBased(:,Nsteps+1), bins);
    hist(pnlTimeBased(:,Nsteps+1), bins1);
    axis([bins(1) bins(end) 0 max(freq1)*1.1 ]);
    title('Time Based P n L');
    
    figure
    [ freq bins ] = hist(pnlMoveBased(:,Nsteps+1), bins);
    hist(pnlMoveBased(:,Nsteps+1), bins);
    axis([bins(1) bins(end) 0 max(freq)*1.1 ]);
    title('Move Based P n L');
    
%     bins = [-5:1:5];
%     [ freq(1,:) bins] = hist(pnlTimeBased(:,Nsteps+1), bins);    
%     [ freq(2,:) bins] = hist(pnlMoveBased(:,Nsteps+1), bins);
%     bar(bins', freq',1.5)
%     legend('Time Based', 'Move Based');
%     %axis([bins(1) bins(end) 0 max(freq)*1.1 ]);
%     %title('Move Based P n L');
%     %hold 
    
    % compare replication with payoff
    terminalReplTimeBased = Spot(:,end) .* NumSTimeBased(:,end)  + BankTimeBased(:,end);
    terminalReplMoveBased = Spot(:,end) .* NumSMoveBased(:,end)  + BankMoveBased(:,end);
    
    figure
    scatter(Spot(:,Nsteps+1), terminalReplTimeBased)
    hold
    plot( [0:1:250], max( K - [0:1:250], 0), '-r','LineWidth',3);
    hold
    title('Time Based Replication');
    axis([ 0 250 -25 125]);    
    
    figure
    scatter(Spot(:,Nsteps+1), terminalReplMoveBased)
    hold
    plot( [0:1:250], max( K - [0:1:250], 0), '-r','LineWidth',3);
    hold
    title('Move Based Replication');
    axis([ 0 250 -25 125]);    
    
    % plot histogram of number of trades using moved-based trading
    figure
    Ntrades = sum(1-KeepDelta,2);
    hist(Ntrades, [0:1:255]);
    title('Histogram of Number of Move-Based Trades');
    
end

function price = CallPrice(S, K, T, rf, sigma)

    dp = (log(S/K) + (rf + 1/2*sigma.^2).*T) ./ (sigma.*sqrt(T));
    dm = dp - sigma.*sqrt(T);
    
    price = S .* normcdf(dp, 0, 1) - K .* exp(-rf*T) .* normcdf(dm, 0, 1);
    
end

function delta = CallDelta(S, K, T, rf, sigma)

    dp = ( log(S ./ K) + (rf + 1/2 * sigma.^2).* T ) ./ (sigma.*sqrt(T));
    delta = normcdf(dp, 0, 1);
    
end

function gamma = CallGamma(S, K, T, rf, sigma)

    dp = ( log(S./K) + (rf + 1/2*sigma.^2).*T) ./ (sigma.*sqrt(T));
    gamma = normpdf(dp, 0, 1) ./ (sigma .* S .* sqrt(T) );
    
end

function vega = CallVega(S, K, T, rf, sigma)

    dp = ( log(S./K) + (rf + 1/2*sigma.^2).*T) ./ (sigma.*sqrt(T));
    
    vega = S .* normpdf(dp, 0, 1) .* sqrt(T); 
    
end


function price = PutPrice(S, K, T, rf, sigma)

    dp = ( log(S./K) + (rf + 1/2*sigma.^2).*T) ./ (sigma.*sqrt(T));
    dm = dp - sigma.*sqrt(T);
    
    price =  - S .* normcdf(-dp, 0, 1) + exp(-rf*T) .* K .* normcdf(-dm, 0, 1);
    
end

function delta = PutDelta(S, K, T, rf, sigma)

    dp = (log(S./K) + (rf + 1/2*sigma.^2).*T) ./ (sigma.*sqrt(T));
    delta = normcdf(dp, 0, 1) - 1;
    
end

function gamma = PutGamma(S, K, T, rf, sigma)

    dp = (log(S./K) + (rf + 1/2*sigma.^2).*T) ./ (sigma.*sqrt(T));
    gamma = normpdf(dp, 0, 1) ./ (sigma .* S .* sqrt(T) );
    
end

function vega = PutVega(S, K, T, rf, sigma)

    dp = (log(S./K) + (rf + 1/2*sigma.^2).*T) ./ (sigma.*sqrt(T));
    
    vega = S .* normpdf(dp, 0, 1) .* sqrt(T); 
    
end