Guest User

Untitled

a guest
Nov 12th, 2011
176
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.14 KB | None | 0 0
  1. #include <stdint.h>
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. #include <math.h>
  5. #include <pthread.h>
  6. #include <stdint.h>
  7.  
  8. #define NS 10
  9. #define CORES 4
  10.  
  11. uint32_t initialSeed( size_t index )
  12. {
  13.   uint32_t seed = 1;
  14.   uint32_t mult = 300773;
  15.   size_t mask = 1;
  16.   while ( mask != 0 )
  17.   {
  18.     if ( index & mask )
  19.       seed = (seed * mult) % 1073741824;
  20.     mult = (mult * mult) % 1073741824;
  21.     mask <<= 1;
  22.   }
  23.   return seed;
  24. }
  25.  
  26. double nextUniform01( uint32_t* seed )
  27. {
  28.   *seed = (*seed * 300773) % 1073741824;
  29.   //printf( "%u\n", (unsigned)seed );
  30.   return (double)*seed / (double)1073741824.0;
  31. }
  32.  
  33. double randomNormal( uint32_t* seed )
  34. {
  35.   double x1, x2, w;
  36.   do
  37.   {
  38.     x1 = 2.0 * nextUniform01( seed ) - 1.0;
  39.     x2 = 2.0 * nextUniform01( seed ) - 1.0;
  40.     w = x1 * x1 + x2 * x2;
  41.   } while ( w >= 1.0 );
  42.   w = sqrt( (-2.0 * log(w)) / w );
  43.   return x1 * w;
  44. }
  45.  
  46. void randomNormalVec( double vec[NS], uint32_t* seed )
  47. {
  48.   for ( size_t i=0; i<NS; ++i )
  49.     vec[i] = randomNormal( seed );
  50. }
  51.  
  52. void multMatVec( double const mat[NS][NS], double const vec[NS], double res[NS] )
  53. {
  54.   for ( size_t i=0; i<NS; ++i )
  55.   {
  56.     res[i] = 0.0;
  57.     for ( size_t j=0; j<NS; ++j )
  58.       res[i] += mat[i][j] * vec[j];
  59.   }
  60. }
  61.  
  62. double runTrial(
  63.   size_t index,
  64.   size_t numTradingDays,
  65.   double dt,
  66.   double sqrtDT,
  67.   double const choleskyTrans[NS][NS],
  68.   double const drifts[NS]
  69.   )
  70. {
  71.   uint32_t seed = initialSeed( 4096 * (1+index) );
  72.  
  73.   double amounts[NS];
  74.   for ( size_t i=0; i<NS; ++i )
  75.     amounts[i] = 100.0;
  76.  
  77.   for ( size_t day=0; day<numTradingDays; ++day )
  78.   {
  79.     double Z[NS];
  80.     randomNormalVec( Z, &seed );
  81.     double X[NS];
  82.     multMatVec( choleskyTrans, Z, X );
  83.     for ( size_t i=0; i<NS; ++i )
  84.       amounts[i] *= exp(drifts[i]*dt + X[i]*sqrtDT);
  85.   }
  86.  
  87.   double value = 0.0;
  88.   for ( size_t i=0; i<NS; ++i )
  89.     value += amounts[i];
  90.   return value;
  91. }
  92.  
  93. typedef struct FixedArgs_
  94. {
  95.   size_t numTradingDays;
  96.   double dt;
  97.   double sqrtDT;
  98.   double choleskyTrans[NS][NS];
  99.   double drifts[NS];
  100. } FixedArgs;
  101.  
  102. typedef struct Args_
  103. {
  104.   FixedArgs *fixedArgs;
  105.   size_t startIndex;
  106.   size_t endIndex;
  107.   double *trialResults;
  108. } Args;
  109.  
  110. void *threadEntry( void *_args )
  111. {
  112.   Args const *args = (Args const *)_args;
  113.   for ( size_t index = args->startIndex;
  114.     index != args->endIndex; ++index )
  115.   {
  116.     args->trialResults[index] = runTrial(
  117.       index,
  118.       args->fixedArgs->numTradingDays,
  119.       args->fixedArgs->dt,
  120.       args->fixedArgs->sqrtDT,
  121.       args->fixedArgs->choleskyTrans,
  122.       args->fixedArgs->drifts
  123.     );
  124.   }
  125.   return 0;
  126. }
  127.  
  128. void trans( double A[NS][NS], double B[NS][NS] )
  129. {
  130.   for ( size_t i=0; i<NS; ++i )
  131.   {
  132.     for ( size_t j=0; j<NS; ++j )
  133.     {
  134.       B[i][j] = A[j][i];
  135.     }
  136.   }
  137. }
  138.  
  139. void multMatMat( double A[NS][NS], double B[NS][NS], double R[NS][NS] )
  140. {
  141.   for ( size_t i=0; i<NS; ++i )
  142.   {
  143.     for ( size_t j=0; j<NS; ++j )
  144.     {
  145.       R[i][j] = 0.0;
  146.       for ( size_t k=0; k<NS; ++k )
  147.         R[i][j] += A[i][k] * B[k][j];
  148.     }
  149.   }
  150. }
  151.  
  152. void randomCorrelation( double R[NS][NS], uint32_t* seed )
  153. {
  154.   double T[NS][NS];
  155.   for ( size_t i=0; i<NS; ++i )
  156.   {
  157.     for ( size_t j=0; j<NS; ++j )
  158.     {
  159.       T[i][j] = randomNormal( seed );
  160.     }
  161.   }
  162.  
  163.   for ( size_t j=0; j<NS; ++j )
  164.   {
  165.     double sqSum = 0.0;
  166.     for ( size_t i=0; i<NS; ++i )
  167.     {
  168.       sqSum += T[i][j] * T[i][j];
  169.     }
  170.     double norm = sqrt( sqSum );
  171.     for ( size_t i=0; i<NS; ++i )
  172.       T[i][j] /= norm;
  173.   }
  174.  
  175.   double TTrans[NS][NS];
  176.   trans( T, TTrans );
  177.  
  178.   multMatMat( TTrans, T, R );
  179. }
  180.  
  181. void computeCholeskyTrans( double A[NS][NS], double B[NS][NS] )
  182. {
  183.   for ( size_t i=0; i<NS; ++i )
  184.     for ( size_t j=0; j<NS; ++j )
  185.       B[i][j] = 0.0;
  186.  
  187.   for ( size_t i=0; i<NS; ++i )
  188.   {
  189.     for ( size_t j=0; j<i+1; ++j )
  190.     {
  191.       double s = 0.0;
  192.       for ( size_t k=0; k<j; ++k )
  193.         s += B[i][k] * B[j][k];
  194.       if ( i == j )
  195.         B[i][i] = sqrt( A[i][i] - s );
  196.       else
  197.         B[i][j] = 1.0 / B[j][j] * (A[i][j] - s);
  198.     }
  199.   }
  200. }
  201.  
  202. int doubleCompare( void const *_lhs, void const *_rhs )
  203. {
  204.   double lhs = *(double const *)_lhs;
  205.   double rhs = *(double const *)_rhs;
  206.   if ( lhs < rhs )
  207.     return -1;
  208.   else if ( lhs > rhs )
  209.     return 1;
  210.   else return 0;
  211. }
  212.  
  213. int main( int argc, char **argv )
  214. {
  215.   size_t const numTrials = 1048576;
  216.   double *trialResults = malloc(sizeof(double) * numTrials);
  217.  
  218.   FixedArgs fixedArgs;
  219.   fixedArgs.numTradingDays = 252;
  220.   fixedArgs.dt = 1.0 / fixedArgs.numTradingDays;
  221.   fixedArgs.sqrtDT = sqrt( fixedArgs.dt );
  222.  
  223.   double priceMeans[NS];
  224.   for ( size_t i=0; i<NS; ++i )
  225.     priceMeans[i] = 25.0/fixedArgs.numTradingDays;
  226.  
  227.   double priceDevs[NS];
  228.   for ( size_t i=0; i<NS; ++i )
  229.     priceDevs[i] = 25.0/fixedArgs.numTradingDays;
  230.  
  231.   uint32_t seed = initialSeed(0);
  232.  
  233.   double priceCorrelations[NS][NS];
  234.   randomCorrelation( priceCorrelations, &seed );
  235.  
  236.   double priceCovariance[NS][NS];
  237.   for ( size_t i=0; i<NS; ++i )
  238.   {
  239.     for ( size_t j=0; j<NS; ++j )
  240.     {
  241.       priceCovariance[i][j] = priceDevs[i] * priceDevs[j] * priceCorrelations[i][j];
  242.     }
  243.   }
  244.  
  245.   computeCholeskyTrans( priceCovariance, fixedArgs.choleskyTrans );
  246.  
  247.   for ( size_t i=0; i<NS; ++i )
  248.     fixedArgs.drifts[i] = priceMeans[i] - priceCovariance[i][i]/2.0;
  249.  
  250.   Args args[CORES];
  251.   pthread_t threads[CORES-1];
  252.   for ( size_t core=0; core<CORES; ++core )
  253.   {
  254.     if ( core == 0 )
  255.       args[core].startIndex = 0;
  256.     else
  257.       args[core].startIndex = args[core-1].endIndex;
  258.     if ( core+1 == CORES )
  259.       args[core].endIndex = numTrials;
  260.     else
  261.       args[core].endIndex = args[core].startIndex + numTrials/CORES;
  262.     args[core].fixedArgs = &fixedArgs;
  263.     args[core].trialResults = trialResults;
  264.     if ( core+1 == CORES )
  265.       threadEntry( &args[core] );
  266.     else
  267.       pthread_create( &threads[core], 0, &threadEntry, &args[core] );
  268.   }
  269.  
  270.   for ( size_t core=0; core<CORES-1; ++core )
  271.     pthread_join( threads[core], 0 );
  272.  
  273.   qsort( trialResults, numTrials, sizeof(double), doubleCompare );
  274.  
  275.   printf( "VaR = %.16f\n", 100.0*NS - trialResults[(size_t)floor( 0.05 * numTrials )] );
  276.  
  277.   free(trialResults);
  278.  
  279.   return 0;
  280. }
  281.  
  282.  
Advertisement
Add Comment
Please, Sign In to add comment