📄 swaption.java
字号:
/* WARANTY NOTICE AND COPYRIGHTThis program is free software; you can redistribute it and/ormodify it under the terms of the GNU General Public Licenseas published by the Free Software Foundation; either version 2of 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 ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.Copyright (C) Michael J. Meyermatmjm@mindspring.comspyqqqdia@yahoo.com*//* * Swaption.java * * Created on September 7, 2002, 4:33 PM */package Libor.LiborDerivatives;import Libor.LiborProcess.*;import Statistics.*;import Exceptions.*;import LinAlg.*;/** <p>Forward start payer swaption <code>swpn(T,[T_p,T_q],k)</code> pays off * <code>h=B_pq(T)*(S_pq(T)-k)^+</code> at exercise time <code>T=T_tau</code>, * where <code>k</code> is the strike rate and <code>S_pq(T)</code> is * the value of the <code>[T_p,T_q]</code>-swap rate at time <code>T</code>. * </p> * <p>Here <code>B_pq</code> is the annuity * <code>sum_{k=p}^{q-1}delta_kB_{k+1}</code> as usual. The time * <code>T=T_tau</code> of swaption exercise is assumed to be a point on the * Libor tenor structure.</p> * * @author Michael J. Meyer */public class Swaption extends LiborDerivative { int tau,p,q; // swap along [T_p,T_q], exercisable at time tau double kappa; //strike rate /******************************************************************************* * * CONSTRUCTOR * ******************************************************************************/ /** Libors needed for forward payoff are <code>L_j, j>=tau</code> * at time <code>T_tau</code> (forward transporting from time * <code>T_tau</code>). * * @param LP underlying Libor process. * @param p swap begins at <code>T_p</code>. * @param q swap ends at <code>T_q</code>. * @param tau swaption exercises at time <code>T_tau<=T_p</code>. * @param kappa strike rate. */ public Swaption (LiborProcess LP, int tau, int p, int q, double kappa) { super(LP,tau,tau,LP.X0LiborVector(tau)); this.tau=tau; this.p=p; this.q=q; this.kappa=kappa; hasControlVariate=true; controlVariateNeedsX0=false; controlVariateNeedsX1=false; } /******************************************************************************* * * FUNCTIONS NEEDED FOR THE APPROXIMATE ANALYTIC PRICE * ******************************************************************************/ /** <p>The weight <code>w^{p,q}_j(t)</code> in the representation of the * swap rate <code>S_pq(t)</code> as a convex combination of Libors. * See <i>LiborProcess.ps</i>. * * @param j Libor index in <code>[p,q)</code>. * @param t current discrete time. */ public double wpq(int j, int t) { double delta_j=LP.delta()[j]; return delta_j*LP.B(j+1,t)/LP.B_pq(p,q,t); } /** <p>The vector <code>x_pq(t)</code> used in the computation of the * approximation of the swap rate volatility. See * <i>LiborProcess.ps</i>.</p> * * @param t current discrete time. */ public ColtVector xpq(int t) { ColtVector x=new ColtVector(q-p); for(int j=p;j<q;j++){ double x_j=wpq(j,t)*LP.L(j,t); x.setQuick(j-p,x_j); } return x; } // end xpq /** <p>Conditionally deterministic approximation * to the aggregate volatility (square root of the quadratic variation * <code><log(S_pq)>_t^T</code>) of the swap rate <code>S_pq</code> * to expiration conditioned on the state of the Libor process * at time <code>t</code>.</p> * * <p>This quantity is used in the analytic approximation to the swaption * price {@link #analyticForwardPrice}. See <i>LiborProcess.ps</i></p> * * @param t current discrete time. */ public double Sigma(int t) { // compute the Cholesky root of the covariation matrix on [T_t,T_tau] // for the relevant Libors L_j, j=p,...,q-1. ColtMatrix Q=LP.logCovariationCholeskyRoot(p,q,Tc[t],Tc[tau]); Q.transposeSelf(); double nrm=xpq(t).timesEquals(Q).L2Norm(); return nrm/LP.swapRate(p,q,t); } /******************************************************************************* * * FORWARD TRANSPORTED PAYOFF * ******************************************************************************/ /** Payoff at time <code>T_tau</code> from current Libor path transported * forward from time <code>T_tau</code> to time <code>T_n</code>. */ public double currentForwardPayoff() { double k=LP.swapRate(p,q,tau), h; if(k<kappa) return 0; h=LP.B_pq(p,q,tau)*(k-kappa); // move this from time T_tau to time T_n return h*LP.forwardTransport(tau); } /** Mean of the control variate conditioned on the state of the * Libor path at time <code>t</code>. This is * <code>(B_p(t)-B_q(t))/B_n(t)</code> * (a <code>P_n</code>-martingale), see <i>LiborProcess.ps</i>. * * @param t current discrete time <code>t<=T</code>. */ public double controlVariateMean(int t) { return (LP.B(p,t)-LP.B(q,t))/LP.B(n,t); } /** Control variate is <code>(B_p(T)-B_q(T))/B_n(T), T=T_tau</code>. * See <i>LiborProcess.ps</i> */ public double[] currentControlledForwardPayoff() { double h=currentForwardPayoff(), cv=(LP.B(p,tau)-LP.B(q,tau))/LP.B(n,tau); return new double[] {h,cv}; } /** <p>The forward transported payoff (as seen from time <code>t=0</code>) * computed from a new sample of the <code>LiborVector</code> object * <code>U=(X^0_tau(T_tau),...,X^0_{n-1}(T_tau))</code>, a log-normal * approximation to the vector of true Libors * <code>U=(X_tau(T_tau),...,X_{n-1}(T_tau))</code>. * Recall <code>X_j(t)=delta_jL_j(t)</code>, see document * <i>LiborProcess.ps</i>.</p> */ public double lognormalForwardPayoffSample() { LV.nextSample(); double h=LV.B_pqTm(p,q)*Math.max(LV.S_pqTm(p,q)-kappa,0); // move this from time T_tau to time T_n return h*LV.forwardTransport(); }/******************************************************************************* * * ANALYTIC PRICE * ******************************************************************************/ /** <p>Analytic approximation to the swaption price. Based on a log-normal * distribution of the swap rate conditioned on the state of the Libor path * at the time <code>t</code> of pricing. * * @param t current discrete time. */ public double analyticForwardPrice(int t) { double S_pqt=LP.swapRate(p,q,t), // S_pq(t) swpnSigma,Nplus,Nminus; // at time t=tau it's the forward transported payoff if(t==tau)return currentForwardPayoff(); // if t<T swpnSigma=Sigma(t); // aggregate volatility to expiry Nplus=FinMath.N(FinMath.d_plus(S_pqt,kappa,swpnSigma)); Nminus=FinMath.N(FinMath.d_minus(S_pqt,kappa,swpnSigma)); return LP.B_pq(p,q,t)*(S_pqt*Nplus-kappa*Nminus)/LP.B(n,t); } //end analyticForwardPrice() /******************************************************************************* * * TEST PROGRAM * ******************************************************************************/ /** <p>Test program. Allocates a Libor process of dimension * <code>n=15</code> and prices the (at the money) swaption * <code>swpn(T_5,[T_5,T_15],0.04)</code>. * * <p>The Monte Carlo forward price of this swaption * at time <code>T_n</code> is compared to the analytic price and * to the Monte carlo price based on the log-normal Libor approximation * <code>X0</code> and the correlation of the payoff with the control * variate computed. * The forward transporting and discounting involves all Libors * <code>L_j, j>=5</code>.</p> */ public static void main(String[] args) { // Libor process setup int n=15, // dimension of Libor process tau=3, // swaption exercisable at time T_tau p=5, q=15; // [T_p,T_q]-swaption double kappa=0.03; // strike rate // Libor parameter sample final LMM_Parameters lmmParams=new LMM_Parameters(n,LMM_Parameters.CS); final LiborProcess LP=new LiborProcess(lmmParams); final LiborDerivative swpn=new Swaption(LP,tau,p,q,kappa); // all prices forward prices at time T_n double aprice, // approximate analytic price mcprice, // Monte carlo price cvmcprice, // Monte carlo price with control variate lgnprice; // log-normal price int nPath=40000; // number of Libor paths System.out.print ("\nSWAPTION: \n"+ "Correlation of payoff with control variate, "+nPath/4+" paths: "); double cvcorr=swpn.controlledForwardPayoff(). correlationWithControlVariate(0,nPath/4); cvcorr=FinMath.round(cvcorr,4); System.out.print(cvcorr+"\n\nPrice, "+nPath+" paths:\n\n"); aprice=swpn.analyticForwardPrice(0); mcprice=swpn.monteCarloForwardPrice(0,nPath); cvmcprice=swpn.controlledMonteCarloForwardPrice(0,nPath); lgnprice=swpn.lognormalMonteCarloForwardPrice(nPath); aprice=FinMath.round(aprice,8); mcprice=FinMath.round(mcprice,8); cvmcprice=FinMath.round(cvmcprice,8); lgnprice=FinMath.round(lgnprice,8); String report= "approximate analytic: "+aprice+"\n"+ "Monte Carlo: "+mcprice+"\n"+ "Monte Carlo with control variate: "+cvmcprice+"\n"+ "log-normal Monte Carlo: "+lgnprice; System.out.println(report); } // end main } // end Swaption
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -