packages feed

Chart-fltkhs-0.1.0.4: examples/Example13.hs

{-# LANGUAGE OverloadedStrings
  , BangPatterns
  , MultiWayIf
  , LambdaCase
  , TemplateHaskell
#-}
module Main where


import           Control.Monad                  ( void )

import qualified Graphics.UI.FLTK.LowLevel.FL  as FL
import           Graphics.UI.FLTK.LowLevel.Fl_Types
import           Graphics.UI.FLTK.LowLevel.FLTKHS
                                               as FL
import           Graphics.UI.FLTK.LowLevel.Fl_Enumerations

import           Control.Lens

import           Graphics.Rendering.Chart
import           Graphics.Rendering.Chart.Grid
import           Graphics.Rendering.Chart.Easy as Ch
import           Graphics.Rendering.Chart.Backend.FLTKHS


-- haskell black scholes (see http://www.espenhaug.com/black_scholes.html)

blackScholesCall :: Double -> Double -> Double -> Double -> Double -> Double
blackScholesCall s x t r v = s * normcdf d1 - x * exp (-r * t) * normcdf d2
  where
    d1 = (log (s / x) + (r + v * v / 2) * t) / (v * sqrt t)
    d2 = d1 - v * sqrt t

normcdf :: Double -> Double
normcdf x | x < 0     = 1 - w
          | otherwise = w
  where
    w =
        1.0
            - 1.0
            / sqrt (2.0 * pi)
            * exp (-l * l / 2.0)
            * ( a1
              * k
              + a2
              * (k ** 2)
              + a3
              * (k ** 3)
              + a4
              * (k ** 4)
              + a5
              * (k ** 5)
              )
    k  = 1.0 / (1.0 + 0.2316419 * l)
    l  = abs x
    a1 = 0.31938153
    a2 = -0.356563782
    a3 = 1.781477937
    a4 = -1.821255978
    a5 = 1.330274429


-- Construct a single chart for the grid
bsChart :: Double -> Double -> Double -> Layout Double Double
bsChart t r v = execEC $ do
    layout_y_axis . laxis_generate .= scaledAxis def (-10, 80)
    plot $ line "" [[ (s, blackScholesCall s 100 0.001 r v) | s <- ss ]]
    plot $ line lbl [[ (s, blackScholesCall s 100 t r v) | s <- ss ]]
  where
    ss  = [50, 51 .. 150]
    lbl = "t = " ++ show t ++ ", r = " ++ show r

-- Construct a grid of charts, with a single title accross the top
grid = title `wideAbove` aboveN
    [ besideN [ layoutToGrid (bsChart t r v) | t <- ts ] | r <- rs ]
  where
    ts    = [1, 2, 5]
    rs    = [0.05, 0.10, 0.20]
    v     = 0.10
    title = setPickFn nullPickFn
        $ label ls HTA_Centre VTA_Centre "Black Scholes Option Values"
    ls = def { _font_size = 15, _font_weight = FontWeightBold }





drawChart :: Ref Widget -> IO ()
drawChart widget = do
    rectangle' <- getRectangle widget
    withFlClip rectangle' $
        void $ renderToWidget widget
            $ fillBackground def
            $ gridToRenderable
            $ grid


main :: IO ()
main = do
    let width  = 800
        height = 600

    window' <- doubleWindowNew (Size (Width width) (Height height))
                               Nothing
                               Nothing
    begin window'
    widget' <- widgetCustom
        (FL.Rectangle (Position (X 0) (Y 0))
                      (Size (Width width) (Height height))
        )
        Nothing
        drawChart
        defaultCustomWidgetFuncs
    end window'
    showWidget window'
    void FL.run