Monday, 7 April 2014

Smith Wilson and the F# Community

Recap

Last month I wrote a post on Smith Wilson and Deedle. Smith-Wilson is a method of curve fitting, which was the preferred method under QIS5 for interpolating and extrapolating interest rate curves.

In that post, I first used R with a CRAN package created by my friend and ex-colleague Phil Joubert. I then used Deedle and the R Type Provider to call this functionality from F#.

I promised to revisit this topic and generate a purely F# approach.

The F# Community

I had initially intended to generate the F# code needed, but through the F# Community I found a much better alternative. I was able to contact Russell Politzky in South Africa. Russell tells me that he is "a developer and aspiring Quant/Developer". He had generated some excellent code for Smith-Wilson and he has very kindly let me refer to this in this post. His code can be found in his GitHub repository at:
I was given more help by Adam Mlocek of StatFactory - see comments in the next section.

Math Libraries

Being able to quickly generate solutions for these types of modelling challenges is critically dependent on being able to utilise good supporting libraries. F# programmers are very lucky to have a large number of excellent options of Math libraries. These are documented on the F# Foundation site at:
Russell's code uses the open source Math.NET Numerics library. It also uses the supporting Intel Math Kernel Library (MKL) to increase the performance of the code.

Adam also provided me with a version of this code converted to use StatFactory's FCore library. I believe Adam is planning to also blog on this topic and I will add a link here when he publishes the relevant post.

EIOPA Example

In the earlier post, I replicated the results from one of the EIOPA QIS5 examples. Russell's repository already includes scripts to replicate these examples, see:
I have created a simplified version of the former to replicate the results from the earlier post:
 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
32: 
33: 
34: 
35: 
36: 
37: 
38: 
39: 
40: 
41: 
42: 
43: 
44: 
45: 
#r "System.Windows.Forms"
#r "System.Windows.Forms.DataVisualization"
#r @"..\packages\MathNet.Numerics.2.6.2\lib\net40\MathNet.Numerics.dll"
#r @"..\packages\MathNet.Numerics.FSharp.2.6.0\lib\net40\MathNet.Numerics.FSharp.dll"
#r @"..\packages\FSharp.Charting.0.90.5\lib\net40\FSharp.Charting.dll"
#load "Rates.fs"
#load "SmithWilson.fs"
#load "Plot.fs"

open System
open FSharp.Charting
open FSharp.Charting.ChartTypes
open System.Drawing
open Rates
open SmithWilson
open Plot

// This is the first of the EIOPA examples from the paper at the following URL
// http://eiopa.europa.eu/fileadmin/tx_dam/files/consultations/QIS/QIS5/ceiops-paper-extrapolation-risk-free-rates_en-20100802.pdf
let a = 0.1 // Mean reversion parameter controls rate at which curve reverts to UFR.
let UFR = Math.Log(1.0 + 0.042) // Ultimate Forward Rate expressed in NACC (converted from 0.042 NACA)
// Market data.
let m = [| 1.0; 1.0; 1.0; 1.0 |] // market prices
// Cash flow dates in year fractions.
// This is the union of all of the cash flow dates
// from all instruments.  It's expressed in years
// here.
let cashFlowDates = [| 1.0; 2.0; 3.0; 4.0; 5.0 |]

let C = // Cash flow matrix
        
    [ [ 1.01; 0.00; 0.00; 0.00; 0.00 ] // instrument 1
      [ 0.02; 1.02; 0.0; 0.0; 0.0 ] // instrument 2
      [ 0.026; 0.026; 1.026; 0.0; 0.0 ] // instrument 3
      [ 0.034; 0.034; 0.034; 0.034; 1.034 ] // instrument 4
                                            ]

let time = [| 0.0..50.0 |]
let timeDfs = PtSmithWilson a UFR m C cashFlowDates time
let dfs = timeDfs.Column(1)
let rateNACA = getNacaRates time dfs

plot (rateNACA |> Seq.zip time) 100.0 "EIOPA Sample : NACA Rates" "Rate     [% NACA]"

let ans = dfs.[4]

In lines 1 to 16, supporting code and libraries are referenced. In addition to Math.NET Numerics the code also uses the F# Charting library to support charting directly from F# Interactive.

The code from lines 18 to 38 sets up the input data. The main function PtSmithWilson is then called in line 39, which returns a Dense Matrix. In F# Interactive you get:
val timeDfs : MathNet.Numerics.LinearAlgebra.Double.DenseMatrix =
  DenseMatrix 51x2-Double
           0            1
           1     0.990099
           2     0.960978
           3     0.925216
           4     0.885004
           5     0.843439
           6     0.803782
         ...          ...
          50     0.122813
The discounts rates are then put into a Vector in line 40 and then converted to a List of spot rates with annual compounding in line 41.

These are then plotted to produce the following chart (which corresponds to the same chart produced by R in the earlier post):


Finally, we confirm that the code generates the test value of 0.885 in line 45. In F# Interactive we get:
val ans : float = 0.8850041337

3 comments:

  1. I'm impressed. You're truly well informed and very intelligent. You wrote something that people could understand and made the subject intriguing for everyone. I'm saving this for future use.


    Kendra
    www.imarksweb.org

    ReplyDelete
  2. This is a great website. I will make sure that I stop back again!.

    Sherly
    www.gofastek.com

    ReplyDelete
  3. Love it! Very interesting topics, I hope the incoming comments and suggestion are equally positive. Thank you for sharing this information that is actually helpful.


    ufgop.org
    ufgop.org

    ReplyDelete