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; // 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.25, 0.08 },
42 { 60.33, 65.33, 0.33, 0.25, 0.08 },
43 { 60.44, 65.44, 0.34, 0.25, 0.08 },
44 { 60.55, 65.55, 0.35, 0.25, 0.08 },
45 { 60.66, 65.66, 0.36, 0.25, 0.08 },
46 { 60.77, 65.77, 0.37, 0.25, 0.08 },
47 { 60.88, 65.88, 0.38, 0.25, 0.08 },
48 { 60.11, 65.11, 0.31, 0.25, 0.08 },
49 { 60.22, 65.22, 0.32, 0.25, 0.08 },
50 { 60.33, 65.33, 0.33, 0.25, 0.08 },
51 { 60.44, 65.44, 0.34, 0.25, 0.08 },
52 { 60.55, 65.55, 0.35, 0.25, 0.08 },
53 { 60.66, 65.66, 0.36, 0.25, 0.08 },
54 { 60.77, 65.77, 0.37, 0.25, 0.08 },
55 { 60.88, 65.88, 0.38, 0.25, 0.08 }
56 };
57
58const std::size_t bsm_list_size = sizeof (bsm_list) / sizeof(bsm_parameters<double>);
59
60template <typename T>
62{
63 typedef exprtk::symbol_table<T> symbol_table_t;
64 typedef exprtk::expression<T> expression_t;
65 typedef exprtk::parser<T> parser_t;
66
67 const std::string bsm_model_program =
68 " var d1 := (log(s / k) + (r + v^2 / 2) * t) / (v * sqrt(t)); "
69 " var d2 := d1 - v * sqrt(t); "
70 " "
71 " if (callput_flag == 'call') "
72 " s * ncdf(d1) - k * e^(-r * t) * ncdf(d2); "
73 " else if (callput_flag == 'put') "
74 " k * e^(-r * t) * ncdf(-d2) - s * ncdf(-d1); "
75 " ";
76
77 const std::string bsm_model_program_opt1 =
78 " var v_sqrtt := (v * sqrt(t)); "
79 " var d1 := (log(s / k) + (r + v * v / 2) * t) / v_sqrtt; "
80 " var d2 := d1 - v_sqrtt; "
81 " var kert := k * exp(-r * t); "
82 " "
83 " if (callput_flag == 'call') "
84 " s * ncdf(d1) - kert * ncdf(d2); "
85 " else if (callput_flag == 'put') "
86 " kert * ncdf(-d2) - s * ncdf(-d1); "
87 " ";
88
89 const std::string bsm_model_program_opt2 =
90 " var v_sqrtt := (v * sqrt(t)); "
91 " var d1 := (log(s / k) + (r + v * v / 2) * t) / v_sqrtt; "
92 " var d2 := d1 - v_sqrtt; "
93 " "
94 " if (callput_flag == 'call') "
95 " s * ncdf(d1) - (k * exp(-r * t)) * ncdf(d2); "
96 " else if (callput_flag == 'put') "
97 " (k * exp(-r * t)) * ncdf(-d2) - s * ncdf(-d1); "
98 " ";
99
100 T s = T(0);
101 T k = T(0);
102 T t = T(0);
103 T r = T(0);
104 T v = T(0);
105
106 std::string callput_flag;
107
108 static const T e = exprtk::details::numeric::constant::e;
109
110 symbol_table_t symbol_table;
111 symbol_table.add_variable("s",s);
112 symbol_table.add_variable("k",k);
113 symbol_table.add_variable("t",t);
114 symbol_table.add_variable("r",r);
115 symbol_table.add_variable("v",v);
116 symbol_table.add_constant("e",e);
117 symbol_table.add_stringvar("callput_flag",callput_flag);
118
119 expression_t bsm_expression (symbol_table);
120 expression_t bsm_expression_opt1(symbol_table);
121 expression_t bsm_expression_opt2(symbol_table);
122
123 parser_t parser;
124
125 parser.compile(bsm_model_program , bsm_expression );
126 parser.compile(bsm_model_program_opt1, bsm_expression_opt1);
127 parser.compile(bsm_model_program_opt2, bsm_expression_opt2);
128
129 {
130 exprtk::timer timer;
131 timer.start();
132
133 T total = T(0);
134
135 for (std::size_t i = 0; i < rounds; ++i)
136 {
137 const bsm_parameters<T>& params = bsm_list[i % bsm_list_size];
138
139 s = params.s;
140 k = params.k;
141 t = params.t;
142 r = params.r;
143 v = params.v;
144
145 callput_flag = "call";
146 total += bsm_expression.value();
147
148 callput_flag = "put";
149 total += bsm_expression.value();
150 }
151
152 timer.stop();
153
154 printf("[exprtk0] Total: %16.5f\tTime:%8.3fsec\tRate:%16.3fbsm/sec\n",
155 total,
156 timer.time(),
157 (2.0 * rounds) / timer.time());
158 }
159
160 {
161 exprtk::timer timer;
162 timer.start();
163
164 T total = T(0);
165
166 for (std::size_t i = 0; i < rounds; ++i)
167 {
168 const bsm_parameters<T>& params = bsm_list[i % bsm_list_size];
169
170 s = params.s;
171 k = params.k;
172 t = params.t;
173 r = params.r;
174 v = params.v;
175
176 callput_flag = "call";
177 total += bsm_expression_opt1.value();
178
179 callput_flag = "put";
180 total += bsm_expression_opt1.value();
181 }
182
183 timer.stop();
184
185 printf("[exprtk1] Total: %16.5f\tTime:%8.3fsec\tRate:%16.3fbsm/sec\n",
186 total,
187 timer.time(),
188 (2.0 * rounds) / timer.time());
189 }
190
191 {
192 exprtk::timer timer;
193 timer.start();
194
195 T total = T(0);
196
197 for (std::size_t i = 0; i < rounds; ++i)
198 {
199 const bsm_parameters<T>& params = bsm_list[i % bsm_list_size];
200
201 s = params.s;
202 k = params.k;
203 t = params.t;
204 r = params.r;
205 v = params.v;
206
207 callput_flag = "call";
208 total += bsm_expression_opt2.value();
209
210 callput_flag = "put";
211 total += bsm_expression_opt2.value();
212 }
213
214 timer.stop();
215
216 printf("[exprtk2] Total: %16.5f\tTime:%8.3fsec\tRate:%16.3fbsm/sec\n",
217 total,
218 timer.time(),
219 (2.0 * rounds) / timer.time());
220 }
221}
222
223template <typename T>
224inline T bsm_model(const std::string& callput_flag, const T s, const T k, const T t, const T r, const T v)
225{
226 using namespace std;
227
228 const T d1 = (std::log(s / k) + (r + (v * v) / 2) * t) / (v * sqrt(t));
229 const T d2 = d1 - v * sqrt(t);
230
231 if (callput_flag == "call")
232 return s * exprtk::details::numeric::ncdf(d1) - k * exp(-r * t) * exprtk::details::numeric::ncdf(d2);
233 else if (callput_flag == "put")
234 return k * exp(-r * t) * exprtk::details::numeric::ncdf(-d2) - s * exprtk::details::numeric::ncdf(-d1);
235 else
236 return T(0);
237}
238
239template <typename T>
241{
242 T s = T(0);
243 T k = T(0);
244 T t = T(0);
245 T r = T(0);
246 T v = T(0);
247
248 std::string callput_flag;
249
250 exprtk::timer timer;
251 timer.start();
252
253 T total = T(0);
254
255 for (std::size_t i = 0; i < rounds; ++i)
256 {
257 const bsm_parameters<T>& params = bsm_list[i % bsm_list_size];
258
259 s = params.s;
260 k = params.k;
261 t = params.t;
262 r = params.r;
263 v = params.v;
264
265 callput_flag = "call";
266 total += bsm_model(callput_flag, s, k, t, r, v);
267
268 callput_flag = "put";
269 total += bsm_model(callput_flag, s, k, t, r, v);
270 }
271
272 timer.stop();
273
274 printf("[native ] Total: %16.5f\tTime:%8.3fsec\tRate:%16.3fbsm/sec\n",
275 total,
276 timer.time(),
277 (2.0 * rounds) / timer.time());
278}
279
280int main()
281{
282 black_scholes_merton_model<double>();
283 bsm_native<double>();
284 return 0;
285}
286
287/*
288 Build command:
289 c++ -pedantic-errors -Wall -Wextra -Werror -flto -march=native -O3 -DNDEBUG -o exprtk_bsm_benchmark exprtk_bsm_benchmark.cpp -L/usr/lib -lstdc++ -lm
290*/
double time() const
Definition exprtk.hpp:41912
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()
const bsm_parameters< double > bsm_list[]