move the math functions to a separate file; remove dependency on GSL due to license
This commit is contained in:
9
Makefile
9
Makefile
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
25
src/gbm_mc.c
25
src/gbm_mc.c
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
52
src/utils.c
Normal 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
8
src/utils.h
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#ifndef UTILS_H
|
||||||
|
#define UTILS_H
|
||||||
|
|
||||||
|
double normalcdf(double value);
|
||||||
|
|
||||||
|
double gaussrand();
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user