00001 #include ".\mcengine.h"
00002
00003 MCEngine::MCEngine(LongNatural nPaths,LongNatural nDates,valarray<Real> DiscFactors)
00004 : m_nDates(nDates),
00005 m_nPaths(nPaths)
00006 {
00007 m_price=0.;
00008 m_DiscFactor=DiscFactors[nDates-1];
00009 }
00010
00011 MCEngine::MCEngine(LongNatural nPaths,Real DFToMaturity)
00012 : m_nPaths(nPaths),
00013 m_DiscFactor(DFToMaturity)
00014 {
00015 m_nDates=1;
00016 m_price=0.;
00017
00018 }
00019
00020 MCEngine::~MCEngine()
00021 {
00022 }
00023
00024 MCEngine::MCEngine(void)
00025 {
00026 }
00027
00028 void MCEngine::RunEngineRainbow2SpreadOptionMax(Random* pRandom,valarray<GaussianProcess> pHazardRateProcesses,PayOff thePayOff,Real gaussianSample,valarray<Real> TerminalPoints,valarray<Real> weights,Matrix Correlation,Real Mult)
00029 {
00030 Natural size=Correlation.GetRows();
00031 Matrix independantShocks=Matrix(0.0,size,1);
00032 Matrix Cholesky=Correlation.CholeskyDecomposition();
00033 Matrix correlatedShocks=Matrix(0.0,size,1);
00034 for(LongNatural i=0;i<m_nPaths;++i)
00035 {
00036
00037 for(Natural j=0;j<size;j++){
00038 pRandom->GetGaussian(gaussianSample);
00039 independantShocks.SetValue(j,0,gaussianSample);
00040 }
00041
00042 correlatedShocks=Cholesky*independantShocks;
00043 for(Natural j=0;j<size;j++){
00044 TerminalPoints[j]=pHazardRateProcesses[j].BuildTerminalPoint((Real)correlatedShocks[j][0]);
00045 }
00046
00047 m_price+=thePayOff.Rainbow2SpreadOptionMax(TerminalPoints[0],TerminalPoints[1],weights[0],weights[1],Mult)*m_DiscFactor;
00048 }
00049 }
00050
00051 void MCEngine::RunEngineRainbow2AssetsBasketMax(Random* pRandom,valarray<GaussianProcess> pHazardRateProcesses,PayOff thePayOff,Real gaussianSample,valarray<Real> TerminalPoints,valarray<Real> weights,Matrix Correlation,Real Mult)
00052 {
00053 Natural size=Correlation.GetRows();
00054 Matrix independantShocks=Matrix(0.0,size,1);
00055 Matrix Cholesky=Correlation.CholeskyDecomposition();
00056 Matrix correlatedShocks=Matrix(0.0,size,1);
00057 for(LongNatural i=0;i<m_nPaths;++i)
00058 {
00059
00060 for(Natural j=0;j<size;j++){
00061 pRandom->GetGaussian(gaussianSample);
00062 independantShocks.SetValue(j,0,gaussianSample);
00063 }
00064
00065 correlatedShocks=Cholesky*independantShocks;
00066 for(Natural j=0;j<size;j++){
00067 TerminalPoints[j]=pHazardRateProcesses[j].BuildTerminalPoint((Real)correlatedShocks[j][0]);
00068 }
00069
00070 m_price+=thePayOff.Rainbow2AssetsBasketMax(TerminalPoints[0],TerminalPoints[1],weights[0],weights[1],Mult)*m_DiscFactor;
00071 }
00072 }
00073
00074
00075 void MCEngine::RunEngineRainbowBestOf2AssetsCash(Random* pRandom,valarray<GaussianProcess> pHazardRateProcesses,PayOff thePayOff,Real gaussianSample,valarray<Real> TerminalPoints,valarray<Real> weights,Matrix Correlation)
00076 {
00077 Natural size=Correlation.GetRows();
00078 Matrix independantShocks=Matrix(0.0,size,1);
00079 Matrix Cholesky=Correlation.CholeskyDecomposition();
00080 Matrix correlatedShocks=Matrix(0.0,size,1);
00081 for(LongNatural i=0;i<m_nPaths;++i)
00082 {
00083
00084 for(Natural j=0;j<size;j++){
00085 pRandom->GetGaussian(gaussianSample);
00086 independantShocks.SetValue(j,0,gaussianSample);
00087 }
00088
00089 correlatedShocks=Cholesky*independantShocks;
00090 for(Natural j=0;j<size;j++){
00091 TerminalPoints[j]=pHazardRateProcesses[j].BuildTerminalPoint((Real)correlatedShocks[j][0]);
00092 }
00093
00094 m_price+=thePayOff.RainbowBestOf2AssetsCash(TerminalPoints[0],TerminalPoints[1],weights[0],weights[1])*m_DiscFactor;
00095 }
00096 }
00097
00098 void MCEngine::RunEngineRainbowWorstOf2AssetsCash(Random* pRandom,valarray<GaussianProcess> pHazardRateProcesses,PayOff thePayOff,Real gaussianSample,valarray<Real> TerminalPoints,valarray<Real> weights,Matrix Correlation)
00099 {
00100 Natural size=Correlation.GetRows();
00101 Matrix independantShocks=Matrix(0.0,size,1);
00102 Matrix Cholesky=Correlation.CholeskyDecomposition();
00103 Matrix correlatedShocks=Matrix(0.0,size,1);
00104 for(LongNatural i=0;i<m_nPaths;++i)
00105 {
00106
00107 for(Natural j=0;j<size;j++){
00108 pRandom->GetGaussian(gaussianSample);
00109 independantShocks.SetValue(j,0,gaussianSample);
00110 }
00111
00112 correlatedShocks=Cholesky*independantShocks;
00113 for(Natural j=0;j<size;j++){
00114 TerminalPoints[j]=pHazardRateProcesses[j].BuildTerminalPoint((Real)correlatedShocks[j][0]);
00115 }
00116
00117 m_price+=thePayOff.RainbowWorstOf2AssetsCash(TerminalPoints[0],TerminalPoints[1],weights[0],weights[1])*m_DiscFactor;
00118 }
00119 }
00120
00121 void MCEngine::RunEngineRainbowMax2AssetsCall(Random* pRandom,valarray<GaussianProcess> pHazardRateProcesses,PayOff thePayOff,Real gaussianSample,valarray<Real> TerminalPoints,valarray<Real> weights,Matrix Correlation,Real Mult)
00122 {
00123 Natural size=Correlation.GetRows();
00124 Matrix independantShocks=Matrix(0.0,size,1);
00125 Matrix Cholesky=Correlation.CholeskyDecomposition();
00126 Matrix correlatedShocks=Matrix(0.0,size,1);
00127 for(LongNatural i=0;i<m_nPaths;++i)
00128 {
00129
00130 for(Natural j=0;j<size;j++){
00131 pRandom->GetGaussian(gaussianSample);
00132 independantShocks.SetValue(j,0,gaussianSample);
00133 }
00134
00135 correlatedShocks=Cholesky*independantShocks;
00136 for(Natural j=0;j<size;j++){
00137 TerminalPoints[j]=pHazardRateProcesses[j].BuildTerminalPoint((Real)correlatedShocks[j][0]);
00138 }
00139
00140 m_price+=thePayOff.RainbowMax2AssetsCall(TerminalPoints[0],TerminalPoints[1],weights[0],weights[1],Mult)*m_DiscFactor;
00141 }
00142 }
00143
00144 void MCEngine::RunEngineRainbowMin2AssetsCall(Random* pRandom,valarray<GaussianProcess> pHazardRateProcesses,PayOff thePayOff,Real gaussianSample,valarray<Real> TerminalPoints,valarray<Real> weights,Matrix Correlation,Real Mult)
00145 {
00146 Natural size=Correlation.GetRows();
00147 Matrix independantShocks=Matrix(0.0,size,1);
00148 Matrix Cholesky=Correlation.CholeskyDecomposition();
00149 Matrix correlatedShocks=Matrix(0.0,size,1);
00150 for(LongNatural i=0;i<m_nPaths;++i)
00151 {
00152
00153 for(Natural j=0;j<size;j++){
00154 pRandom->GetGaussian(gaussianSample);
00155 independantShocks.SetValue(j,0,gaussianSample);
00156 }
00157
00158 correlatedShocks=Cholesky*independantShocks;
00159 for(Natural j=0;j<size;j++){
00160 TerminalPoints[j]=pHazardRateProcesses[j].BuildTerminalPoint((Real)correlatedShocks[j][0]);
00161 }
00162
00163 m_price+=thePayOff.RainbowMin2AssetsCall(TerminalPoints[0],TerminalPoints[1],weights[0],weights[1],Mult)*m_DiscFactor;
00164 }
00165 }
00166
00167 void MCEngine::RunEngineRainbowMax2AssetsPut(Random* pRandom,valarray<GaussianProcess> pHazardRateProcesses,PayOff thePayOff,Real gaussianSample,valarray<Real> TerminalPoints,valarray<Real> weights,Matrix Correlation,Real Mult)
00168 {
00169 Natural size=Correlation.GetRows();
00170 Matrix independantShocks=Matrix(0.0,size,1);
00171 Matrix Cholesky=Correlation.CholeskyDecomposition();
00172 Matrix correlatedShocks=Matrix(0.0,size,1);
00173 for(LongNatural i=0;i<m_nPaths;++i)
00174 {
00175
00176 for(Natural j=0;j<size;j++){
00177 pRandom->GetGaussian(gaussianSample);
00178 independantShocks.SetValue(j,0,gaussianSample);
00179 }
00180
00181 correlatedShocks=Cholesky*independantShocks;
00182 for(Natural j=0;j<size;j++){
00183 TerminalPoints[j]=pHazardRateProcesses[j].BuildTerminalPoint((Real)correlatedShocks[j][0]);
00184 }
00185
00186 m_price+=thePayOff.RainbowMax2AssetsPut(TerminalPoints[0],TerminalPoints[1],weights[0],weights[1],Mult)*m_DiscFactor;
00187 }
00188 }
00189
00190 void MCEngine::RunEngineRainbowMin2AssetsPut(Random* pRandom,valarray<GaussianProcess> pHazardRateProcesses,PayOff thePayOff,Real gaussianSample,valarray<Real> TerminalPoints,valarray<Real> weights,Matrix Correlation,Real Mult)
00191 {
00192 Natural size=Correlation.GetRows();
00193 Matrix independantShocks=Matrix(0.0,size,1);
00194 Matrix Cholesky=Correlation.CholeskyDecomposition();
00195 Matrix correlatedShocks=Matrix(0.0,size,1);
00196 for(LongNatural i=0;i<m_nPaths;++i)
00197 {
00198
00199 for(Natural j=0;j<size;j++){
00200 pRandom->GetGaussian(gaussianSample);
00201 independantShocks.SetValue(j,0,gaussianSample);
00202 }
00203
00204 correlatedShocks=Cholesky*independantShocks;
00205 for(Natural j=0;j<size;j++){
00206 TerminalPoints[j]=pHazardRateProcesses[j].BuildTerminalPoint((Real)correlatedShocks[j][0]);
00207 }
00208
00209 m_price+=thePayOff.RainbowMin2AssetsPut(TerminalPoints[0],TerminalPoints[1],weights[0],weights[1],Mult)*m_DiscFactor;
00210 }
00211 }
00212
00213 void MCEngine::RunEngineAsianCall(Random* pRandom,GaussianProcess* pHazardRateProcess,PayOff thePayOff,valarray <Real> gaussianSample,valarray<Real> vHazardRatePath)
00214 {
00215 for(LongNatural i=0;i<m_nPaths;++i)
00216 {
00217 pRandom->GetGaussians(gaussianSample);
00218 vHazardRatePath=pHazardRateProcess->BuildPath(gaussianSample);
00219
00220 m_price+=thePayOff.AsianCall(vHazardRatePath,m_nDates)*m_DiscFactor;
00221 }
00222 }
00223
00224 void MCEngine::RunEngineAsianPut(Random* pRandom,GaussianProcess* pHazardRateProcess,PayOff thePayOff,valarray <Real> gaussianSample,valarray<Real> vHazardRatePath)
00225 {
00226 for(LongNatural i=0;i<m_nPaths;++i)
00227 {
00228 pRandom->GetGaussians(gaussianSample);
00229 vHazardRatePath=pHazardRateProcess->BuildPath(gaussianSample);
00230
00231 m_price+=thePayOff.AsianPut(vHazardRatePath,m_nDates)*m_DiscFactor;
00232 }
00233 }
00234
00235 void MCEngine::RunEngineCall(Random* pRandom,GaussianProcess* pHazardRateProcess,PayOff thePayOff,valarray<Real> gaussianSample,valarray<Real> vHazardRatePath)
00236 {
00237 for(LongNatural i=0;i<m_nPaths;++i)
00238 {
00239 if (i % 2 == 0)
00240 pRandom->GetGaussians(gaussianSample);
00241 else {
00242 for (LongNatural j=0;j<gaussianSample.size();j++) {
00243 gaussianSample[j]=-gaussianSample[j];
00244 }
00245 }
00246 vHazardRatePath=pHazardRateProcess->BuildPath(gaussianSample);
00247
00248 m_price+=thePayOff.Call(vHazardRatePath[0])*m_DiscFactor;
00249 }
00250 }
00251
00252 void MCEngine::RunEnginePut(Random* pRandom,GaussianProcess* pHazardRateProcess,PayOff thePayOff,valarray <Real> gaussianSample,valarray<Real> vHazardRatePath)
00253 {
00254 for(LongNatural i=0;i<m_nPaths;++i)
00255 {
00256 pRandom->GetGaussians(gaussianSample);
00257 vHazardRatePath=pHazardRateProcess->BuildPath(gaussianSample);
00258
00259 m_price+=thePayOff.Put(vHazardRatePath[0])*m_DiscFactor;
00260 }
00261 }
00262
00263 void MCEngine::RunEngineRevLookbackCall(Random* pRandom,GaussianProcess* pHazardRateProcess,PayOff thePayOff,valarray <Real> gaussianSample,valarray<Real> vHazardRatePath)
00264 {
00265 for(LongNatural i=0;i<m_nPaths;++i)
00266 {
00267 pRandom->GetGaussians(gaussianSample);
00268 vHazardRatePath=pHazardRateProcess->BuildPath(gaussianSample);
00269
00270 m_price+=thePayOff.RevLookbackCall(vHazardRatePath,m_nDates)*m_DiscFactor;
00271 }
00272 }
00273
00274 void MCEngine::RunEngineRevLookbackPut(Random* pRandom,GaussianProcess* pHazardRateProcess,PayOff thePayOff,valarray <Real> gaussianSample,valarray<Real> vHazardRatePath)
00275 {
00276 for(LongNatural i=0;i<m_nPaths;++i)
00277 {
00278 pRandom->GetGaussians(gaussianSample);
00279 vHazardRatePath=pHazardRateProcess->BuildPath(gaussianSample);
00280
00281 m_price+=thePayOff.RevLookbackPut(vHazardRatePath,m_nDates)*m_DiscFactor;
00282 }
00283 }
00284
00285 void MCEngine::RunEngineBarrierCall(Random* pRandom,GaussianProcess* pHazardRateProcess,PayOff thePayOff,valarray <Real> gaussianSample,valarray<Real> vHazardRatePath)
00286 {
00287 for(LongNatural i=0;i<m_nPaths;++i)
00288 {
00289 pRandom->GetGaussians(gaussianSample);
00290 vHazardRatePath=pHazardRateProcess->BuildPath(gaussianSample);
00291
00292 m_price+=thePayOff.BarrierCall(vHazardRatePath,m_nDates)*m_DiscFactor;
00293 }
00294 }
00295
00296 void MCEngine::RunEngineBarrierPut(Random* pRandom,GaussianProcess* pHazardRateProcess,PayOff thePayOff,valarray <Real> gaussianSample,valarray<Real> vHazardRatePath)
00297 {
00298 for(LongNatural i=0;i<m_nPaths;++i)
00299 {
00300 pRandom->GetGaussians(gaussianSample);
00301 vHazardRatePath=pHazardRateProcess->BuildPath(gaussianSample);
00302
00303 m_price+=thePayOff.BarrierPut(vHazardRatePath,m_nDates)*m_DiscFactor;
00304 }
00305 }
00306
00307 void MCEngine::RunEngineFlooredCliquet(Random* pRandom,GaussianProcess* pHazardRateProcess,PayOff thePayOff,valarray <Real> gaussianSample,valarray<Real> vHazardRatePath)
00308 {
00309 for(LongNatural i=0;i<m_nPaths;++i)
00310 {
00311 pRandom->GetGaussians(gaussianSample);
00312 vHazardRatePath=pHazardRateProcess->BuildPath(gaussianSample);
00313
00314 m_price+=thePayOff.FlooredCliquet(vHazardRatePath[0],vHazardRatePath[m_nDates])*m_DiscFactor;
00315 }
00316 }
00317
00318 void MCEngine::RunEngineCappedCliquet(Random* pRandom,GaussianProcess* pHazardRateProcess,PayOff thePayOff,valarray <Real> gaussianSample,valarray<Real> vHazardRatePath)
00319 {
00320 for(LongNatural i=0;i<m_nPaths;++i)
00321 {
00322 pRandom->GetGaussians(gaussianSample);
00323 vHazardRatePath=pHazardRateProcess->BuildPath(gaussianSample);
00324
00325 m_price+=thePayOff.CappedCliquet(vHazardRatePath[0],vHazardRatePath[m_nDates])*m_DiscFactor;
00326 }
00327 }
00328
00329 void MCEngine::RunEngineGeneral(Random* pRandom,GaussianProcess* pHazardRateProcess,PayOff thePayOff,valarray<Real> gaussianSample,valarray<Real> vHazardRatePath,Natural Product)
00330 {
00331 if (Product==1)
00332 this->RunEngineCall(pRandom,pHazardRateProcess,thePayOff,gaussianSample,vHazardRatePath);
00333 if (Product==2)
00334 this->RunEnginePut(pRandom,pHazardRateProcess,thePayOff,gaussianSample,vHazardRatePath);
00335 if (Product==3)
00336 this->RunEngineAsianCall(pRandom,pHazardRateProcess,thePayOff,gaussianSample,vHazardRatePath);
00337 if (Product==4)
00338 this->RunEngineAsianPut(pRandom,pHazardRateProcess,thePayOff,gaussianSample,vHazardRatePath);
00339 if (Product==5)
00340 this->RunEngineRevLookbackCall(pRandom,pHazardRateProcess,thePayOff,gaussianSample,vHazardRatePath);
00341 if (Product==6)
00342 this->RunEngineRevLookbackPut(pRandom,pHazardRateProcess,thePayOff,gaussianSample,vHazardRatePath);
00343 if (Product==7)
00344 this->RunEngineBarrierCall(pRandom,pHazardRateProcess,thePayOff,gaussianSample,vHazardRatePath);
00345 if (Product==8)
00346 this->RunEngineBarrierPut(pRandom,pHazardRateProcess,thePayOff,gaussianSample,vHazardRatePath);
00347 if (Product==9)
00348 this->RunEngineFlooredCliquet(pRandom,pHazardRateProcess,thePayOff,gaussianSample,vHazardRatePath);
00349 if (Product==10)
00350 this->RunEngineCappedCliquet(pRandom,pHazardRateProcess,thePayOff,gaussianSample,vHazardRatePath);
00351 }
00352
00353 Real MCEngine::MCResult()
00354 {
00355 return m_price/m_nPaths;
00356 }