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

Normals.cpp

Go to the documentation of this file.
00001 #include ".\normals.h"
00002 /*
00003 code to implement the basic distribution functions necessary in mathematical finance
00004 via rational approximations
00005   */
00006  
00007 #include <cmath>
00008 
00009 // the basic math functions should be in namespace std but aren't in VCPP6
00010 #if !defined(_MSC_VER)
00011 using namespace std;
00012 #endif
00013 
00014 const Real OneOverRootTwoPi = 0.398942280401433; 
00015 
00016 // probability density for a standard Gaussian distribution
00017 Real NormalDensity(Real x)
00018 {
00019     return OneOverRootTwoPi*exp(-x*x/2);
00020 }
00021 
00022 // the InverseCumulativeNormal function via the Beasley-Springer/Moro approximation
00023 Real InverseCumulativeNormal(Real u)
00024 {
00025 
00026 
00027     static Real a[4]={  2.50662823884,
00028                         -18.61500062529,
00029                          41.39119773534,
00030                         -25.44106049637};
00031 
00032     static Real b[4]={-8.47351093090,
00033                         23.08336743743,
00034                        -21.06224101826,
00035                          3.13082909833};
00036 
00037     static Real c[9]={0.3374754822726147,
00038                         0.9761690190917186,
00039                         0.1607979714918209,
00040                         0.0276438810333863,
00041                         0.0038405729373609,
00042                         0.0003951896511919,
00043                         0.0000321767881768,
00044                         0.0000002888167364,
00045                         0.0000003960315187};
00046 
00047     
00048     Real x=u-0.5;
00049     Real r;
00050 
00051     if (fabs(x)<0.42) // Beasley-Springer
00052     {
00053         Real y=x*x;
00054         
00055         r=x*(((a[3]*y+a[2])*y+a[1])*y+a[0])/
00056                 ((((b[3]*y+b[2])*y+b[1])*y+b[0])*y+1.0);
00057                
00058     }
00059     else // Moro
00060     {
00061     
00062         r=u;
00063     
00064         if (x>0.0) 
00065             r=1.0-u;
00066         
00067         r=log(-log(r));
00068         
00069         r=c[0]+r*(c[1]+r*(c[2]+r*(c[3]+r*(c[4]+r*(c[5]+r*(c[6]+
00070                 r*(c[7]+r*c[8])))))));
00071         
00072         if (x<0.0) 
00073             r=-r;
00074     
00075     }
00076 
00077     return r;
00078 }
00079 
00080 
00081 // standard normal cumulative distribution function
00082 Real CumulativeNormal(Real x)
00083 {
00084     static Real a[5] = { 0.319381530,
00085                           -0.356563782,
00086                            1.781477937,
00087                           -1.821255978,
00088                            1.330274429};
00089 
00090     Real result;
00091     
00092     if (x<-7.0)
00093         result = NormalDensity(x)/sqrt(1.+x*x);
00094     
00095     else 
00096     {
00097         if (x>7.0)
00098             result = 1.0 - CumulativeNormal(-x);
00099         else
00100         {
00101             Real tmp = 1.0/(1.0+0.2316419*fabs(x));
00102 
00103             result=1-NormalDensity(x)*
00104                      (tmp*(a[0]+tmp*(a[1]+tmp*(a[2]+tmp*(a[3]+tmp*a[4])))));
00105 
00106             if (x<=0.0) 
00107                 result=1.0-result;
00108 
00109         }
00110     }
00111 
00112     return result;
00113 }
00114 
00115 
00116 Real Average(valarray<Real> Ptr,LongNatural dim)
00117 {
00118         LongNatural i;
00119         Real result=0;
00120 
00121         for (i=0;i<dim;i++)
00122         {
00123                 result+=Ptr[i];
00124         }
00125 
00126         result/=Real(dim);
00127         return result;
00128 }
00129 
00130 Real Maximize(valarray<Real> Ptr,LongNatural dim)
00131 {
00132         LongNatural i;
00133         Real result=0;
00134 
00135         for (i=0;i<dim;i++)
00136         {
00137                 if (Ptr[i]>result)
00138                         result=Ptr[i];
00139         }
00140 
00141         return result;
00142 }
00143 
00144 Real CumulativeBivariateNormal(Real a,Real b,Real rho)
00145 {
00146     static Real aarray[5]= {0.24840615, 0.39233107, 0.21141819, 0.03324666, 0.00082485334};
00147         static Real barray[5]={0.10024215, 0.48281397, 1.0609498, 1.7797294, 2.6697604};
00148  //   static Real aarray[4]= {0.325303, 0.4211071, 0.1334425, 0.006374323};
00149         //static Real barray[4]={0.1337764, 0.6243247, 1.3425378, 2.2626645};
00150     Real rho1 , rho2 , delta ;
00151     Real ap , bp ;
00152     Real Sum, Pi;
00153         Real sgnA,sgnB;
00154     Natural i , j ;
00155         Real BivN, denum;
00156 
00157         sgnA=(Real)sign(a);
00158         sgnB=(Real)sign(b);
00159     
00160         Pi = 3.14159265358979;
00161     if(pow(rho,2)==1)
00162                 rho=(Real)sign(rho)*0.99999;
00163     ap = a / sqrt(2 * (1 - pow(rho,2)));
00164     bp = b / sqrt(2 * (1 - pow(rho,2)));
00165     
00166         if( (a <= 0) && (b <= 0) && (rho <= 0) ){
00167         Sum = 0;
00168                 for (i = 0 ;i< 5;i++)
00169             for (j = 0 ;j< 5;j++)
00170                 Sum +=  + aarray[i] * aarray[j] * SubFunctionForBivariateNormal(barray[i], barray[j], ap, bp, rho);
00171         BivN = Sum * sqrt(1 - pow(rho,2)) / Pi;
00172         }  
00173         else if ((a <= 0 )&& (b >= 0) && (rho >= 0)) 
00174         BivN = CumulativeNormal(a) - CumulativeBivariateNormal(a, -b, -rho); 
00175     else if ((a >= 0) && (b <= 0) && (rho >= 0)) 
00176         BivN = CumulativeNormal(b) - CumulativeBivariateNormal(-a, b, -rho);
00177     else if ((a >= 0) && (b >= 0) && (rho <= 0))
00178         BivN = CumulativeNormal(a) + CumulativeNormal(b) - 1 + CumulativeBivariateNormal(-a, -b, rho);
00179         else if (a * b * rho >= 0) {
00180         denum = sqrt(pow(a,2) - 2 * rho * a * b + pow(b,2));
00181         rho1 = (rho * a - b) * sgnA / denum;
00182         rho2 = (rho * b - a) * sgnB / denum;
00183         delta = (1 - sgnA*sgnB) / 4;
00184         BivN = CumulativeBivariateNormal(a, 0, rho1) + CumulativeBivariateNormal(b, 0, rho2) - delta;
00185         }       
00186         return BivN;
00187 }
00188 
00189 Real SubFunctionForBivariateNormal(Real X,Real y,Real ap,Real bp,Real rho){
00190         Real r;
00191         r = ap * (2 * X - ap) + bp * (2 * y - bp) + 2 * rho * (X - ap) * (y - bp);
00192         return exp(r);
00193 }

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