From 785c546ba373b4fd4733e8595e11e362d139bf35 Mon Sep 17 00:00:00 2001 From: Kevin Keogh Date: Tue, 25 Jul 2017 23:10:05 -0400 Subject: [PATCH] Fix bugs, clean up code, standardize MC Greeks --- src/black_scholes.c | 2 +- src/gbm_mc.c | 18 +++++++++--------- src/opt-pricer.c | 42 ++++++++++++++++++++++++++---------------- src/utils.h | 4 +++- 4 files changed, 39 insertions(+), 27 deletions(-) diff --git a/src/black_scholes.c b/src/black_scholes.c index 00f0fa3..6b3c9e5 100644 --- a/src/black_scholes.c +++ b/src/black_scholes.c @@ -22,5 +22,5 @@ void bsm(struct Option *opt) price = opt->spot * normalcdf(d1 * opt->type) * opt->type - opt->strike * exp(-opt->rfr * tte) * normalcdf(d2 * opt->type) * opt->type; opt->fv = price; - opt->vega = opt->spot * exp(-opt->rfr * tte) * pow(tte, 0.5) * normalpdf(d1); + opt->vega = opt->spot / 100 * exp(-opt->rfr * tte) * pow(tte, 0.5) * normalpdf(d1); } diff --git a/src/gbm_mc.c b/src/gbm_mc.c index 98124eb..46bcd72 100644 --- a/src/gbm_mc.c +++ b/src/gbm_mc.c @@ -35,25 +35,25 @@ void gbm(struct Option *opt) rand = gaussrand(); level = gbm_simulation(opt->spot, opt->rfr, opt->vol, tte, rand); base += max((level - opt->strike) * opt->type, 0); - level = gbm_simulation(opt->spot + 0.01, opt->rfr, opt->vol, tte, rand); + level = gbm_simulation(opt->spot + 1, opt->rfr, opt->vol, tte, rand); delta_shift += max((level - opt->strike) * opt->type, 0); level = gbm_simulation(opt->spot, opt->rfr, opt->vol + 0.01, tte, rand); vega_shift += max((level - opt->strike) * opt->type, 0); - level = gbm_simulation(opt->spot, opt->rfr, opt->vol, tte + 1/365, rand); + level = gbm_simulation(opt->spot, opt->rfr, opt->vol, tte - 1./365., rand); theta_shift += max((level - opt->strike) * opt->type, 0); - level = gbm_simulation(opt->spot, opt->rfr + 0.0001, opt->vol, tte, rand); + level = gbm_simulation(opt->spot, opt->rfr + 0.01, opt->vol, tte, rand); rho_shift += max((level - opt->strike) * opt->type, 0); } price = base / opt->sims * 1 / pow((1 + opt->rfr), tte); delta = delta_shift / opt->sims * 1 / pow((1 + opt->rfr), tte); vega = vega_shift / opt->sims * 1 / pow((1 + opt->rfr), tte); - theta = theta_shift / opt->sims * 1 / pow((1 + opt->rfr), tte); - rho = rho_shift / opt->sims * 1 / pow((1 + opt->rfr), tte); + theta = theta_shift / opt->sims * 1 / pow((1 + opt->rfr), tte - 1./365.); + rho = rho_shift / opt->sims * 1 / pow((1 + opt->rfr + 0.01), tte); opt->fv = price; - opt->delta = (delta - price) * 100 * opt->spot; - opt->vega = (vega - price) * opt->spot; - opt->theta = (theta - price) * opt->spot; - opt->rho = (rho - price) * opt->spot; + opt->delta = (delta - price); + opt->vega = (vega - price); + opt->theta = (theta - price); + opt->rho = (rho - price); } diff --git a/src/opt-pricer.c b/src/opt-pricer.c index 2a386e2..6297ffd 100644 --- a/src/opt-pricer.c +++ b/src/opt-pricer.c @@ -73,7 +73,7 @@ int print_help(void) int main(int argc, char *argv[]) { double spot = 0, strike = 0, rfr = 0, vol = 0, sims = 1000; - char expiry_date[11], value_date[11], buffer[1024]; + char expiry_date[11], value_date[11]; int opt, option_index = 0, type = 0; struct tm value, expiry; struct Option bs_opt, mc_opt; @@ -84,7 +84,9 @@ int main(int argc, char *argv[]) memset(&expiry, 0, sizeof(expiry)); memset(&value, 0, sizeof(value)); - while ((opt = getopt_long(argc, argv, "s:k:r:v:d:e:N:cp:h", long_options, &option_index)) != -1) { + srand(time(NULL)); + + 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) { @@ -133,14 +135,16 @@ int main(int argc, char *argv[]) return 1; } - bs_opt.spot = spot; - bs_opt.strike = strike; - bs_opt.expiry_date = &expiry; - bs_opt.value_date = &value; - bs_opt.rfr = rfr; - bs_opt.vol = vol; - bs_opt.type = type; + bs_opt.spot = mc_opt.spot = spot; + bs_opt.strike = mc_opt.strike = strike; + bs_opt.expiry_date = mc_opt.expiry_date = &expiry; + bs_opt.value_date = mc_opt.value_date = &value; + bs_opt.rfr = mc_opt.rfr = rfr; + bs_opt.vol = mc_opt.vol = vol; + bs_opt.type = mc_opt.type = type; + mc_opt.sims = sims; + /* mc_opt.spot = spot; mc_opt.strike = strike; mc_opt.expiry_date = &expiry; @@ -148,13 +152,13 @@ int main(int argc, char *argv[]) mc_opt.rfr = rfr; mc_opt.vol = vol; mc_opt.type = type; - mc_opt.sims = sims; + */ strftime(expiry_date, 11, "%Y-%m-%d", &expiry); strftime(value_date, 11, "%Y-%m-%d", &value); bsm(&bs_opt); gbm(&mc_opt); - sprintf(&buffer[0], + printf( "\nValuation date: %s\n\n" " | BS Analytic | BS Monte Carlo |\n" " ---------------------------------------------\n" @@ -167,11 +171,11 @@ int main(int argc, char *argv[]) " |sims: | %4.2f| %4.2f|\n" " |exp: | %4.2s| %4.2f|\n" */ - " |Fair value: | %10.2f | %13.2f |\n" - " |Delta: | %10.2f | %13.2f |\n" - " |Vega: | %10.2f | %13.2f |\n" + " |Fair value: | %8.4f | %11.4f |\n" + " |Delta: | %8.4f | %11.4f |\n" + " |Vega: | %8.4f | %11.4f |\n" " |Theta: | %8.4f | %11.4f |\n" - " |Rho : | %8.4f | %11.4f |\n\n", + " |Rho: | %8.4f | %11.4f |\n", value_date, bs_opt.type, mc_opt.type, bs_opt.spot, mc_opt.spot, @@ -183,6 +187,12 @@ int main(int argc, char *argv[]) bs_opt.vega, mc_opt.vega, bs_opt.theta, mc_opt.theta, bs_opt.rho, mc_opt.rho); - printf("%s", buffer); + printf( + " ---------------------------------------------\n\n" + ); + /* + printf("%s", buffer1); + printf("%s", buffer2); + */ return 0; } diff --git a/src/utils.h b/src/utils.h index 01d87bf..71cbe2a 100644 --- a/src/utils.h +++ b/src/utils.h @@ -1,6 +1,8 @@ #ifndef UTILS_H #define UTILS_H +void srand(unsigned int seed); + double normalcdf(double z); double normalpdf(double z); @@ -18,7 +20,7 @@ struct Option { double spot; double rfr; double vol; - int sims; + long sims; /* fv and greeks */ double fv;