add example with black-scholes call pricing

This commit is contained in:
Roland Conybeare 2016-05-01 12:49:39 -04:00
commit 200a6006fb
10 changed files with 258 additions and 0 deletions

View file

@ -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;
}();

View file

@ -0,0 +1,10 @@
.axis path,
.axis line {
fill: none;
stroke: black;
}
.axis text {
font-family: sans-serif;
font-size: 11px;
}

1
option/blackscholes/fx.js Symbolic link
View file

@ -0,0 +1 @@
../../d3/drag7/fx.js

View file

@ -0,0 +1 @@
../../d3/drag7/fx_view.js

View file

@ -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: <link rel="stylesheet" type="text/css" href="../../css/notebook.css" />
#+html_link_home: ../../index.html
#+html_link_up: index.html
#+include: "index.org" example

View file

@ -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: <script type="text/javascript" src="/ext/d3/d3.js"></script>
#+html_head: <script type="text/javascript" src="point.js"></script>
#+html_head: <script type="text/javascript" src="fx.js"></script>
#+html_head: <script type="text/javascript" src="xyscale.js"></script>
#+html_head: <script type="text/javascript" src="fx_view.js"></script>
#+html_head: <script type="text/javascript" src="normal.js"></script>
#+html_head: <script type="text/javascript" src="blackscholes.js"></script>
#+html_head: <script type="text/javascript" src="parametric-drag-example.js"></script>
#+html_head: <link rel="stylesheet" type="text/css" href="../../css/notebook.css" />
#+html_head: <link rel="stylesheet" type="text/css" href="drag6.css" />
#+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
<div id="frame"></div>
<script type="text/javascript">
window.onload = function() { ex.start(this); }
</script>
#+end_html
#+end_example
The div element ~#frame~ will appear below this line:
#+begin_html
<div id="frame"></div>
<script type="text/javascript">
window.onload = function() { ex.start(this); }
</script>
#+end_html

View file

@ -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;
}();

View file

@ -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;
}();

View file

@ -0,0 +1 @@
../../d3/drag7/point.js

View file

@ -0,0 +1 @@
../../d3/drag7/xyscale.js