C++ Mathematical Expression Toolkit (ExprTk) release
Loading...
Searching...
No Matches
exprtk_bsm_benchmark.cpp
Go to the documentation of this file.
1/*
2 **************************************************************
3 * C++ Mathematical Expression Toolkit Library *
4 * *
5 * ExprTk Black Scholes Merton Benchmark *
6 * Author: Arash Partow (1999-2024) *
7 * URL: https://www.partow.net/programming/exprtk/index.html *
8 * *
9 * Copyright notice: *
10 * Free use of the Mathematical Expression Toolkit Library is *
11 * permitted under the guidelines and in accordance with the *
12 * most current version of the MIT License. *
13 * https://www.opensource.org/licenses/MIT *
14 * SPDX-License-Identifier: MIT *
15 * *
16 **************************************************************
17*/
18
19
20#include <cstdio>
21#include <string>
22
23#include "exprtk.hpp"
24
25
26static const std::size_t rounds = 20000000;
27
28template <typename T>
30{
31 T s; // Spot / Stock / Underlying / Base price
32 T k; // Strike price
33 T v; // Volatility
34 T t; // Years to maturity
35 T r; // Risk free rate
36};
37
39 {
40 { 60.11, 65.11, 0.31, 0.25, 0.08 },
41 { 60.22, 65.22, 0.32, 0.35, 0.07 },
42 { 60.33, 65.33, 0.33, 0.45, 0.06 },
43 { 60.44, 65.44, 0.34, 0.55, 0.05 },
44 { 60.55, 65.55, 0.35, 0.65, 0.04 },
45 { 60.66, 65.66, 0.36, 0.75, 0.03 },
46 { 60.77, 65.77, 0.37, 0.85, 0.08 },
47 { 60.88, 65.88, 0.38, 0.95, 0.07 },
48 { 60.11, 65.11, 0.31, 0.25, 0.06 },
49 { 60.22, 65.22, 0.32, 0.35, 0.05 },
50 { 60.33, 65.33, 0.33, 0.45, 0.04 },
51 { 60.44, 65.44, 0.34, 0.55, 0.03 },
52 { 60.55, 65.55, 0.35, 0.65, 0.08 },
53 { 60.66, 65.66, 0.36, 0.75, 0.07 },
54 { 60.77, 65.77, 0.37, 0.85, 0.06 },
55 { 60.88, 65.88, 0.38, 0.95, 0.05 }
56 };
57
58const std::size_t bsm_list_size = sizeof (bsm_list) / sizeof(bsm_parameters<double>);
59
60template <typename T>
61inline T call_bsm_model(T s, T k, T t, T r, T v)
62{
63 using namespace std;
64 using namespace exprtk::details::numeric;
65
66 const T d1 = (log(s / k) + (r + (v * v) / 2) * t) / (v * sqrt(t));
67 const T d2 = d1 - v * sqrt(t);
68 return s * ncdf(d1) - k * exp(-r * t) * ncdf(d2);
69}
70
71template <typename T>
72inline T put_bsm_model(T s, T k, T t, T r, T v)
73{
74 using namespace std;
75 using namespace exprtk::details::numeric;
76
77 const T d1 = (log(s / k) + (r + (v * v) / 2) * t) / (v * sqrt(t));
78 const T d2 = d1 - v * sqrt(t);
79 return k * exp(-r * t) * ncdf(-d2) - s * ncdf(-d1);
80}
81
82template <typename T>
84{
85 typedef exprtk::symbol_table<T> symbol_table_t;
86 typedef exprtk::expression<T> expression_t;
87 typedef exprtk::parser<T> parser_t;
88
89 const std::string bsm_model_program =
90 " var d1 := (log(s / k) + (r + v^2 / 2) * t) / (v * sqrt(t)); "
91 " var d2 := d1 - v * sqrt(t); "
92 " "
93 " if (callput_flag == 'call') "
94 " s * ncdf(d1) - k * e^(-r * t) * ncdf(d2); "
95 " else if (callput_flag == 'put') "
96 " k * e^(-r * t) * ncdf(-d2) - s * ncdf(-d1); "
97 " ";
98
99 const std::string bsm_model_program_opt1 =
100 " var v_sqrtt := (v * sqrt(t)); "
101 " var d1 := (log(s / k) + (r + v * v / 2) * t) / v_sqrtt; "
102 " var d2 := d1 - v_sqrtt; "
103 " var kert := k * exp(-r * t); "
104 " "
105 " if (callput_flag == 'call') "
106 " s * ncdf(d1) - kert * ncdf(d2); "
107 " else if (callput_flag == 'put') "
108 " kert * ncdf(-d2) - s * ncdf(-d1); "
109 " ";
110
111 const std::string bsm_model_program_opt2 =
112 " var v_sqrtt := (v * sqrt(t)); "
113 " var d1 := (log(s / k) + (r + v * v / 2) * t) / v_sqrtt; "
114 " var d2 := d1 - v_sqrtt; "
115 " "
116 " if (callput_flag == 'call') "
117 " s * ncdf(d1) - (k * exp(-r * t)) * ncdf(d2); "
118 " else if (callput_flag == 'put') "
119 " (k * exp(-r * t)) * ncdf(-d2) - s * ncdf(-d1); "
120 " ";
121
122 const std::string bsm_model_program_opt3 =
123 " if (callput_flag == 'call') "
124 " call_bsm_model(s, k, t, r, v); "
125 " else if (callput_flag == 'put') "
126 " put_bsm_model(s, k, t, r, v); "
127 " ";
128
129 bsm_parameters<T> parameters;
130
131 std::string callput_flag;
132
133 static const T e = exprtk::details::numeric::constant::e;
134
135 symbol_table_t symbol_table;
136 symbol_table.add_variable ( "s", parameters.s );
137 symbol_table.add_variable ( "k", parameters.k );
138 symbol_table.add_variable ( "t", parameters.t );
139 symbol_table.add_variable ( "r", parameters.r );
140 symbol_table.add_variable ( "v", parameters.v );
141 symbol_table.add_constant ( "e", e );
142 symbol_table.add_stringvar( "callput_flag" , callput_flag );
143 symbol_table.add_function ( "call_bsm_model", call_bsm_model );
144 symbol_table.add_function ( "put_bsm_model" , put_bsm_model );
145
146 expression_t bsm_expression (symbol_table);
147 expression_t bsm_expression_opt1(symbol_table);
148 expression_t bsm_expression_opt2(symbol_table);
149 expression_t bsm_expression_opt3(symbol_table);
150
151 parser_t parser;
152
153 parser.compile(bsm_model_program , bsm_expression );
154 parser.compile(bsm_model_program_opt1, bsm_expression_opt1);
155 parser.compile(bsm_model_program_opt2, bsm_expression_opt2);
156 parser.compile(bsm_model_program_opt3, bsm_expression_opt3);
157
158 {
160 timer.start();
161
162 T total = T(0);
163
164 for (std::size_t i = 0; i < rounds; ++i)
165 {
166 const bsm_parameters<T>& current_parameters = bsm_list[i % bsm_list_size];
167
168 parameters = current_parameters;
169
170 callput_flag = "call";
171 total += bsm_expression.value();
172
173 callput_flag = "put";
174 total += bsm_expression.value();
175 }
176
177 timer.stop();
178
179 printf("[exprtk0] Total: %13.5f Time:%6.3fsec Rate:%13.3fbsm/sec execrt: %6.3fns\n",
180 total,
181 timer.time(),
182 (2.0 * rounds) / timer.time(),
183 1e9 / ((2.0 * rounds) / timer.time()));
184 }
185
186 {
188 timer.start();
189
190 T total = T(0);
191
192 for (std::size_t i = 0; i < rounds; ++i)
193 {
194 const bsm_parameters<T>& current_parameters = bsm_list[i % bsm_list_size];
195
196 parameters = current_parameters;
197
198 callput_flag = "call";
199 total += bsm_expression_opt1.value();
200
201 callput_flag = "put";
202 total += bsm_expression_opt1.value();
203 }
204
205 timer.stop();
206
207 printf("[exprtk1] Total: %13.5f Time:%6.3fsec Rate:%13.3fbsm/sec execrt: %6.3fns\n",
208 total,
209 timer.time(),
210 (2.0 * rounds) / timer.time(),
211 1e9 / ((2.0 * rounds) / timer.time()));
212 }
213
214 {
216 timer.start();
217
218 T total = T(0);
219
220 for (std::size_t i = 0; i < rounds; ++i)
221 {
222 const bsm_parameters<T>& current_parameters = bsm_list[i % bsm_list_size];
223
224 parameters = current_parameters;
225
226 callput_flag = "call";
227 total += bsm_expression_opt2.value();
228
229 callput_flag = "put";
230 total += bsm_expression_opt2.value();
231 }
232
233 timer.stop();
234
235 printf("[exprtk2] Total: %13.5f Time:%6.3fsec Rate:%13.3fbsm/sec execrt: %6.3fns\n",
236 total,
237 timer.time(),
238 (2.0 * rounds) / timer.time(),
239 1e9 / ((2.0 * rounds) / timer.time()));
240 }
241
242 {
244 timer.start();
245
246 T total = T(0);
247
248 for (std::size_t i = 0; i < rounds; ++i)
249 {
250 const bsm_parameters<T>& current_parameters = bsm_list[i % bsm_list_size];
251
252 parameters = current_parameters;
253
254 callput_flag = "call";
255 total += bsm_expression_opt3.value();
256
257 callput_flag = "put";
258 total += bsm_expression_opt3.value();
259 }
260
261 timer.stop();
262
263 printf("[exprtk3] Total: %13.5f Time:%6.3fsec Rate:%13.3fbsm/sec execrt: %6.3fns\n",
264 total,
265 timer.time(),
266 (2.0 * rounds) / timer.time(),
267 1e9 / ((2.0 * rounds) / timer.time()));
268 }
269}
270
271template <typename T>
272inline T bsm_model(const std::string& callput_flag, const T s, const T k, const T t, const T r, const T v)
273{
274 using namespace std;
275 using namespace exprtk::details::numeric;
276
277 const T d1 = (log(s / k) + (r + (v * v) / 2) * t) / (v * sqrt(t));
278 const T d2 = d1 - v * sqrt(t);
279
280 if (callput_flag == "call")
281 return s * ncdf(d1) - k * exp(-r * t) * ncdf(d2);
282 else if (callput_flag == "put")
283 return k * exp(-r * t) * ncdf(-d2) - s * ncdf(-d1);
284 else
285 return T(0);
286}
287
288template <typename T>
290{
291 bsm_parameters<T> parameters;
292
293 std::string callput_flag;
294
296 timer.start();
297
298 T total = T(0);
299
300 for (std::size_t i = 0; i < rounds; ++i)
301 {
302 const bsm_parameters<T>& current_parameters = bsm_list[i % bsm_list_size];
303
304 parameters = current_parameters;
305
306 callput_flag = "call";
307 total += bsm_model(callput_flag, parameters.s, parameters.k, parameters.t, parameters.r, parameters.v);
308
309 callput_flag = "put";
310 total += bsm_model(callput_flag, parameters.s, parameters.k, parameters.t, parameters.r, parameters.v);
311 }
312
313 timer.stop();
314
315 printf("[native ] Total: %13.5f Time:%6.3fsec Rate:%13.3fbsm/sec execrt: %6.3fns\n",
316 total,
317 timer.time(),
318 (2.0 * rounds) / timer.time(),
319 1e9 / ((2.0 * rounds) / timer.time()));
320}
321
322int main()
323{
324 black_scholes_merton_model<double>();
325 bsm_native<double>();
326 return 0;
327}
328
329/*
330 Build command:
331 c++ -pedantic-errors -Wall -Wextra -Werror -flto -march=native -O3 -DNDEBUG -o exprtk_bsm_benchmark exprtk_bsm_benchmark.cpp -L/usr/lib -lstdc++ -lm
332*/
bool compile(const std::string &expression_string, expression< T > &expr)
Definition exprtk.hpp:24742
bool add_constant(const std::string &constant_name, const T &value)
Definition exprtk.hpp:21047
bool add_function(const std::string &function_name, function_t &function)
Definition exprtk.hpp:21076
bool add_variable(const std::string &variable_name, T &t, const bool is_constant=false)
Definition exprtk.hpp:21035
bool add_stringvar(const std::string &stringvar_name, std::string &s, const bool is_constant=false)
Definition exprtk.hpp:21063
double time() const
Definition exprtk.hpp:43995
T put_bsm_model(T s, T k, T t, T r, T v)
void bsm_native()
static const std::size_t rounds
T bsm_model(const std::string &callput_flag, const T s, const T k, const T t, const T r, const T v)
const std::size_t bsm_list_size
void black_scholes_merton_model()
T call_bsm_model(T s, T k, T t, T r, T v)
const bsm_parameters< double > bsm_list[]