diff --git a/build/opt-pricer b/build/opt-pricer deleted file mode 100755 index a2f084f..0000000 Binary files a/build/opt-pricer and /dev/null differ diff --git a/src/gbm_mc.c b/src/gbm_mc.c index be052b7..cf39a63 100644 --- a/src/gbm_mc.c +++ b/src/gbm_mc.c @@ -1,5 +1,5 @@ #define _XOPEN_SOURCE -#define max(X,Y) (((X) > (Y)) ? (X) : (Y)) +#define max(X, Y) (((X) > (Y)) ? (X) : (Y)) #include "gbm_mc.h" #include "utils.h" @@ -28,6 +28,8 @@ double gbm_simulation(double spot, double rfr, double vol, double tte, double ra void *run_simulations(void *opt_ptr) { + /* A single thread simulation, calculates the PV and Greeks */ + int i; double tte, theta_tte, expiry_date, value_date, level, rand, df; double delta_shift = 0, vega_shift = 0, theta_shift = 0, rho_shift = 0; @@ -36,16 +38,17 @@ void *run_simulations(void *opt_ptr) double base = 0; double max_rand = 0; - struct Option *opt = (struct Option*) opt_ptr; + struct Option *opt = (struct Option *) opt_ptr; - if (opt->sims < 1) opt->sims = 1; + if (opt->sims < 1) + opt->sims = 1; expiry_date = mktime(opt->expiry_date); value_date = mktime(opt->value_date); tte = difftime(expiry_date, value_date) / (60 * 60 * 24 * 365); theta_tte = tte - 1. / 365; - for (i=0; isims; i++) { + for (i = 0; i < opt->sims; i++) { rand = opt->randoms[i]; max_rand = rand > max_rand ? rand : max_rand; /* Base scenario */ @@ -103,30 +106,41 @@ void gbm(struct Option *opt) pthread_t *threads; struct Option *options; double **randoms; + options = malloc(sizeof(struct Option) * NUM_THREADS); - randoms = malloc(sizeof(double*) * NUM_THREADS); + randoms = malloc(sizeof(double *) * NUM_THREADS); + + /* Create 2D array */ for(i=0; isims / NUM_THREADS); } - /* generate array of normal randoms */ - for(i=0;;) { - if (j == (opt->sims / NUM_THREADS)) { + /* Fill 2D array with normal randoms + * The purpose is to give the Option structs the random + * numbers they will need for simulations, as opposed to + * having the individual threads do so (rand() is not thread-safe) + */ + j = 0; + i = 0; + for(i = 0; i < NUM_THREADS;){ + randoms[i][j] = gaussrand(); + if (j >= (opt->sims / NUM_THREADS)) { j = 0; i += 1; } - - if (i == NUM_THREADS) { - break; - } - - randoms[i][j] = gaussrand(); j++; } + /* Set the number of simulations on a per-thread basis + */ opt->sims = opt->sims / NUM_THREADS; + for(i=0; iexpiry_date; options[i].value_date = opt->value_date; options[i].randoms = randoms[i]; @@ -145,8 +159,9 @@ void gbm(struct Option *opt) for(i=0; ifv += result->fv / NUM_THREADS; opt->delta += result->delta / NUM_THREADS; opt->gamma += result->gamma / NUM_THREADS; @@ -156,4 +171,9 @@ void gbm(struct Option *opt) opt->sims += result->sims; } + free(threads); + for(i=0; i #include +#include #include #include #include @@ -42,7 +43,7 @@ static struct helptext options[] = { "Put or call flag"}, {"-h, --help", "This help text"}, - { NULL , NULL } + { NULL, NULL } }; @@ -71,7 +72,7 @@ int print_help(void) } -char* read_type(struct Option opt) +char *read_type(struct Option opt) { return (opt.type == 1) ? "Call" : "Put"; } @@ -85,9 +86,6 @@ int main(int argc, char *argv[]) struct tm value, expiry; struct Option bs_opt, mc_opt; - extern char *optarg; - extern int getopt_long(); - memset(&expiry, 0, sizeof(expiry)); memset(&value, 0, sizeof(value)); @@ -95,46 +93,46 @@ int main(int argc, char *argv[]) while ((opt = getopt_long(argc, argv, "s:k:r:v:d:e:N:cph", long_options, &option_index)) != -1) { switch (opt) { - case 's': - if (sscanf(optarg, "%lf", &spot) == EOF) { - return 1; - }; - break; - case 'k': /* strike */ - if (sscanf(optarg, "%lf", &strike) == EOF) { - return 1; - }; - break; - case 'r': /* risk-free rate */ - if (sscanf(optarg, "%lf.", &rfr) == EOF) { - return 1; - }; - break; - case 'v': /* implied volatility */ - if (sscanf(optarg, "%lf", &vol) == EOF) { - return 1; - }; - break; - case 'e': /* expiry date, must be YYYY-MM-DD */ - strptime(optarg, "%Y-%m-%d", &expiry); - break; - case 'd': /* valuation date, must be YYYY-MM-DD */ - strptime(optarg, "%Y-%m-%d", &value); - break; - case 'N': /* number of simulations */ - if (sscanf(optarg, "%lf", &sims) == EOF) { - return 1; - }; - break; - case 'c': /* set as call */ - type = 1; - break; - case 'p': /* set as put */ - type = -1; - break; - case 'h': /* print help*/ - print_help(); - return 0; + case 's': + if (sscanf(optarg, "%lf", &spot) == EOF) { + return 1; + }; + break; + case 'k': /* strike */ + if (sscanf(optarg, "%lf", &strike) == EOF) { + return 1; + }; + break; + case 'r': /* risk-free rate */ + if (sscanf(optarg, "%lf.", &rfr) == EOF) { + return 1; + }; + break; + case 'v': /* implied volatility */ + if (sscanf(optarg, "%lf", &vol) == EOF) { + return 1; + }; + break; + case 'e': /* expiry date, must be YYYY-MM-DD */ + strptime(optarg, "%Y-%m-%d", &expiry); + break; + case 'd': /* valuation date, must be YYYY-MM-DD */ + strptime(optarg, "%Y-%m-%d", &value); + break; + case 'N': /* number of simulations */ + if (sscanf(optarg, "%lf", &sims) == EOF) { + return 1; + }; + break; + case 'c': /* set as call */ + type = 1; + break; + case 'p': /* set as put */ + type = -1; + break; + case 'h': /* print help */ + print_help(); + return 0; } } if (spot == 0 || strike == 0 || rfr == 0 || vol == 0) { @@ -156,7 +154,7 @@ int main(int argc, char *argv[]) bsm(&bs_opt); gbm(&mc_opt); - setlocale(LC_ALL,""); + setlocale(LC_ALL, ""); printf( "\nValuation date: %s\n\n" " | BS Analytic | BS Monte Carlo |\n" diff --git a/src/utils.c b/src/utils.c index 6c33e79..e226d43 100644 --- a/src/utils.c +++ b/src/utils.c @@ -35,11 +35,11 @@ double normalpdf(double z) } -double gaussrand() +double gaussrand(void) { /* Marsaglia and Bray, ``A Convenient Method for Generating Normal Variables'' */ static double V1, V2, S; - static int phase = 0; + static int phase; double X; if (phase == 0) { diff --git a/src/utils.h b/src/utils.h index 1297eb9..74e294d 100644 --- a/src/utils.h +++ b/src/utils.h @@ -1,13 +1,11 @@ #ifndef UTILS_H #define UTILS_H -void srand(unsigned int seed); - double normalcdf(double z); double normalpdf(double z); -double gaussrand(); +double gaussrand(void); struct Option { /* option details */