Finance: Black-Scholes

The Black-Scholes Equation estimates the price of a European option over time. The formula itself can be used in a number of ways, the most basic of which is to use the projected value to smartly hedge the option on its underlying asset. The simulation in this sample is vectorized with Intel® C++ autovectorization and parallelized with OpenMP* Worksharing construct #pragma omp for.

 

Code Change Highlights:

  • #pragma omp for
  • linear version: (black_scholes.cpp, black_scholes_serial())
    for(int option = 0; option<OPT_N; ++option) {
            float T = OptionYears[option];
            float X = OptionStrike[option];
            float S = StockPrice[option];
            float sqrtT = sqrtf(T);
            float d1 = (logf(S / X) + (c_riskfree + c_half * c_volatility * c_volatility) * T) /
                       (c_volatility * sqrtT);
            float d2 = d1 - c_volatility * sqrtT;
    #ifdef _WIN32
            float CNDD1 = CND(d1);
            float CNDD2 = CND(d2);
    #else			
            float CNDD1 = c_half + c_half*erff(SQRT1_2*d1);
            float CNDD2 = c_half + c_half*erff(SQRT1_2*d2);
    #endif
            float expRT = expf(-c_riskfree * T);
    
            CallResult[option] = S * CNDD1 - X * expRT * CNDD2;
            PutResult[option] = CallResult[option]  +  expRT - S;
        }
    #pragma omp for version: (black_scholes.cpp, black_scholes_openmp())
    #pragma omp parallel for
        for(int option = 0; option<OPT_N; ++option) {
            float T = OptionYears[option];
            float X = OptionStrike[option];
            float S = StockPrice[option];
            float sqrtT = sqrtf(T);
            float d1 = (logf(S / X) + (c_riskfree + c_half * c_volatility * c_volatility) * T) /
                       (c_volatility * sqrtT);
            float d2 = d1 - c_volatility * sqrtT;
    #ifdef _WIN32
            float CNDD1 = CND(d1);
            float CNDD2 = CND(d2);
    #else			
            float CNDD1 = c_half + c_half*erff(SQRT1_2*d1);
            float CNDD2 = c_half + c_half*erff(SQRT1_2*d2);
    #endif
            float expRT = expf(-c_riskfree * T);
    
            CallResult[option] = S * CNDD1 - X * expRT * CNDD2;
            PutResult[option] = CallResult[option]  +  expRT - S;
        }

Performance Data:

Note: Modified Speedup shows performance speedup with respect to serial implementation.

Modified Speedup Compiler (Intel® 64) Compiler options System specifications
omp for: 2.2x Intel C++ Compiler 18.0 for Windows /O3 /Oi /fp:fast /QxHost /Qipo /Qopenmp Microsoft Windows 10* (x64)
6th generation Intel® Core™ i5-6300U CPU  @ 2.50GHz
8GB memory
omp for: 3.7x Intel C++ Compiler 18.0 for Linux -O3 -fp-model fast -xHost -ipo -qopenmp RHEL 7 (x64)
4rd Generation Intel Core™ i7-4790 CPU @ 3.60GHz
32GB memory

Build Instructions:

  • For Microsoft Visual Studio* users:
  • Open the solution .sln file
    [Optional] To collect performance numbers (will run example 5 times and take average time):
    • Project Properties -> C/C++ -> Preprocessor -> Preprocessor Definitions: add PERF_NUM
    Choose a configuration (for best performance, choose a release configuration):
    • Intel-debug and Intel-release: uses Intel® C++ compiler
    • VSC-debug and VSC-release: uses Visual C++ compiler (only linear/scalar will run)
  • For Windows* Command Line users:
  • Enable your particular compiler environment
    for Intel® C++ Compiler:
    • Open the appropriate Intel C++ compiler command prompt
    • Navigate to project folder
    • Compile with Build.bat [perf_num]
      • perf_num: collect performance numbers (will run example 5 times and take average time)
    • To run: Build.bat run [help|0|1|2|3|4]
    For Visual C++ Compiler (only linear/scalar will run):
    • Open the appropriate MicrosoftVisual Studio* 2010 or 2012 command prompt
    • Navigate to project folder
    • To compile: Build.bat [perf_num]
      • perf_num: collect performance numbers (will run example 5 times and take average time)
    • To run: Build.bat run
  • For Linux* or OS X* users:
  • From a terminal window, navigate to the project folder
    Using Intel C++ compiler:
    • Set the icc environment: source <icc-install-dir>/bin/compilervars.sh {ia32|intel64}
    • To compile: make [icpc] [perf_num=1]
      • perf_num=1: collect performance numbers (will run example 5 times and take average time)
    • To run: make run [option=help|0|1|2|3|4]
    Using gcc (only linear/scalar will run):
    • To compile: make gcc [perf_num=1]
      • perf_num=1: collect performance numbers (will run example 5 times and take average time)
    • To run: make run
For more complete information about compiler optimizations, see our Optimization Notice.