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
|
/*
Copyright (c) 2010-2023, Intel Corporation
SPDX-License-Identifier: BSD-3-Clause
*/
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
#define NOMINMAX
#pragma warning(disable : 4244)
#pragma warning(disable : 4305)
#endif
#include "options_defs.h"
#include <algorithm>
#include <math.h>
// Cumulative normal distribution function
static inline float CND(float X) {
float L = fabsf(X);
float k = 1.f / (1.f + 0.2316419f * L);
float k2 = k * k;
float k3 = k2 * k;
float k4 = k2 * k2;
float k5 = k3 * k2;
const float invSqrt2Pi = 0.39894228040f;
float w = (0.31938153f * k - 0.356563782f * k2 + 1.781477937f * k3 + -1.821255978f * k4 + 1.330274429f * k5);
w *= invSqrt2Pi * expf(-L * L * .5f);
if (X > 0.f)
w = 1.f - w;
return w;
}
void black_scholes_serial(float Sa[], float Xa[], float Ta[], float ra[], float va[], float result[], int count) {
for (int i = 0; i < count; ++i) {
float S = Sa[i], X = Xa[i];
float T = Ta[i], r = ra[i];
float v = va[i];
float d1 = (logf(S / X) + (r + v * v * .5f) * T) / (v * sqrtf(T));
float d2 = d1 - v * sqrtf(T);
result[i] = S * CND(d1) - X * expf(-r * T) * CND(d2);
}
}
void binomial_put_serial(float Sa[], float Xa[], float Ta[], float ra[], float va[], float result[], int count) {
float V[BINOMIAL_NUM];
for (int i = 0; i < count; ++i) {
float S = Sa[i], X = Xa[i];
float T = Ta[i], r = ra[i];
float v = va[i];
float dt = T / BINOMIAL_NUM;
float u = expf(v * sqrtf(dt));
float d = 1.f / u;
float disc = expf(r * dt);
float Pu = (disc - d) / (u - d);
for (int j = 0; j < BINOMIAL_NUM; ++j) {
float upow = powf(u, (float)(2 * j - BINOMIAL_NUM));
V[j] = std::max(0.f, X - S * upow);
}
for (int j = BINOMIAL_NUM - 1; j >= 0; --j)
for (int k = 0; k < j; ++k)
V[k] = ((1 - Pu) * V[k] + Pu * V[k + 1]) / disc;
result[i] = V[0];
}
}
|