diff --git a/option/blackscholes/blackscholes.js b/option/blackscholes/blackscholes.js new file mode 100644 index 0000000..298bbf4 --- /dev/null +++ b/option/blackscholes/blackscholes.js @@ -0,0 +1,50 @@ +!function() +{ + var blackscholes = {}; + + blackscholes.normal = new normal(0.0 /*mean*/, 1.0 /*sigma*/); + + blackscholes.d1 = function(strike, tau, spot, vol, r) + { + var moneyness = spot/strike; + return (Math.log(moneyness) + (r + 0.5*vol*vol)*tau)/(vol*Math.sqrt(tau)); + } /*d1*/ + + blackscholes.d2 = function(d1, tau, vol) + { + return d1 - vol * Math.sqrt(tau); + } /*d2*/ + + blackscholes.call_px1 = function(strike, tau, spot, r, d1, d2) + { + return blackscholes.normal.cdf(d1)*spot + - blackscholes.normal.cdf(d2)*strike*Math.exp(-r*tau) + } /*call_px1*/ + + blackscholes.call_px = function(strike, tau, spot, vol, r) + { + var d1 = blackscholes.d1(strike, tau, spot, vol, r); + var d2 = blackscholes.d2(d1, tau, vol); + + return blackscholes.call_px1(strike, tau, spot, r, d1, d2); + } /*call_px*/ + + blackscholes.call_delta = function(strike, tau, spot, vol, r) + { + var d1 = blackscholes.d1(strike, tau, spot, vol, r); + + return blackscholes.normal.cdf(d1); + } /*call_delta*/ + + blackscholes.gamma = function(strike, tau, spot, vol, r) + { + var d1 = blackscholes.d1(strike, tau, spot, vol, r); + + return blackscholes.normal.pdf(d1) / (spot * vol * Math.sqrt(tau)); + } /*gamma*/ + + /* providing call_gamma() for consistency with call_px(), call_delta() */ + blackscholes.call_gamma = blackscholes.gamma; + + this.blackscholes = blackscholes; +}(); diff --git a/option/blackscholes/drag6.css b/option/blackscholes/drag6.css new file mode 100644 index 0000000..24e7b76 --- /dev/null +++ b/option/blackscholes/drag6.css @@ -0,0 +1,10 @@ +.axis path, +.axis line { + fill: none; + stroke: black; +} + +.axis text { + font-family: sans-serif; + font-size: 11px; +} \ No newline at end of file diff --git a/option/blackscholes/fx.js b/option/blackscholes/fx.js new file mode 120000 index 0000000..2c53b76 --- /dev/null +++ b/option/blackscholes/fx.js @@ -0,0 +1 @@ +../../d3/drag7/fx.js \ No newline at end of file diff --git a/option/blackscholes/fx_view.js b/option/blackscholes/fx_view.js new file mode 120000 index 0000000..aebc741 --- /dev/null +++ b/option/blackscholes/fx_view.js @@ -0,0 +1 @@ +../../d3/drag7/fx_view.js \ No newline at end of file diff --git a/option/blackscholes/index-src.org b/option/blackscholes/index-src.org new file mode 100644 index 0000000..c288587 --- /dev/null +++ b/option/blackscholes/index-src.org @@ -0,0 +1,19 @@ +#+title: option/blackscholes .org source +# org-publish options +# H:2 controls section numbering. +# number top-level and second-level headings only +# ^:{} require a_{b} before assuming that b should be subscripted. +# without this option a_b will automatically subscript b. +#+options: ^:{} +# +# options used exclusively by emacs +#+startup: showall +# +# options used exclusively by the html exporter +#+language: en +#+infojs_opt: view: showall +#+html_head: +#+html_link_home: ../../index.html +#+html_link_up: index.html + +#+include: "index.org" example diff --git a/option/blackscholes/index.org b/option/blackscholes/index.org new file mode 100644 index 0000000..e39b3ac --- /dev/null +++ b/option/blackscholes/index.org @@ -0,0 +1,85 @@ +#+title: black-scholes example +# +# org-publish options +# H:2 controls section numbering. +# number top-level and second-level headings only +# ^:{} require a_{b} before assuming that b should be subscripted. +# without this option a_b will automatically subscript b. +#+options: ^:{} +# +# options used exclusively by emacs +#+startup: showall +# +# options used exclusively by the html exporter +#+language: en +#+infojs_opt: view:showall toc:nil ltoc:nil mouse:#ffc0c0 path:/ext/org/org-info.js +#+html_mathjax: align:left indent:5em path:/ext/mathjax/MathJax.js +#+html_head: +#+html_head: +#+html_head: +#+html_head: +#+html_head: +#+html_head: +#+html_head: +#+html_head: +#+html_head: +#+html_head: +#+html_link_home: ../../index.html +#+html_link_up: ../../index.html + +* Introduction + This is intended to be an interactive Black-Scholes option-pricing demonstration. + *Warning: Work in progress* + + - ~.org~ source for this page is here: [[file:index-src.org][index.org]] + +** Option pricing + The Black-Scholes formula for European call options is: + $$ C(s,t) = N(d_{1})S = N(d_{2})Ke^{-r\tau} $$ + where $N(x)$ is the cumulative normal distribution function: + $$ N(x) = \frac{1}{\sqrt{2\pi}}\int_{-\infty}^{x}{e^{-\frac{x^2}{2}} dx} $$ + We also have $N'(x)$ is the normal probability density function: + $$ N'(x) = \frac{1}{\sqrt{2\pi}}e^{-\frac{x^2}{2}} $$ + $$ d_{1} = \frac{1}{\sigma\sqrt{\tau}} + \left[\ln{\left(\frac{S}{K}\right)}+\left(r+\frac{\sigma^2}{2}\right)\tau\right] $$ + and + $$ d_{2} = d_{1} - \sigma\sqrt{\tau} $$ + + We also have greeks: + $$ delta: \frac{\partial C}{\partial S} = N(d_{1}) $$ + $$ gamma: \frac{N'(d1)}{S\sigma\sqrt{\tau}} $$ +* Prerequisites + As for [[file:~/proj/org-howto/d3/drag1/index.org#Prerequisites][d3 example /#1/]] + +* Procedure + +** Cumulative normal distribution + We use the ubiquitous polynomial approximation. + Write ~normal.js~ + +#+include: normal.js example + +** Black-Scholes call + Write ~blackscholes.js~ + +#+include: blackscholes.js example + +** Insert html fragment to invoke our interactive javascript code + This also follows the same model we used in examples [[file:~/proj/org-howto/d3/drag3/index.org][/#3/]], [[file:~/proj/org-howto/d3/drag4/index.org][/#4/]], [[file:~/proj/org-howto/d3/drag5/index.org][/#5/]]. + #+begin_example + ,#+begin_html +
+ + #+end_html + #+end_example + The div element ~#frame~ will appear below this line: + #+begin_html + + + #+end_html + + diff --git a/option/blackscholes/normal.js b/option/blackscholes/normal.js new file mode 100644 index 0000000..f0913f0 --- /dev/null +++ b/option/blackscholes/normal.js @@ -0,0 +1,35 @@ +!function() +{ + /* e.g. N = normal(0,1) + * N.cdf(0.0) -> 0.5 + */ + function normal(mean, sigma) + { + this.mean = mean; + this.sigma = sigma; + this.sigma_2 = sigma*sigma; + this.cdf = function(x) { + var z = (x-mean)/Math.sqrt(2*this.sigma_2); + var t = 1/(1+0.3275911*Math.abs(z)); + var a1 = 0.254829592; + var a2 = -0.284496736; + var a3 = 1.421413741; + var a4 = -1.453152027; + var a5 = 1.061405429; + var erf = 1-(((((a5*t + a4)*t) + a3)*t + a2)*t + a1)*t*Math.exp(-z*z); + var sign = 1; + if(z < 0) + { + sign = -1; + } + return (1/2)*(1+sign*erf); + } /*cdf*/ + this.pdf = function(x) { + var z = (x-mean)/Math.sqrt(2*this.sigma_2); + + return (1.0/Math.sqrt(2*Math.PI)) * Math.exp(-0.5*z*z); + } /*pdf*/ + } /*normal*/ + + this.normal = normal; +}(); diff --git a/option/blackscholes/parametric-drag-example.js b/option/blackscholes/parametric-drag-example.js new file mode 100644 index 0000000..5ea4105 --- /dev/null +++ b/option/blackscholes/parametric-drag-example.js @@ -0,0 +1,55 @@ +!function() { + var ex = {}; + + /* Requires: + * - point.js + * - fx.js + * - fx_view.js + */ + + ex.box_pt = {x: 700, y: 450}; + + ex.strike = 1.0; + ex.tau = 1.0; + ex.vol = 0.55; + ex.r = 0.02; + + /* target function f(x) + * x :: number + * returns :: number + */ + ex.target_fn = function(x) { + return blackscholes.call_px(ex.strike, ex.tau, x, ex.vol, ex.r); + } /*target_fn*/ + + /* derivative f'(x) of fx.target_fn + * x :: number + * returns :: number + */ + ex.target_deriv_fn = function(x) { + return blackscholes.call_delta(ex.strike, ex.tau, x, ex.vol, ex.r); + } /*target_deriv_fn*/ + + /* 2nd derivative f''(x) of fx.target_fn + * x :: number + * returns :: number + */ + ex.target_deriv2_fn = function(x) { + return blackscholes.call_gamma(ex.strike, ex.tau, x, ex.vol, ex.r); + } /*target_deriv2_fn*/ + + /* w :: Window */ + ex.start = function(w) + { + fx_view.init_sequence(ex.target_fn, + ex.target_deriv_fn, + ex.target_deriv2_fn, + ex.box_pt, 200.0 /*scale_factor*/, + +0.01 /*lo_x*/, +2.0 /*hi_x*/, + 0.0 /*lo_y*/, 1.0 /*hi_y*/, + 200 /*n_pt*/); + fx_view.draw("#frame"); + } + + this.ex = ex; +}(); diff --git a/option/blackscholes/point.js b/option/blackscholes/point.js new file mode 120000 index 0000000..7df8356 --- /dev/null +++ b/option/blackscholes/point.js @@ -0,0 +1 @@ +../../d3/drag7/point.js \ No newline at end of file diff --git a/option/blackscholes/xyscale.js b/option/blackscholes/xyscale.js new file mode 120000 index 0000000..0a7222c --- /dev/null +++ b/option/blackscholes/xyscale.js @@ -0,0 +1 @@ +../../d3/drag7/xyscale.js \ No newline at end of file