00001 #include ".\rainbowoption.h"
00002
00003 RainbowOption::RainbowOption(void)
00004 {
00005 Date today;
00006 today.setDateToToday();
00007 _startDate=today;
00008 _expiryInYears=RO_DEFAULT_MATURITY;
00009 _Strike=RO_DEFAULT_STRIKE;
00010 _Multiplier=1;
00011 _NumberOfAssets=RO_DEFAULT_NB_ASSETS;
00012 _weights=valarray<Real>(1/(Real)_NumberOfAssets ,_NumberOfAssets);
00013 _CorrelationMatrix=IdentityMatrix(_NumberOfAssets);
00014 _volatilities=valarray<Real>(RO_DEFAULT_VOL,_NumberOfAssets);
00015 _volatilitiesSurfaces=valarray<volsurface>(volsurface(RO_DEFAULT_VOL),_NumberOfAssets);
00016 _yc=yieldCurve(RO_DEFAULT_RATE);
00017 _spots=valarray<Real>(RO_DEFAULT_STRIKE,RO_DEFAULT_NB_ASSETS);
00018
00019 _DFTomaturity=_yc.discountFactor(_expiryInYears);
00020 haveClosedFormVariablesBeenComputed=false;
00021 _outputMsgs=false;
00022 _type=BestOf2AssetsCash;
00023
00024 _seed=(LongNatural)RO_SEED;
00025 MersenneTwister* pRandGen = new MersenneTwister(_seed);
00026 _pRandom=new Random(pRandGen);
00027 }
00028
00029 RainbowOption::RainbowOption(rainbowType type,Date startDate,Real expiry,Real Strike,yieldCurve yc,valarray<volsurface> vols,valarray <Real> spots,Real Multiplier,Matrix Correl,valarray<Real> weights,bool outputMsgs)
00030 : _type(type),
00031 _startDate(startDate),
00032 _expiryInYears(expiry),
00033 _Strike(Strike),
00034 _spots(spots),
00035 _yc(yc),
00036 _volatilitiesSurfaces(vols),
00037 _Multiplier(Multiplier),
00038 _CorrelationMatrix(Correl),
00039 _weights(weights),
00040 _outputMsgs(outputMsgs)
00041 {
00042 _NumberOfAssets=_CorrelationMatrix.GetRows();
00043 _thePayOff.SetStrike(_Strike);
00044 _DFTomaturity=_yc.discountFactor(_expiryInYears);
00045 reassignVolsAtThestrike();
00046 haveClosedFormVariablesBeenComputed=false;
00047 _seed=(LongNatural)RO_SEED;
00048 MersenneTwister* pRandGen = new MersenneTwister(_seed);
00049 _pRandom=new Random(pRandGen);
00050 }
00051
00052 RainbowOption::RainbowOption(rainbowType type,Date start,Real exp,Real Strike,yieldCurve yc,valarray<volsurface> vols,Real Spot1,Real Spot2,Real Mult,Real Correl12,Real weight1,Real weight2,bool outputMsgs)
00053 : _type(type),
00054 _startDate(start),
00055 _expiryInYears(exp),
00056 _Strike(Strike),
00057 _yc(yc),
00058 _volatilitiesSurfaces(vols),
00059 _Multiplier(Mult),
00060 _outputMsgs(outputMsgs)
00061 {
00062 _NumberOfAssets =2;
00063 _CorrelationMatrix=IdentityMatrix(_NumberOfAssets);
00064 _CorrelationMatrix.SetValue(1,0,Correl12);
00065 _CorrelationMatrix.SetValue(0,1,Correl12);
00066
00067 _weights=valarray<Real>(_NumberOfAssets);
00068 _weights[0]=weight1;
00069 _weights[1]=weight2;
00070
00071 _spots=valarray<Real>(_NumberOfAssets);
00072 _spots[0]=Spot1 ;
00073 _spots[1]=Spot2 ;
00074
00075 _DFTomaturity=_yc.discountFactor(_expiryInYears);
00076 _volatilities.resize(_NumberOfAssets);
00077
00078 reassignVolsAtThestrike();
00079 haveClosedFormVariablesBeenComputed=false;
00080 _seed=(LongNatural)RO_SEED;
00081 MersenneTwister* pRandGen = new MersenneTwister(_seed);
00082 _pRandom=new Random(pRandGen);
00083 }
00084
00085 Real RainbowOption::getPrice(priceType priceMethod,LongNatural nPaths){
00086 Real price;
00087 switch (_type) {
00088 case SpreadOptionMax:
00089 if((priceMethod!=MonteCarlo)&&(_outputMsgs))
00090 cout<<"In pricing the rainbow spread, you specified Closed form and there is no closed form\nPrice will be MC"<<endl;
00091 price=PriceByMc_2SpreadOptionMax(nPaths);
00092 break;
00093 case AssetsBasketMax:
00094 if((priceMethod!=MonteCarlo)&&(_outputMsgs))
00095 cout<<"In pricing the rainbow basket, you specified Closed form and there is no closed form\nPrice will be MC"<<endl;
00096 price=PriceByMc_2AssetsBasketMax(nPaths);
00097 break;
00098 case BestOf2AssetsCash:
00099 switch(priceMethod){
00100 case MonteCarlo:
00101 price=PriceByMc_BestOf2AssetsCash(nPaths);
00102 break;
00103 case ClosedForm:
00104 price=PriceByClosedForm_BestOf2_plusCash();
00105 break;
00106 }
00107 break;
00108 case WorstOf2AssetsCash:
00109 if((priceMethod!=MonteCarlo)&&(_outputMsgs))
00110 cout<<"In pricing the rainbow Worst of + cash, you specified Closed form and there is no closed form\nPrice will be MC"<<endl;
00111 price=PriceByMc_WorstOf2AssetsCash(nPaths);
00112 break;
00113 case BetterOf2Assets:
00114 switch(priceMethod){
00115 case MonteCarlo:
00116 price=PriceByMc_BetterOf2Assets(nPaths);
00117 break;
00118 case ClosedForm:
00119 price=PriceByClosedForm_BetterOf2();
00120 break;
00121 }
00122 break;
00123 case WorseOf2Assets:
00124 switch(priceMethod){
00125 case MonteCarlo:
00126 price=PriceByMc_WorseOf2Assets(nPaths);
00127 break;
00128 case ClosedForm:
00129 price=PriceByClosedForm_WorseOf2();
00130 break;
00131 }
00132 break;
00133 case Max2AssetsCall:
00134 switch(priceMethod){
00135 case MonteCarlo:
00136 price=PriceByMc_Max2AssetsCall(nPaths);
00137 break;
00138 case ClosedForm:
00139 price=PriceByClosedForm_MaxOf2_call();
00140 break;
00141 }
00142 break;
00143 case Min2AssetsCall:
00144 switch(priceMethod){
00145 case MonteCarlo:
00146 price=PriceByMc_Min2AssetsCall(nPaths);
00147 break;
00148 case ClosedForm:
00149 price=PriceByClosedForm_MinOf2_call();
00150 break;
00151 }
00152 break;
00153 case Max2AssetsPut:
00154 switch(priceMethod){
00155 case MonteCarlo:
00156 price=PriceByMc_Max2AssetsPut(nPaths);
00157 break;
00158 case ClosedForm:
00159 price=PriceByClosedForm_MaxOf2_put();
00160 break;
00161 }
00162 break;
00163 case Min2AssetsPut:
00164 switch(priceMethod){
00165 case MonteCarlo:
00166 price=PriceByMc_Min2AssetsPut(nPaths);
00167 break;
00168 case ClosedForm:
00169 price=PriceByClosedForm_MinOf2_put();
00170 break;
00171 }
00172 break;
00173 }
00174 return price;
00175 }
00176
00177 Real RainbowOption::getPartialDelta(Natural security,priceType priceMethod){
00178 bool outputmsgstate=_outputMsgs ;
00179 _outputMsgs=false;
00180 Natural secIndexInSpotArray = (((security > 0)&&(security <=_NumberOfAssets) )? security -1: 0);
00181 Real priceup,pricedown;
00182
00183 Real oldSpot=_spots[secIndexInSpotArray];
00184 Real spotUp=oldSpot*(1.0+(Real)GREEKAPPROX),spotDown=oldSpot*(1.0-(Real)GREEKAPPROX);
00185 _spots[secIndexInSpotArray]=spotUp;
00186 haveClosedFormVariablesBeenComputed=false;
00187 priceup=getPrice(priceMethod);
00188 _spots[secIndexInSpotArray]=spotDown;
00189 haveClosedFormVariablesBeenComputed=false;
00190 pricedown=getPrice(priceMethod);
00191 _spots[secIndexInSpotArray]=oldSpot;
00192 haveClosedFormVariablesBeenComputed=false;
00193
00194 _outputMsgs=outputmsgstate;
00195 return (priceup-pricedown)/(2.0*(Real)GREEKAPPROX);
00196 }
00197
00198 Real RainbowOption::getPartialGamma(Natural security,priceType priceMethod){
00199 bool outputmsgstate=_outputMsgs ;
00200 _outputMsgs=false;
00201 Natural secIndexInSpotArray = (((security > 0)&&(security <=_NumberOfAssets) )? security -1: 0);
00202 Real deltaup,deltadown;
00203
00204 Real oldSpot=_spots[secIndexInSpotArray];
00205 Real spotUp=oldSpot*(1.0+(Real)GREEKAPPROX),spotDown=oldSpot*(1.0-(Real)GREEKAPPROX);
00206 _spots[secIndexInSpotArray]=spotUp;
00207 haveClosedFormVariablesBeenComputed=false;
00208 deltaup=getPartialDelta(security,priceMethod);
00209 _spots[secIndexInSpotArray]=spotDown;
00210 haveClosedFormVariablesBeenComputed=false;
00211 deltadown=getPartialDelta(security,priceMethod);
00212 _spots[secIndexInSpotArray]=oldSpot;
00213 haveClosedFormVariablesBeenComputed=false;
00214
00215 _outputMsgs=outputmsgstate;
00216 return (deltaup-deltadown)/(2.0*(Real)GREEKAPPROX);
00217 }
00218
00219 Real RainbowOption::getPartialVega(Natural security,priceType priceMethod){
00220 bool outputmsgstate=_outputMsgs ;
00221 _outputMsgs=false;
00222 Natural secIndexInSpotArray = (((security > 0)&&(security <=_NumberOfAssets) )? security -1: 0);
00223 Real priceup,pricedown;
00224
00225 Real oldVol=_volatilities [secIndexInSpotArray];
00226 Real volUp=oldVol*(1.0+(Real)GREEKAPPROX),volDown=oldVol*(1.0-(Real)GREEKAPPROX);
00227 _volatilities[secIndexInSpotArray]=volUp;
00228 haveClosedFormVariablesBeenComputed=false;
00229 priceup=getPrice(priceMethod);
00230 _volatilities[secIndexInSpotArray]=volDown;
00231 haveClosedFormVariablesBeenComputed=false;
00232 pricedown=getPrice(priceMethod);
00233 _volatilities[secIndexInSpotArray]=oldVol;
00234 haveClosedFormVariablesBeenComputed=false;
00235
00236 _outputMsgs=outputmsgstate;
00237 return (priceup-pricedown)/(2.0*(Real)GREEKAPPROX);
00238 }
00239
00240 Real RainbowOption::getDelta(priceType priceMethod){
00241 Matrix partialDeltas=Matrix(0.0,_NumberOfAssets,1);
00242 for(Natural i=0;i<_NumberOfAssets;i++){
00243 partialDeltas.SetValue(i,0,getPartialDelta(i,priceMethod));
00244 }
00245 return partialDeltas.SumColumn(0);
00246 }
00247
00248 Real RainbowOption::getGamma(priceType priceMethod){
00249 Matrix partialGammas=Matrix(0.0,_NumberOfAssets,1);
00250 for(Natural i=0;i<_NumberOfAssets;i++){
00251 partialGammas.SetValue(i,0,getPartialGamma(i,priceMethod));
00252 }
00253 return partialGammas.SumColumn(0);
00254 }
00255
00256 Real RainbowOption::getVega(priceType priceMethod){
00257 Matrix partialVegas=Matrix(0.0,_NumberOfAssets,1);
00258 for(Natural i=0;i<_NumberOfAssets;i++){
00259 partialVegas.SetValue(i,0,getPartialVega(i,priceMethod));
00260 }
00261 return partialVegas.SumColumn(0);
00262 }
00263
00264 Real RainbowOption::getCorrelRisk(priceType priceMethod){
00265 bool outputmsgstate=_outputMsgs ;
00266 _outputMsgs=false;
00267 Real priceup,pricedown;
00268
00269 Matrix oldCorrel=_CorrelationMatrix;
00270 Natural size=(Natural)_CorrelationMatrix.GetRows();
00271 Matrix corrup=_CorrelationMatrix,corrdown=_CorrelationMatrix;
00272 Real multup=(1.0+(Real)GREEKAPPROX);
00273 Real multdown=(1.0-(Real)GREEKAPPROX);
00274 Real tempmult;
00275 for(Natural i=0;i<size;i++){
00276 for(Natural j=0;j<size;j++){
00277 if(i!=j){
00278 if(_CorrelationMatrix(i,j)==1){
00279 tempmult=multup;
00280 multup=1;
00281 }
00282 else if(_CorrelationMatrix(i,j)==-1){
00283 tempmult=multdown ;
00284 multdown =1;
00285 }
00286 corrup.SetValue(i,j,multup*_CorrelationMatrix(i,j));
00287 corrdown.SetValue(i,j,multdown*_CorrelationMatrix (i,j));
00288
00289 if(_CorrelationMatrix(i,j)==1)
00290 multup=tempmult;
00291 else if(_CorrelationMatrix(i,j)==-1)
00292 multdown =tempmult;
00293 }
00294 }
00295 }
00296
00297 _CorrelationMatrix =corrup;
00298 haveClosedFormVariablesBeenComputed=false;
00299 priceup=getPrice(priceMethod);
00300 _CorrelationMatrix =corrdown;
00301 haveClosedFormVariablesBeenComputed=false;
00302 pricedown=getPrice(priceMethod);
00303 _CorrelationMatrix =oldCorrel;
00304 haveClosedFormVariablesBeenComputed=false;
00305
00306 _outputMsgs=outputmsgstate;
00307 return (priceup-pricedown)/(2.0*(Real)GREEKAPPROX);
00308 }
00309
00310 Real RainbowOption::getRho(priceType priceMethod){
00311 bool outputmsgstate=_outputMsgs ;
00312 _outputMsgs=false;
00313 Real priceup,pricedown;
00314
00315 yieldCurve oldYc=_yc;
00316 yieldCurve ycup=_yc.shiftZCBRateCurve(0.001),ycdown=_yc.shiftZCBRateCurve(-0.001);
00317
00318 _yc =ycup;
00319 haveClosedFormVariablesBeenComputed=false;
00320 priceup=getPrice(priceMethod);
00321 _yc =ycdown;
00322 haveClosedFormVariablesBeenComputed=false;
00323 pricedown=getPrice(priceMethod);
00324 _yc =oldYc;
00325 haveClosedFormVariablesBeenComputed=false;
00326
00327 _outputMsgs=outputmsgstate;
00328 return (priceup-pricedown)/(2.0*(Real)GREEKAPPROX);
00329 }
00330
00331 Real RainbowOption::getTheta(priceType priceMethod){
00332 Real timeStep=1/365.0;
00333 bool outputmsgstate=_outputMsgs ;
00334 _outputMsgs=false;
00335 Real priceup,pricedown;
00336
00337 Real oldMat=_expiryInYears;
00338 Real up=_expiryInYears+timeStep,down=_expiryInYears-timeStep;
00339
00340 _expiryInYears =up;
00341 haveClosedFormVariablesBeenComputed=false;
00342 priceup=getPrice(priceMethod);
00343 _expiryInYears =down;
00344 haveClosedFormVariablesBeenComputed=false;
00345 pricedown=getPrice(priceMethod);
00346 _expiryInYears =oldMat;
00347 haveClosedFormVariablesBeenComputed=false;
00348
00349 _outputMsgs=outputmsgstate;
00350 return (priceup-pricedown)/(2.0*timeStep);
00351 }
00352
00353
00354 void RainbowOption::instanciateMCVariables()
00355 {
00356 Natural i;
00357 _Drifts.resize(_NumberOfAssets);
00358 for (i=0;i<_NumberOfAssets;i++){
00359 _Drifts[i]=Drift(_startDate,_expiryInYears,_yc.spotRate(_expiryInYears),_volatilities[i]);
00360 }
00361 _thePayOff.SetStrike(_Strike);
00362 _pRandom->SetSeed(RO_SEED);
00363 _gaussianSample=0.;
00364 _TerminalPoints.resize(_NumberOfAssets);
00365 _pHazardRateProcesses.resize(_NumberOfAssets);
00366 for(i=0;i<_NumberOfAssets;i++)
00367 {
00368 _pHazardRateProcesses[i]=GaussianProcess(_Drifts[i].GetvDates(),1,_spots[i],_Drifts[i].GetvDrift(),0.0,_volatilities[i]);
00369 }
00370 }
00371
00372 void RainbowOption::reassignVolsAtThestrike(){
00373 for (Natural i=0;i<_NumberOfAssets;i++)
00374 _volatilities[i]=_volatilitiesSurfaces[i].volatility(_Strike,_startDate.plusDays((Natural)(365*_expiryInYears)));
00375
00376 }
00377
00378 void RainbowOption::reassignVolsAtThemoney(){
00379 for (Natural i=0;i<_NumberOfAssets;i++)
00380 _volatilities[i]=_volatilitiesSurfaces[i].volatility(_spots[i],_startDate.plusDays((Natural)(365*_expiryInYears)));
00381 }
00382
00383 Real RainbowOption::PriceByMc_2SpreadOptionMax(LongNatural nPaths)
00384 {
00385
00386
00387 instanciateMCVariables();
00388
00389 _MCEngine=MCEngine(nPaths,_DFTomaturity);
00390 _MCEngine.RunEngineRainbow2SpreadOptionMax(_pRandom,_pHazardRateProcesses,_thePayOff,_gaussianSample,_TerminalPoints,_weights,_CorrelationMatrix,_Multiplier);
00391
00392 return _MCEngine.MCResult();
00393 }
00394
00395 Real RainbowOption::PriceByMc_2AssetsBasketMax(LongNatural nPaths)
00396 {
00397 instanciateMCVariables();
00398
00399 _MCEngine=MCEngine(nPaths,_DFTomaturity);
00400 _MCEngine.RunEngineRainbow2AssetsBasketMax(_pRandom,_pHazardRateProcesses,_thePayOff,_gaussianSample,_TerminalPoints,_weights,_CorrelationMatrix,_Multiplier);
00401 return _MCEngine.MCResult();
00402 }
00403
00404 Real RainbowOption::PriceByMc_BestOf2AssetsCash(LongNatural nPaths)
00405 {
00406 instanciateMCVariables();
00407
00408 _MCEngine=MCEngine(nPaths,_DFTomaturity);
00409 _MCEngine.RunEngineRainbowBestOf2AssetsCash(_pRandom,_pHazardRateProcesses,_thePayOff,_gaussianSample,_TerminalPoints,_weights,_CorrelationMatrix);
00410 return _MCEngine.MCResult();
00411 }
00412
00413 Real RainbowOption::PriceByMc_WorstOf2AssetsCash(LongNatural nPaths)
00414 {
00415 instanciateMCVariables();
00416
00417 _MCEngine=MCEngine(nPaths,_DFTomaturity);
00418 _MCEngine.RunEngineRainbowWorstOf2AssetsCash(_pRandom,_pHazardRateProcesses,_thePayOff,_gaussianSample,_TerminalPoints,_weights,_CorrelationMatrix);
00419 return _MCEngine.MCResult();
00420 }
00421
00422 Real RainbowOption::PriceByMc_BetterOf2Assets(LongNatural nPaths){
00423
00424
00425 Real tempStrike=_Strike;
00426 _Strike=EPSILON;
00427 instanciateMCVariables();
00428
00429 Real result=PriceByMc_Max2AssetsCall(nPaths);
00430 _Strike=tempStrike;
00431
00432 return result;
00433
00434 }
00435 Real RainbowOption::PriceByMc_WorseOf2Assets(LongNatural nPaths){
00436
00437
00438 Real tempStrike=_Strike;
00439 _Strike=EPSILON;
00440 instanciateMCVariables();
00441 Real result=PriceByMc_Min2AssetsCall(nPaths);
00442 _Strike=tempStrike;
00443
00444 return result;
00445 }
00446
00447 Real RainbowOption::PriceByMc_Max2AssetsCall(LongNatural nPaths)
00448 {
00449 instanciateMCVariables();
00450
00451 _MCEngine=MCEngine(nPaths,_DFTomaturity);
00452 _MCEngine.RunEngineRainbowMax2AssetsCall(_pRandom,_pHazardRateProcesses,_thePayOff,_gaussianSample,_TerminalPoints,_weights,_CorrelationMatrix,_Multiplier);
00453 return _MCEngine.MCResult();
00454 }
00455
00456 Real RainbowOption::PriceByMc_Min2AssetsCall(LongNatural nPaths)
00457 {
00458 instanciateMCVariables();
00459
00460 _MCEngine=MCEngine(nPaths,_DFTomaturity);
00461 _MCEngine.RunEngineRainbowMin2AssetsCall(_pRandom,_pHazardRateProcesses,_thePayOff,_gaussianSample,_TerminalPoints,_weights,_CorrelationMatrix,_Multiplier);
00462 return _MCEngine.MCResult();
00463 }
00464
00465 Real RainbowOption::PriceByMc_Max2AssetsPut(LongNatural nPaths)
00466 {
00467 instanciateMCVariables();
00468
00469 _MCEngine=MCEngine(nPaths,_DFTomaturity);
00470 _MCEngine.RunEngineRainbowMax2AssetsPut(_pRandom,_pHazardRateProcesses,_thePayOff,_gaussianSample,_TerminalPoints,_weights,_CorrelationMatrix,_Multiplier);
00471 return _MCEngine.MCResult();
00472 }
00473
00474 Real RainbowOption::PriceByMc_Min2AssetsPut(LongNatural nPaths)
00475 {
00476 instanciateMCVariables();
00477
00478 _MCEngine=MCEngine(nPaths,_DFTomaturity);
00479 _MCEngine.RunEngineRainbowMin2AssetsPut(_pRandom,_pHazardRateProcesses,_thePayOff,_gaussianSample,_TerminalPoints,_weights,_CorrelationMatrix,_Multiplier);
00480 return _MCEngine.MCResult();
00481 }
00482
00483 void RainbowOption::compute_sigmaA(){
00484 Real vol1,vol2,rho;
00485 vol1=_volatilities[0];
00486 vol2=_volatilities[1];
00487 rho=_CorrelationMatrix(0,1);
00488 sigmaA=sqrt(pow(vol1,2)+pow(vol2,2)-2*rho*vol1*vol2);
00489 }
00490
00491 void RainbowOption::compute_rho1(){
00492 Real vol1,vol2,rho;
00493 vol1=_volatilities[0];
00494 vol2=_volatilities[1];
00495 rho=_CorrelationMatrix(0,1);
00496 rho1=(rho*vol2-vol1)/sigmaA;
00497 }
00498
00499 void RainbowOption::compute_rho2(){
00500 Real vol1,vol2,rho;
00501 vol1=_volatilities[0];
00502 vol2=_volatilities[1];
00503 rho=_CorrelationMatrix(0,1);
00504 rho2=(rho*vol1-vol2)/sigmaA;
00505 }
00506
00507 void RainbowOption::compute_d1(){
00508 Real S1,vol1,rate;
00509 S1=_spots[0];
00510 vol1=_volatilities[0];
00511 rate=_yc.spotRate(_expiryInYears);
00512
00513 d1=(log(S1/_Strike)+(rate+0.5*pow(vol1,2))*_expiryInYears)/(vol1*sqrt(_expiryInYears));
00514 }
00515
00516 void RainbowOption::compute_d2(){
00517 Real S2,vol2,rate;
00518 S2=_spots[1];
00519 vol2=_volatilities[1];
00520 rate=_yc.spotRate(_expiryInYears);
00521
00522 d2=(log(S2/_Strike)+(rate+0.5*pow(vol2,2))*_expiryInYears)/(vol2*sqrt(_expiryInYears));
00523 }
00524
00525 void RainbowOption::compute_d3(){
00526 Real S1,S2;
00527 S1=_spots[0];
00528 S2=_spots[1];
00529
00530 d3=(log(S1/S2)+(0.5*pow(sigmaA,2))*_expiryInYears)/(sigmaA*sqrt(_expiryInYears));
00531 }
00532
00533 void RainbowOption::compute_d4(){
00534 Real S1,S2;
00535 S1=_spots[0];
00536 S2=_spots[1];
00537
00538 d4=(log(S2/S1)+(0.5*pow(sigmaA,2))*_expiryInYears)/(sigmaA*sqrt(_expiryInYears));
00539 }
00540
00541 void RainbowOption::compute_A(){
00542 Real S1=_spots[0];
00543 Real cum3=CumulativeNormal(d3);
00544 A=S1*(cum3-CumulativeBivariateNormal(-d1,d3,rho1));
00545 }
00546
00547 void RainbowOption::compute_B(){
00548 Real S2=_spots[1];
00549 Real cum4=CumulativeNormal(d4);
00550 B=S2*(cum4-CumulativeBivariateNormal(-d2,d4,rho2));
00551 }
00552
00553 void RainbowOption::compute_C(){
00554 Real vol1,vol2,rate,a,b,rho;
00555 vol1=_volatilities[0];
00556 vol2=_volatilities[1];
00557 rate=_yc.spotRate(_expiryInYears);
00558 a=-d1+vol1*sqrt(_expiryInYears);
00559 b=-d2+vol2*sqrt(_expiryInYears);
00560 rho=_CorrelationMatrix(0,1);
00561 C=_Strike*exp(-rate*_expiryInYears)*CumulativeBivariateNormal(a,b,rho);
00562 }
00563
00564 void RainbowOption::compute_ClosedFormsParameters(){
00565 compute_sigmaA();
00566 compute_rho1();
00567 compute_rho2();
00568 compute_d1();
00569 compute_d2();
00570 compute_d3();
00571 compute_d4();
00572 compute_A();
00573 compute_B();
00574 compute_C();
00575 }
00576
00577 Real RainbowOption::PriceByClosedForm_BestOf2_plusCash(){
00578 if(!haveClosedFormVariablesBeenComputed){
00579 compute_ClosedFormsParameters();
00580 haveClosedFormVariablesBeenComputed=true;
00581 }
00582 if(_outputMsgs)
00583 cout<<" Note to the user:\n This closed form solution of BestOf2+Cash reflects weight1=weight2=1 - MAX(S1,S2,Cash)"<<endl;
00584 return A + B + C;
00585 }
00586
00587 Real RainbowOption::PriceByClosedForm_BetterOf2(){
00588 if(_outputMsgs)
00589 cout<<" Note to the user:\n This closed form solution of BetterOf2 reflects weight1=weight2=1 and K=0 - MAX(S1,S2,0)"<<endl;
00590
00591
00592 Real temp=_Strike;
00593 _Strike=EPSILON;
00594 compute_ClosedFormsParameters();
00595 haveClosedFormVariablesBeenComputed=false;
00596 _Strike=temp;
00597
00598 return A + B + C;
00599 }
00600
00601 Real RainbowOption::PriceByClosedForm_WorseOf2(){
00602 if(_outputMsgs)
00603 cout<<" Note to the user:\n This closed form solution of WorstOf2 reflects weight1=weight2=1 and K=0 - MAX(MIN(S1,S2),0)"<<endl;
00604
00605 Real S1,S2,vol1,vol2,rate,bscall1,bscall2,bo;
00606 S1=_spots[0];
00607 S2=_spots[1];
00608 vol1=_volatilities[0];
00609 vol2=_volatilities[1];
00610 rate=_yc.spotRate(_expiryInYears);
00611 BlackScholes bs1= BlackScholes(S1,vol1,true,rate,EPSILON,_expiryInYears,Call);
00612 bscall1=bs1.getPrice();
00613 BlackScholes bs2= BlackScholes(S2,vol2,true,rate,EPSILON,_expiryInYears,Call);
00614 bscall2=bs2.getPrice();
00615 bo=PriceByClosedForm_BetterOf2();
00616
00617 return bscall1+bscall2-bo;
00618 }
00619
00620 Real RainbowOption::PriceByClosedForm_MaxOf2_call(){
00621 if(!haveClosedFormVariablesBeenComputed){
00622 compute_ClosedFormsParameters();
00623 haveClosedFormVariablesBeenComputed=true;
00624 }
00625 if(_outputMsgs)
00626 cout<<" Note to the user:\n This closed form solution of MaxOf2_call reflects multiplier=weight1=weight2=1 - MAX(MAX(S1,S2)-K,0)"<<endl;
00627
00628 Real rate= _yc.spotRate(_expiryInYears);
00629 return A + B + C - _Strike*exp(-rate*_expiryInYears);
00630 }
00631
00632 Real RainbowOption::PriceByClosedForm_MinOf2_call(){
00633 if(_outputMsgs)
00634 cout<<" Note to the user:\n This closed form solution of MinOf2_call reflects multiplier=weight1=weight2=1 - MAX(MIN(S1,S2)-K,0)"<<endl;
00635
00636 Real S1,S2,vol1,vol2,rate,bscall1,bscall2,maxcall;
00637 S1=_spots[0];
00638 S2=_spots[1];
00639 vol1=_volatilities[0];
00640 vol2=_volatilities[1];
00641 rate=_yc.spotRate(_expiryInYears);
00642 BlackScholes bs1= BlackScholes(S1,vol1,true,rate,_Strike,_expiryInYears,Call);
00643 bscall1=bs1.getPrice();
00644 BlackScholes bs2= BlackScholes(S2,vol2,true,rate,_Strike,_expiryInYears,Call);
00645 bscall2=bs2.getPrice();
00646 maxcall=PriceByClosedForm_MaxOf2_call();
00647
00648 return bscall1+bscall2-maxcall;
00649 }
00650
00651 Real RainbowOption::PriceByClosedForm_MaxOf2_put(){
00652 if(!haveClosedFormVariablesBeenComputed){
00653 compute_ClosedFormsParameters();
00654 haveClosedFormVariablesBeenComputed=true;
00655 }
00656 if(_outputMsgs)
00657 cout<<" Note to the user:\n This closed form solution of MaxOf2_put reflects multiplier=weight1=weight2=1 - MAX(K-MAX(S1,S2),0)"<<endl;
00658 Real rate= _yc.spotRate(_expiryInYears);
00659 return PriceByClosedForm_MaxOf2_call()-PriceByClosedForm_BetterOf2()+ _Strike*exp(-rate*_expiryInYears);
00660 }
00661
00662 Real RainbowOption::PriceByClosedForm_MinOf2_put(){
00663 if(_outputMsgs)
00664 cout<<" Note to the user:\n This closed form solution of MinOf2_put reflects multiplier=weight1=weight2=1 - MAX(K-MIN(S1,S2),0)"<<endl;
00665 Real S1,S2,vol1,vol2,rate,bsput1,bsput2;
00666 S1=_spots[0];
00667 S2=_spots[1];
00668 vol1=_volatilities[0];
00669 vol2=_volatilities[1];
00670 rate=_yc.spotRate(_expiryInYears);
00671 BlackScholes bs1= BlackScholes(S1,vol1,true,rate,_Strike,_expiryInYears,Put);
00672 bsput1=bs1.getPrice();
00673 BlackScholes bs2= BlackScholes(S2,vol2,true,rate,_Strike,_expiryInYears,Put);
00674 bsput2=bs2.getPrice();
00675
00676 return bsput1+bsput2-PriceByClosedForm_MaxOf2_put();
00677 }
00678
00679 RainbowOption::~RainbowOption(void)
00680 {
00681
00682
00683
00684 }