Black-Scholes

I saw Espen Haug's Black-Scholes page and was inspired to port the formula to a new language or two. The first language I thought of was Lua, a very light weight but powerful and portable language which several people have recommended to me recently and which I am considering using as an embedded scripting language in my work (mainly because I can't seem to convince anyone that we should be using Scheme for this purpose (they just don't like parentheses (hard to believe I know))). So without further ado:

-- "Lua is a powerful light-weight programming language designed for
-- extending applications. Lua is also frequently used as a general-purpose, 
-- stand-alone language. Lua is free software." - from http://www.lua.org
--
-- Black-Scholes option formula put into Lua by Thomas Munro, London, 2007.

-- Cumulative normal distribution.
function cnd(x)
  -- taylor series coefficients
  local a1, a2, a3, a4, a5 = 0.31938153, -0.356563782, 1.781477937,
    -1.821255978, 1.330274429
  local l = math.abs(x)
  local k = 1.0 / (1.0 + 0.2316419 * l)
  local w = 1.0 - 1.0 / math.sqrt(2 * math.pi) * math.exp(-l * l / 2) *
    (a1 * k + a2 * k * k + a3 * math.pow(k, 3) + a4 * math.pow(k, 4) + a5 *
    math.pow(k, 5))
  if x < 0 then w = 1.0 - w end
  return w
end

-- The Black-Scholes option valuation function (1973).
-- is_call: true for call, false for put
-- s: current price
-- x: strike price
-- t: time
-- r: interest rate
-- v: volatility
function black_scholes(is_call, s, x, t, r, v)
  local d1 = (math.log(s / x) + (r + v * v / 2.0) * t) / (v * math.sqrt(t))
  local d2 = d1 - v * math.sqrt(t)
  if is_call then
    return s * cnd(d1) - x * math.exp(-r * t) * cnd(d2)
  else
    return x * math.exp(-r * t) * cnd(-d2) - s * cnd(-d1)
  end
end

So I decided to take Fortress for a spin, since I'd read about it on Lambda the Ultimate and wanted to try out this programming language which borrows conventional maths notation. It looks like a very powerful language which is similar to Haskell. Here is my first attempt:

(*
 * The Black-Scholes formula expressed in the unfinished language Fortress.
 * Thomas Munro, London 2007.
 *
 * From Wikipedia: Fortress "is intended to be a successor to Fortran, with
 * improvements including Unicode support and concrete syntax that is similar
 * to mathematical notation. The language is not designed to be similar to
 * Fortran. Syntactically, it most resembles Scala, Standard ML, and Haskell."
 *)

cnd(x) = do
  a1 = 0.31938153
  a2 = -0.356563782
  a3 = 1.781477937
  a4 = -1.821255978
  a5 = 1.330274429
  l = |x|
  k = 1 / (1 + 0.2316419 l)
  w = 1 - (1 / sqrt(2 pi)) exp(-l DOT l / 2) (k a1 + k^2 a2 + k^3 a3 + k^4 a4 + k^5 a5)
  if x < 0 then 1 - w else w end
end

call(S, x, t, r, sigma) = do
  d1 = (log(S / x) + (r + sigma^2 / 2) t) / (sigma sqrt(t))
  d2 = d1 - sigma sqrt(t)
  S DOT cnd(d1) - x exp(-r t) cnd(d2)
end

put(S, x, t, r, sigma) = do
  d1 = (log(S / x) + (r + sigma^2 / 2) t) / (sigma sqrt(t))
  d2 = d1 - sigma sqrt(t)
  x DOT exp(-r t) cnd(-d2) - S cnd(-d1)
end

This can be typeset using Fortify (an Emacs Lisp program that comes with the reference Fortress implementation, to convert between straight ASCII and Latex), giving the following (although I had to fix a bug in the way it rendered l = |x|):

Pretty, isn't it!