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 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
|
/*
**************************************************************
* C++ Mathematical Expression Toolkit Library *
* *
* Simple Example 22 *
* Author: Arash Partow (1999-2024) *
* URL: https://www.partow.net/programming/exprtk/index.html *
* *
* Copyright notice: *
* Free use of the Mathematical Expression Toolkit Library is *
* permitted under the guidelines and in accordance with the *
* most current version of the MIT License. *
* https://www.opensource.org/licenses/MIT *
* SPDX-License-Identifier: MIT *
* *
**************************************************************
*/
#include <cstdio>
#include <string>
#include "exprtk.hpp"
template <typename T>
void compute_implied_volatility()
{
typedef exprtk::symbol_table<T> symbol_table_t;
typedef exprtk::expression<T> expression_t;
typedef exprtk::parser<T> parser_t;
typedef exprtk::function_compositor<T> compositor_t;
typedef typename compositor_t::function function_t;
const std::string implied_volatility_program =
" const var epsilon := 0.0000001; "
" const var max_iters := 1000; "
" "
" var v := 0.5; /* Initial volatility guess */ "
" var itr := 0; "
" "
" while ((itr += 1) <= max_iters) "
" { "
" var price := "
" switch "
" { "
" case callput_flag == 'call' : bsm_call(s, k, r, t, v); "
" case callput_flag == 'put' : bsm_put (s, k, r, t, v); "
" }; "
" "
" var price_diff := price - target_price; "
" "
" if (abs(price_diff) <= epsilon) "
" { "
" break; "
" }; "
" "
" v -= price_diff / vega(s, k, r, t, v); "
" }; "
" "
" itr <= max_iters ? v : null; ";
T s = T( 100.00); // Spot / Stock / Underlying / Base price
T k = T( 110.00); // Strike price
T t = T( 2.22); // Years to maturity
T r = T( 0.05); // Risk free rate
T target_price = T( 0.00);
std::string callput_flag;
symbol_table_t symbol_table(symbol_table_t::e_immutable);
symbol_table.add_variable("s",s);
symbol_table.add_variable("k",k);
symbol_table.add_variable("t",t);
symbol_table.add_variable("r",r);
symbol_table.add_stringvar("callput_flag",callput_flag);
symbol_table.add_variable ("target_price",target_price);
symbol_table.add_pi();
compositor_t compositor(symbol_table);
compositor.add(
function_t("bsm_call")
.vars("s", "k", "r", "t", "v")
.expression
(
" var d1 := (log(s / k) + (r + v^2 / 2) * t) / (v * sqrt(t)); "
" var d2 := d1 - v * sqrt(t); "
" s * ncdf(d1) - k * exp(-r * t) * ncdf(d2); "
));
compositor.add(
function_t("bsm_put")
.vars("s", "k", "r", "t", "v")
.expression
(
" var d1 := (log(s / k) + (r + v^2 / 2) * t) / (v * sqrt(t)); "
" var d2 := d1 - v * sqrt(t); "
" k * exp(-r * t) * ncdf(-d2) - s * ncdf(-d1); "
));
compositor.add(
function_t("vega")
.vars("s", "k", "r", "t", "v")
.expression
(
" var d1 := (log(s / k) + (r + v^2 / 2) * t) / (v * sqrt(t)); "
" s * sqrt(t) * exp(-d1^2 / 2) / sqrt(2pi); "
));
expression_t expression;
expression.register_symbol_table(symbol_table);
parser_t parser;
parser.compile(implied_volatility_program,expression);
{
callput_flag = "call";
target_price = T(18.339502);
const T implied_vol = expression.value();
printf("Call Option(s: %5.3f, k: %5.3f, t: %5.3f, r: %5.3f) "
"@ $%8.6f Implied volatility = %10.8f\n",
s, k, t, r, target_price, implied_vol);
}
{
callput_flag = "put";
target_price = T(16.782764);
const T implied_vol = expression.value();
printf("Put Option(s: %5.3f, k: %5.3f, t: %5.3f, r: %5.3f) "
"@ $%8.6f Implied volatility = %10.8f\n",
s, k, t, r, target_price, implied_vol);
}
}
int main()
{
compute_implied_volatility<double>();
return 0;
}
|