function [price, delta, swp_premium, par_swap] = swaptionbyblk_bank( U, V, Curve )
%---------------------------------------------------------------------------------
% This function prices swaptions in the Black1976 model for any given cash-flow
% structure. It assumes (without checking) that the matrix U is an n by 5 (at least)
% matrix containing, respectively by column, the cash-flow code, the payment date
% (matlab format), the cash-flow (negative for fixed payer and positive otherwise),
% the coupon rate and finally the day-count basis. The earliest cash-flow is assumed to be
% a no coupon payment used to determine the settlement date of the swap. The coupon
% rate is expected to be constant and the strike is determined by the last coupon rate
% in line. The current date is the settlement date of the curve object, while the
% volatility matrix is assumed to be 10y by 10y (Exp-by-Mat) volatility surface.
%
% 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
% V : volatility matrix
% Curve : interest rate curve object
items=unique(U(:,1));
n_item=size(items,1);
CouponRate=cell(size(items));
Principal=cell(size(items));
CFDates=cell(size(items));
Basis=zeros(size(items));
accrued=zeros(size(items));
FixedLeg=zeros(size(items));
FloatLeg=zeros(size(items));
Annuity=zeros(size(items));
Settle=zeros(size(items));
Maturity=zeros(size(items));
oggi=Curve.Settle;
K=zeros(size(items));
price=zeros(size(items));
delta=zeros(size(items));
for i=1:n_item
H=U(U(:,1)==items(i),:);
[~,u]=sort(H(:,2));
H=H(u,:);
m=find(H(:,2)<=oggi,1,'last');
if isempty(m), m=0; end
CouponRate(i)={H(:,4)/100};
Principal(i)={H(:,3)};
CFDates(i)={H(:,2)};
Basis(i)=H(1,5);
CFDates_num=size(H,1);
K(i)=H(end,4);% record the fix rate
Settle(i)=H(1,2);
Maturity(i)=H(end,2);
if m<CFDates_num,
switch m
case 0
alpha=yearfrac(CFDates{i}(1:end-1),CFDates{i}(2:end),Basis(i));
disc_factors=Curve.getDiscountFactors(CFDates{i}(:));
disc_fwdRates=diff(-disc_factors);
FloatLeg(i)=Principal{i}(2:end)'*disc_fwdRates;
FixedLeg(i)=(Principal{i}(2:end).*CouponRate{i}(2:end))'*(disc_factors(2:end).*alpha);
Annuity(i)=(Principal{i}(2:end))'*(disc_factors(2:end).*alpha);
otherwise
cpnfrac=daysdif(oggi,CFDates{i}(m+1),Basis(i))/daysdif(CFDates{i}(m),CFDates{i}(m+1),Basis(i));
accrued(i)=-(1-cpnfrac)*Principal{i}(m+1)*CouponRate{i}(m+1);
alpha=yearfrac([oggi;CFDates{i}(m+1:end-1)],CFDates{i}(m+1:end),Basis(i));
disc_factors=[1;Curve.getDiscountFactors(CFDates{i}(m+1:end))];
disc_fwdRates=diff(-disc_factors);
FloatLeg(i)=Principal{i}(m+1:end)'*disc_fwdRates;
FixedLeg(i)=(Principal{i}(m+1:end).*CouponRate{i}(m+1:end))'*(disc_factors(2:end).*alpha);
Annuity(i)=abs(Principal{i}(m+1:end))'*(disc_factors(m+1:end).*alpha);
end
else
FloatLeg(i)=nan;
FixedLeg(i)=nan;
Annuity(i)=nan;
end
end
t=yearfrac(oggi,Settle,Basis);
m=yearfrac(Settle,Maturity,Basis);
[X,Y]=meshgrid((0:10)');
V=[[V(1,1);V(:,1)],[V(1,:);V]]/100;% expand V to include the 0's
v=interp2(X,Y,V,max(t,0),m);% avoid the possibly expired swaptions
v(t<=0)=0;
swp_premium = -(FixedLeg - FloatLeg);
par_swap = abs(FloatLeg) ./ Annuity;
[call put] = blsprice(par_swap,K/100,0,max(t,1e-15),v);
[Dcall Dput] = blsdelta(par_swap,K/100,0,max(t,1e-15),v);
for i=1:n_item,
if FixedLeg(i)>0,
price(i)=put(i)*Annuity(i);
delta(i)=Dput(i)*Annuity(i);
else
price(i)=call(i)*Annuity(i);
delta(i)=Dcall(i)*Annuity(i);
end
end
end