autodiff_black_scholes_brief.cpp 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. // Copyright Matthew Pulver 2018 - 2019.
  2. // Distributed under the Boost Software License, Version 1.0.
  3. // (See accompanying file LICENSE_1_0.txt or copy at
  4. // https://www.boost.org/LICENSE_1_0.txt)
  5. #include <boost/math/differentiation/autodiff.hpp>
  6. #include <iostream>
  7. #include <stdexcept>
  8. using namespace boost::math::constants;
  9. using namespace boost::math::differentiation;
  10. // Equations and function/variable names are from
  11. // https://en.wikipedia.org/wiki/Greeks_(finance)#Formulas_for_European_option_Greeks
  12. // Standard normal cumulative distribution function
  13. template <typename X>
  14. X Phi(X const& x) {
  15. return 0.5 * erfc(-one_div_root_two<X>() * x);
  16. }
  17. enum class CP { call, put };
  18. // Assume zero annual dividend yield (q=0).
  19. template <typename Price, typename Sigma, typename Tau, typename Rate>
  20. promote<Price, Sigma, Tau, Rate> black_scholes_option_price(CP cp,
  21. double K,
  22. Price const& S,
  23. Sigma const& sigma,
  24. Tau const& tau,
  25. Rate const& r) {
  26. using namespace std;
  27. auto const d1 = (log(S / K) + (r + sigma * sigma / 2) * tau) / (sigma * sqrt(tau));
  28. auto const d2 = (log(S / K) + (r - sigma * sigma / 2) * tau) / (sigma * sqrt(tau));
  29. switch (cp) {
  30. case CP::call:
  31. return S * Phi(d1) - exp(-r * tau) * K * Phi(d2);
  32. case CP::put:
  33. return exp(-r * tau) * K * Phi(-d2) - S * Phi(-d1);
  34. default:
  35. throw std::runtime_error("Invalid CP value.");
  36. }
  37. }
  38. int main() {
  39. double const K = 100.0; // Strike price.
  40. auto const S = make_fvar<double, 2>(105); // Stock price.
  41. double const sigma = 5; // Volatility.
  42. double const tau = 30.0 / 365; // Time to expiration in years. (30 days).
  43. double const r = 1.25 / 100; // Interest rate.
  44. auto const call_price = black_scholes_option_price(CP::call, K, S, sigma, tau, r);
  45. auto const put_price = black_scholes_option_price(CP::put, K, S, sigma, tau, r);
  46. std::cout << "black-scholes call price = " << call_price.derivative(0) << '\n'
  47. << "black-scholes put price = " << put_price.derivative(0) << '\n'
  48. << "call delta = " << call_price.derivative(1) << '\n'
  49. << "put delta = " << put_price.derivative(1) << '\n'
  50. << "call gamma = " << call_price.derivative(2) << '\n'
  51. << "put gamma = " << put_price.derivative(2) << '\n';
  52. return 0;
  53. }
  54. /*
  55. Output:
  56. black-scholes call price = 56.5136
  57. black-scholes put price = 51.4109
  58. call delta = 0.773818
  59. put delta = -0.226182
  60. call gamma = 0.00199852
  61. put gamma = 0.00199852
  62. **/