Using QuantLib from Clojure via the SWIG/Java binding

As I mentioned in a previous post we have been doing some work in QuantLib/Swig/Java in part using the Clojure language which is build on top of the Java Virtual Machine. Using Clojure can give substantial benefits over using QuantLib from normal Java, including much simpler, less verbose code and an interactive development environment.

In order to enable correct loading of the JNI part of SWIG binding the technique described here needs to be used. No other modifications to the standard SWIG Java binding of QuantLib is reuiqred.

Here is a quick example of building a Yield Curve in Clojure using the QuantLib libraries:

(ns cql.core
  (:import (org.quantlib Calendar Actual360 TARGET Date Month Settings
                         TimeUnit
                         QuoteHandle Period BusinessDayConvention DepositRateHelper SimpleQuote
                         SwapRateHelper Frequency Thirty360 Euribor6M
                         RateHelperVector PiecewiseFlatForward ActualActual QuoteHandleVector DateVector
                         FuturesRateHelper IMM
                         )))

(def indata2 [ [:depo   [1 TimeUnit/Days] 0.00892]
               [:depo   [1 TimeUnit/Weeks] 0.01028]
               [:depo   [1 TimeUnit/Months] 0.01247]
               [:depo   [2 TimeUnit/Months] 0.01351]
               [:depo   [3 TimeUnit/Months] 0.01488]
               [:depo   [4 TimeUnit/Months] 0.01550]
               [:depo   [5 TimeUnit/Months] 0.01618]
               [:depo   [6 TimeUnit/Months] 0.01701]
               [:depo   [7 TimeUnit/Months] 0.01761]
               [:depo   [8 TimeUnit/Months] 0.01818]
               [:depo   [9 TimeUnit/Months] 0.01876]
               [:depo   [10 TimeUnit/Months] 0.01931]
               [:depo   [11 TimeUnit/Months] 0.01988]
               [:depo   [12 TimeUnit/Months] 0.02044]
               [:future [(Date. 19 Month/September 2012) 0] 98.84]
               ])


(def ^:dynamic *fixingDays* 2)
(def ^:dynamic *calendar* (TARGET.))
(def ^:dynamic *depositDayCounter* (Actual360.))

(defn mkRateHelper [ [t [pn pt] rate] ]
  (case t
    :depo  (DepositRateHelper. (QuoteHandle. (SimpleQuote. rate))
                               (Period. pn pt)
                               (long *fixingDays*)
                               *calendar*
                               BusinessDayConvention/ModifiedFollowing
                               true
                               *depositDayCounter*)
    :future (FuturesRateHelper.  (QuoteHandle. (SimpleQuote. rate))
                                 pn
                                 (long 3)
                                 *calendar*
                                 BusinessDayConvention/ModifiedFollowing
                                 (Boolean. false)
                                 *depositDayCounter*
                                 (QuoteHandle. (SimpleQuote. 0)))
    :swap  (SwapRateHelper. (QuoteHandle. (SimpleQuote. rate))
                            (Period. pn pt)
                            *calendar*
                            Frequency/Annual
                            BusinessDayConvention/Unadjusted
                            (Thirty360.)
                            (Euribor6M. ))))

(defn mkRateHVect [s]
  "Turn a clojure sequence of RateHelpers into RateHelperVector for use in QuantLib"
  (let [v (RateHelperVector.)]
    (doseq [x s]
      (.add v x))
    v))

(defn prepRateData [d]
  (mkRateHVect (map mkRateHelper d)))


(defn buildCurve [settleD d]
  (PiecewiseFlatForward.  settleD
                          (prepRateData d)
                          (ActualActual.)
                          (QuoteHandleVector.)
                          (DateVector.)
                          0.0000001))

;; example call:
;; (buildCurve (.adjust (TARGET. ) (Date.  4 Month/September 2004)) indata2)