move the math functions to a separate file; remove dependency on GSL due to license

This commit is contained in:
Kevin Keogh
2017-04-02 21:11:51 -04:00
parent d793ecb2fe
commit a8a96ba17a
6 changed files with 76 additions and 26 deletions

View File

@@ -1,9 +1,9 @@
CC=gcc CC=gcc
CFLAGS=-Wall -fPIC -O3 -ansi -pedantic-errors CFLAGS=-Wall -fPIC -O3 -ansi -pedantic-errors
LDFLAGS=-lgsl -lcblas -lm LDFLAGS=-lcblas -lm
PREFIX= /usr/local PREFIX= /usr/local
opt-pricer : src/opt-pricer.c gbm.o black_scholes.o opt-pricer : src/opt-pricer.c gbm.o black_scholes.o utils.o
@$(CC) $(CFLAGS) $^ $(LDFLAGS) -o $@ @$(CC) $(CFLAGS) $^ $(LDFLAGS) -o $@
gbm.o : src/gbm_mc.c gbm.o : src/gbm_mc.c
@@ -12,6 +12,9 @@ gbm.o : src/gbm_mc.c
black_scholes.o : src/black_scholes.c black_scholes.o : src/black_scholes.c
@$(CC) $(CFLAGS) -c $^ $(LDFLAGS) -o $@ @$(CC) $(CFLAGS) -c $^ $(LDFLAGS) -o $@
utils.o : src/utils.c
@$(CC) $(CFLAGS) -c $^ $(LDFLAGS) -o $@
.PHONY: install .PHONY: install
install : opt-pricer install : opt-pricer
@mkdir -p $(DESTDIR)$(PREFIX)/bin @mkdir -p $(DESTDIR)$(PREFIX)/bin
@@ -24,4 +27,4 @@ uninstall :
.PHONY: clean .PHONY: clean
clean : clean :
@rm -f gbm.o black_scholes.o @rm -f gbm.o black_scholes.o utils.o

View File

@@ -1,15 +1,11 @@
#define _XOPEN_SOURCE #define _XOPEN_SOURCE
#include "black_scholes.h" #include "black_scholes.h"
#include "utils.h"
#include <cblas.h> #include <cblas.h>
#include <math.h> #include <math.h>
#include <time.h> #include <time.h>
double normalcdf(double value)
{
return 0.5 * erfc(-value * M_SQRT1_2);
}
double bsm(double spot, double rfr, double vol, double strike, double bsm(double spot, double rfr, double vol, double strike,
struct tm expiry, struct tm value, int type) struct tm expiry, struct tm value, int type)
{ {

View File

@@ -1,12 +1,10 @@
#define _XOPEN_SOURCE #define _XOPEN_SOURCE
#define max(X,Y) (((X) > (Y)) ? (X) : (Y)) #define max(X,Y) (((X) > (Y)) ? (X) : (Y))
#include <gsl/gsl_statistics_double.h> #include "gbm_mc.h"
#include <gsl/gsl_rng.h> #include "utils.h"
#include <gsl/gsl_randist.h>
#include <math.h> #include <math.h>
#include <time.h> #include <time.h>
#include "gbm_mc.h"
double gbm_simulation(double spot, double rfr, double vol, double tte, double rand) double gbm_simulation(double spot, double rfr, double vol, double tte, double rand)
{ {
@@ -21,32 +19,23 @@ double gbm_simulation(double spot, double rfr, double vol, double tte, double ra
double gbm(double spot, double rfr, double vol, double strike, struct tm expiry, double gbm(double spot, double rfr, double vol, double strike, struct tm expiry,
struct tm value, int type, int sims) struct tm value, int type, int sims)
{ {
const gsl_rng_type *T;
double tte, expiry_date, value_date, level, price, rand; double tte, expiry_date, value_date, level, price, rand;
double *results; double results = 0;
gsl_rng *r;
int i; int i;
results = (double *)malloc(sizeof(double) * sims); if (sims < 1) sims = 1;
expiry_date = mktime(&expiry); expiry_date = mktime(&expiry);
value_date = mktime(&value); value_date = mktime(&value);
tte = difftime(expiry_date, value_date) / (60 * 60 * 24 * 365); tte = difftime(expiry_date, value_date) / (60 * 60 * 24 * 365);
/* GSL RNG setup */
gsl_rng_env_setup();
T = gsl_rng_default;
r = gsl_rng_alloc(T);
for (i=0; i<sims; i++) { for (i=0; i<sims; i++) {
rand = gsl_ran_gaussian(r, 1); rand = gaussrand();
level = gbm_simulation(spot, rfr, vol, tte, rand); level = gbm_simulation(spot, rfr, vol, tte, rand);
results[i] = max((level - strike) * type, 0); results += max((level - strike) * type, 0);
} }
price = gsl_stats_mean(results, 1, sims) * 1 / pow((1 + rfr), tte); price = results / sims * 1 / pow((1 + rfr), tte);
gsl_rng_free(r);
free(results);
return price; return price;
} }

View File

@@ -1,6 +1,8 @@
#ifndef GBM_MC #ifndef GBM_MC
#define GBM_MC #define GBM_MC
#include <time.h>
double gbm_simulation(double spot, double rfr, double vol, double tte, double rand); double gbm_simulation(double spot, double rfr, double vol, double tte, double rand);
double gbm(double spot, double rfr, double vol, double strike, struct tm expiry, struct tm value, int type, int sims); double gbm(double spot, double rfr, double vol, double strike, struct tm expiry, struct tm value, int type, int sims);

52
src/utils.c Normal file
View File

@@ -0,0 +1,52 @@
#define M_SQRT1_2 0.707106781186547524401
#include <math.h>
#include <stdlib.h>
double normalcdf(double z)
{
/* https://www.johndcook.com/blog/cpp_phi/ */
double a1, a2, a3, a4, a5, p, t, y;
int sign;
a1 = 0.254829592;
a2 = -0.284496736;
a3 = 1.421413741;
a4 = -1.453152027;
a5 = 1.061405429;
p = 0.3275911;
sign = 1;
if (z < 0)
sign = -1;
z = fabs(z) / pow(2, 0.5);
t = 1 / (1 + p * z);
y = 1 - (((((a5 * t + a4) * t) + a3) * t + a2) * t + a1) * t * exp(-z * z);
return 0.5 * (1 + sign * y);
}
double gaussrand()
{
static double V1, V2, S;
static int phase = 0;
double X;
if (phase == 0) {
do {
double U1 = (double)rand() / RAND_MAX;
double U2 = (double)rand() / RAND_MAX;
V1 = 2 * U1 - 1;
V2 = 2 * U2 - 1;
S = V1 * V1 + V2 * V2;
} while (S >= 1 || S == 0);
X = V1 * sqrt(-2 * log(S) / S);
} else {
X = V2 * sqrt(-2 * log(S) / S);
}
phase = 1 - phase;
return X;
}

8
src/utils.h Normal file
View File

@@ -0,0 +1,8 @@
#ifndef UTILS_H
#define UTILS_H
double normalcdf(double value);
double gaussrand();
#endif