-
Notifications
You must be signed in to change notification settings - Fork 7
/
black-scholes.c
105 lines (92 loc) · 2.66 KB
/
black-scholes.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
/*
* Copyright (C) 2014-2015, 2018 Intel Corporation
*
* SPDX-License-Identifier: MIT
*/
#include <omp.h>
#include <mathimf.h>
#include "euro_opt.h"
#ifdef __DO_FLOAT__
# define EXP(x) expf(x)
# define LOG(x) logf(x)
# define SQRT(x) sqrtf(x)
# define ERF(x) erff(x)
# define INVSQRT(x) 1.0f/sqrtf(x)
# define QUARTER 0.25f
# define HALF 0.5f
# define TWO 2.0f
#else
# define EXP(x) exp(x)
# define LOG(x) log(x)
# define SQRT(x) sqrt(x)
# define ERF(x) erf(x)
# define INVSQRT(x) 1.0/sqrt(x)
# define QUARTER 0.25
# define HALF 0.5
# define TWO 2.0
#endif
/*
// This function computes the Black-Scholes formula.
// Input parameters:
// nopt - length of arrays
// s0 - initial price
// x - strike price
// t - maturity
//
// Implementation assumes fixed constant parameters
// r - risk-neutral rate
// sig - volatility
//
// Output arrays for call and put prices:
// vcall, vput
//
// Note: the restrict keyword here tells the compiler
// that none of the arrays overlap in memory.
*/
void BlackScholesFormula_Compiler( int nopt,
tfloat r, tfloat sig, tfloat * restrict s0, tfloat * restrict x,
tfloat * restrict t, tfloat * restrict vcall, tfloat * restrict vput )
{
int i;
tfloat a, b, c, y, z, e;
tfloat d1, d2, w1, w2;
tfloat mr = -r;
tfloat sig_sig_two = sig * sig * TWO;
#pragma omp parallel for simd shared(s0, x, t, vcall, vput)
#pragma vector nontemporal (vcall, vput)
for ( i = 0; i < nopt; i++ )
{
a = LOG( s0[i] / x[i] );
b = t[i] * mr;
z = t[i] * sig_sig_two;
c = QUARTER * z;
e = EXP ( b );
y = INVSQRT( z );
w1 = ( a - b + c ) * y;
w2 = ( a - b - c ) * y;
d1 = ERF( w1 );
d2 = ERF( w2 );
d1 = HALF + HALF*d1;
d2 = HALF + HALF*d2;
vcall[i] = s0[i]*d1 - x[i]*e*d2;
vput[i] = vcall[i] - s0[i] + x[i]*e;
}
}
void BlackScholesNaive(
int nopt, tfloat r, tfloat sig, const tfloat s0[], const tfloat x[],
const tfloat t[], tfloat vcall[], tfloat vput[] )
{
tfloat d1, d2, w1, w2;
int i;
for ( i=0; i<nopt; i++ )
{
d1 = ( LOG(s0[i]/x[i]) + (r + HALF*sig*sig)*t[i] ) /
( sig*SQRT(t[i]) );
d2 = ( LOG(s0[i]/x[i]) + (r - HALF*sig*sig)*t[i] ) /
( sig*SQRT(t[i]) );
w1 = HALF + HALF * ERF(d1 / SQRT(2));
w2 = HALF + HALF * ERF(d2 / SQRT(2));
vcall[i] = s0[i] * w1 - EXP(-r * t[i]) * x[i] * w2;
vput[i] = EXP(-r*t[i])*x[i] * -w2 - s0[i] * -w1;
}
}