Main Page | Namespace List | Class Hierarchy | Class List | File List | Class Members | File Members

rainbowoption.cpp

Go to the documentation of this file.
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);  // equaly weighted
00013         _CorrelationMatrix=IdentityMatrix(_NumberOfAssets); // we need the correlation to compute the paths
00014         _volatilities=valarray<Real>(RO_DEFAULT_VOL,_NumberOfAssets);
00015         _volatilitiesSurfaces=valarray<volsurface>(volsurface(RO_DEFAULT_VOL),_NumberOfAssets);
00016         _yc=yieldCurve(RO_DEFAULT_RATE); // no quanto so risk free rate is unique.
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; // the most famous one
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://no closed form
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://no closed form
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://no closed form
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; // in case we are in the case where user wants to see things
00180         Natural secIndexInSpotArray = (((security > 0)&&(security <=_NumberOfAssets) )? security -1: 0); // in case he enters 0..
00181         Real priceup,pricedown;
00182 
00183         Real oldSpot=_spots[secIndexInSpotArray]; // save it
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);// even if we do not have the closed form, the switch should get the MC
00188         _spots[secIndexInSpotArray]=spotDown;
00189         haveClosedFormVariablesBeenComputed=false;
00190         pricedown=getPrice(priceMethod);// even if we do not have the   closed form, the switch should get the MC
00191         _spots[secIndexInSpotArray]=oldSpot; // put it back
00192         haveClosedFormVariablesBeenComputed=false;
00193 
00194         _outputMsgs=outputmsgstate; // where it was
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; // in case we are in the case where user wants to see things
00201         Natural secIndexInSpotArray = (((security > 0)&&(security <=_NumberOfAssets) )? security -1: 0); // in case he enters 0..
00202         Real deltaup,deltadown;
00203 
00204         Real oldSpot=_spots[secIndexInSpotArray]; // save it
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);// even if we do not have the closed form, the switch should get the MC
00209         _spots[secIndexInSpotArray]=spotDown;
00210         haveClosedFormVariablesBeenComputed=false;
00211         deltadown=getPartialDelta(security,priceMethod);// even if we do not have the closed form, the switch should get the MC
00212         _spots[secIndexInSpotArray]=oldSpot; // put it back
00213         haveClosedFormVariablesBeenComputed=false;
00214 
00215         _outputMsgs=outputmsgstate; // where it was
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; // in case we are in the case where user wants to see things
00222         Natural secIndexInSpotArray = (((security > 0)&&(security <=_NumberOfAssets) )? security -1: 0); // in case he enters 0..
00223         Real priceup,pricedown;
00224 
00225         Real oldVol=_volatilities [secIndexInSpotArray]; // save it
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);// even if we do not have the closed form, the switch should get the MC
00230         _volatilities[secIndexInSpotArray]=volDown;
00231         haveClosedFormVariablesBeenComputed=false;
00232         pricedown=getPrice(priceMethod);// even if we do not have the closed form, the switch should get the MC
00233         _volatilities[secIndexInSpotArray]=oldVol; // put it back
00234         haveClosedFormVariablesBeenComputed=false;
00235 
00236         _outputMsgs=outputmsgstate; // where it was
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; // in case we are in the case where user wants to see things
00267         Real priceup,pricedown;
00268 
00269         Matrix oldCorrel=_CorrelationMatrix; // save it
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;//if corr =1 or -1, we cannot go beyond...
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);// even if we do not have the closed form, the switch should get the MC
00300         _CorrelationMatrix =corrdown;
00301         haveClosedFormVariablesBeenComputed=false;
00302         pricedown=getPrice(priceMethod);// even if we do not have the closed form, the switch should get the MC
00303         _CorrelationMatrix =oldCorrel; // put it back
00304         haveClosedFormVariablesBeenComputed=false;
00305 
00306         _outputMsgs=outputmsgstate; // where it was
00307         return (priceup-pricedown)/(2.0*(Real)GREEKAPPROX);
00308 }
00309 
00310 Real RainbowOption::getRho(priceType priceMethod){
00311         bool outputmsgstate=_outputMsgs ;
00312         _outputMsgs=false; // in case we are in the case where user wants to see things
00313         Real priceup,pricedown;
00314 
00315         yieldCurve oldYc=_yc; // save it
00316         yieldCurve ycup=_yc.shiftZCBRateCurve(0.001),ycdown=_yc.shiftZCBRateCurve(-0.001);
00317 
00318         _yc =ycup;
00319         haveClosedFormVariablesBeenComputed=false;
00320         priceup=getPrice(priceMethod);// even if we do not have the closed form, the switch should get the MC
00321         _yc =ycdown;
00322         haveClosedFormVariablesBeenComputed=false;
00323         pricedown=getPrice(priceMethod);// even if we do not have the closed form, the switch should get the MC
00324         _yc =oldYc; // put it back
00325         haveClosedFormVariablesBeenComputed=false;
00326 
00327         _outputMsgs=outputmsgstate; // where it was
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; // in case we are in the case where user wants to see things
00335         Real priceup,pricedown;
00336 
00337         Real oldMat=_expiryInYears; // save it
00338         Real up=_expiryInYears+timeStep,down=_expiryInYears-timeStep;
00339 
00340         _expiryInYears =up;
00341         haveClosedFormVariablesBeenComputed=false;
00342         priceup=getPrice(priceMethod);// even if we do not have the closed form, the switch should get the MC
00343         _expiryInYears =down;
00344         haveClosedFormVariablesBeenComputed=false;
00345         pricedown=getPrice(priceMethod);// even if we do not have the closed form, the switch should get the MC
00346         _expiryInYears =oldMat; // put it back
00347         haveClosedFormVariablesBeenComputed=false;
00348 
00349         _outputMsgs=outputmsgstate; // where it was
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++)// ATM is the more probable approximation
00380                 _volatilities[i]=_volatilitiesSurfaces[i].volatility(_spots[i],_startDate.plusDays((Natural)(365*_expiryInYears)));
00381 }
00382 
00383 Real RainbowOption::PriceByMc_2SpreadOptionMax(LongNatural nPaths)
00384 {
00385         // vol is to be adjusted atm, as W1*S1-W2*S2-K, the K has nothing to do with strike in the vol sense
00386         //reassignVolsAtThemoney();
00387         instanciateMCVariables();
00388         
00389         _MCEngine=MCEngine(nPaths,_DFTomaturity);
00390         _MCEngine.RunEngineRainbow2SpreadOptionMax(_pRandom,_pHazardRateProcesses,_thePayOff,_gaussianSample,_TerminalPoints,_weights,_CorrelationMatrix,_Multiplier);
00391         //reassignVolsAtThestrike();// put them back
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         //a bettor of is a max Call with stike 0
00424         //reassignVolsAtThemoney();
00425         Real tempStrike=_Strike;
00426         _Strike=EPSILON;
00427         instanciateMCVariables();
00428         
00429         Real result=PriceByMc_Max2AssetsCall(nPaths);
00430         _Strike=tempStrike; // put it back
00431         //reassignVolsAtThestrike();
00432         return result;
00433 
00434 }
00435 Real RainbowOption::PriceByMc_WorseOf2Assets(LongNatural nPaths){
00436         //a worse of is a min Call with stike 0
00437         //reassignVolsAtThemoney();
00438         Real tempStrike=_Strike;
00439         _Strike=EPSILON;
00440         instanciateMCVariables();
00441         Real result=PriceByMc_Min2AssetsCall(nPaths);
00442         _Strike=tempStrike; // put it back
00443         //reassignVolsAtThestrike();
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         //if K = 0 like in some BO asset (no cash, the d1 should go to -infinity)
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         //if K = 0 like in some BO asset (no cash, the d1 should go to -infinity)
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         //if K = 0 like in some BO asset (no cash, the d1 should go to -infinity)
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         //if K = 0 like in some BO asset (no cash, the d1 should go to -infinity)
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         //reassignVolsAtThemoney();
00592         Real temp=_Strike; //store it
00593         _Strike=EPSILON;
00594         compute_ClosedFormsParameters();// need to recompute in this case
00595         haveClosedFormVariablesBeenComputed=false;//so that if we price another one we can reuse the real values by recomputing.
00596         _Strike=temp;//memorize it back as key variables have been computed.
00597         //reassignVolsAtThestrike();// and the vols for future use
00598         return A + B + C; // with strike = 0 (that puts d1=d2=1)
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         //Should be deleted but if I do, I cannot price...
00682         //delete _pRandom; 
00683         //delete _MCEngine;
00684 }

Note: Generated nightly - reload for latest version
Generated on Thu Dec 22 23:12:37 2005 for terreneuve by doxygen 1.3.6