Java interface to the ISDA CDS model

The Java interface to the ISDA CDS model is based on the Java Native Interface (JNI). The interface is built out of three components:

  • The original, unmodified ISDA CDS model library, version 1.8.3
  • A collection of routines in the "C" language to help inter-operation with Java
  • A collection of Java classes (packaged in a JAR) which provide a thin wrapper around the original ISDA CDS model functionality

Together this interface makes it easy to write reliable applications in Java which make use of the ISDA Standard CDS model library, benefiting from its acceptance as the standard library while retaining the convenience of a high-level language like Java.

For more information or pricing enquiries contact us at webs@bnikolic.co.uk.

As an illustration of how the interface functions, below is a sample Java program that is contains of the original "C"-language example provided with the ISDA standard library and also some additional high-level functionality:

// Copyright (C) 2009 International Swaps and Derivatives Association, Inc.
// Copyright (C) 2009, 2010, 2012 Bojan Nikolic <bojan@bnikolic.co.uk>
// LICENSE TERMS: for on-screen viewing only of visitors to bnikolic.co.uk
//
// Example program illustrating the use of the JavaCDS library

import co.uk.bnikolic.javacds.javacdsConstants;
import co.uk.bnikolic.javacds.TCurve;
import co.uk.bnikolic.javacds.TDateInterval;
import co.uk.bnikolic.javacds.TStubMethod;

// Free functions which need no Java wrapper are defined in this class
import co.uk.bnikolic.javacds.javacds;

public class javacdsexample {

    /// Load the JNI library
    static {
        try { System.loadLibrary("javacds"); }
        catch (RuntimeException e) { e.printStackTrace(); }
    }

    static public TCurve BuildExampleZeroCurve()
    {
        String expiries[]= {"1M", "2M", "3M", "6M", "9M", "1Y",
                            "2Y", "3Y", "4Y", "5Y", "6Y", "7Y",
                            "8Y", "9Y"};
        double rates[] =  { 0.003, 0.005, 0.01, 0.01, 0.01, 0.02, 0.02,
                            0.02, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03};
        char badDayConv = 'M';
        String holidays = "None";

        String routine="BuildExampleZeroCurve";

        int baseDate = javacds.JpmcdsDate(2008, 1, 3);
        int mmDCC=javacds.JpmcdsStringToDayCountConv("Act/360");
        int dcc=javacds.JpmcdsStringToDayCountConv("30/360");

        TDateInterval ivl=javacds.JpmcdsStringToDateInterval("6M", routine);

        double freq=javacds.JpmcdsDateIntervalToFreq(ivl);

        String types="MMMMMSSSSSSSSS";
        int n=types.length();

        int[] dates=new int[n];
        for(int i=0; i<n; i++)
            {
                TDateInterval tmp=
                    javacds.JpmcdsStringToDateInterval(expiries[i], routine);

                int cdate=javacds.JpmcdsDateFwdThenAdjust(baseDate,
                                                          tmp,
                                                          javacds.getJPMCDS_BAD_DAY_NONE(),
                                                          "None");
                dates[i]=cdate;

            }

        TCurve zc = javacds.JpmcdsBuildIRZeroCurve(baseDate,
                                                   types,
                                                   dates,
                                                   rates,
                                                   n,
                                                   mmDCC,
                                                   (int)freq,
                                                   (int)freq,
                                                   dcc,
                                                   dcc,
                                                   badDayConv,
                                                   holidays);
        return zc;
    }

    // Calculate the upfront charge
    static public double CalcUpfrontCharge(TCurve curve,
                                           double couponRate)
    {
        String routine="CalcUpfrontCharge";
        int    payAccOnDefault = 1;
        double notional = 1e7;
        int    isPriceClean = 0;
        double recoveryRate = 0.4;
        double parSpread = 3600;

        int today          = javacds.JpmcdsDate(2008, 2, 1);
        int valueDate      = javacds.JpmcdsDate(2008, 2, 1);
        int benchmarkStart = javacds.JpmcdsDate(2008, 2, 2);
        int startDate      = javacds.JpmcdsDate(2008, 2, 8);
        int endDate        = javacds.JpmcdsDate(2008, 2, 12);
        int stepinDate     = javacds.JpmcdsDate(2008, 2, 9);

    int dcc=javacds.JpmcdsStringToDayCountConv("Act/360");

    TDateInterval ivl=javacds.JpmcdsStringToDateInterval("1S",
                                                        routine);
    TStubMethod stub=javacds.JpmcdsStringToStubMethod("f/s");

    double result=
      javacds.JpmcdsCdsoneUpfrontCharge(today,
                                       valueDate,
                                       benchmarkStart,
                                       stepinDate,
                                       startDate,
                                       endDate,
                                       couponRate / 10000.0,
                                       payAccOnDefault,
                                       ivl,
                                       stub,
                                       dcc,
                                       'F',
                                       "None",
                                       curve,
                                       parSpread / 10000.0,
                                       recoveryRate,
                                       isPriceClean);
    return result * notional;

  }

    static public double CalcFlatSpread(TCurve curve,
                                        double couponRate,
                                        double upfront)
    {
        String routine="CalcFlatSpread";
        int    payAccOnDefault = 1;
        double notional = 1e7;
        int    isPriceClean = 0;
        double recoveryRate = 0.4;

        int today          = javacds.JpmcdsDate(2008, 2, 1);
        int valueDate      = javacds.JpmcdsDate(2008, 2, 1);
        int benchmarkStart = javacds.JpmcdsDate(2008, 2, 2);
        int startDate      = javacds.JpmcdsDate(2008, 2, 8);
        int endDate        = javacds.JpmcdsDate(2008, 2, 12);
        int stepinDate     = javacds.JpmcdsDate(2008, 2, 9);

        int dcc=javacds.JpmcdsStringToDayCountConv("Act/360");

        TDateInterval ivl=javacds.JpmcdsStringToDateInterval("1S",
                                                             routine);
        TStubMethod stub=javacds.JpmcdsStringToStubMethod("f/s");

        double result=
            javacds.JpmcdsCdsoneSpread(today,
                                       valueDate,
                                       benchmarkStart,
                                       stepinDate,
                                       startDate,
                                       endDate,
                                       couponRate / 10000.0,
                                       payAccOnDefault,
                                       ivl,
                                       stub,
                                       dcc,
                                       'F',
                                       "None",
                                       curve,
                                       upfront/notional,
                                       recoveryRate,
                                       isPriceClean);
        return result * notional;
    }

    /// Illustrates what happens if an exception in the ISDA code is
    /// triggered (this happens usually due to invalid arguments)
    static public void TriggerException()
    {
        try
            {
                int dcc=javacds.JpmcdsStringToDayCountConv("asd/df");
                System.out.println("Invalid returned value of the DCC -- should not be reached "+
                                   dcc);
            }
        catch (java.lang.RuntimeException e)
            {
                System.out.println("OK -- caught an EXPECTED exception from ISDA code\n:  "+
                                   e);
            }

        // Now redirect to a new filename in the current working directory
        // of the process. Note that the default log file name is
        // c:\errors.log
        int s=javacds.JpmcdsErrMsgFileName("newerrorlog.txt", 1);
        if (s!=0)
            {
                System.out.println("Problem: could not open new error log file");
            }
        try
            {
                int dcc=javacds.JpmcdsStringToDayCountConv("asd/df");
                System.out.println("Invalid returned value of the DCC -- should not be reached "+
                                   dcc);
            }
        catch (java.lang.RuntimeException e)
            {
                System.out.println("OK -- caught an EXPECTED exception from ISDA code\n:  "+
                                   e);
            }
  }

    /// Verify that no exception is triggered if correct argument is
    /// passed to the function
    static public void NoTriggerException()
    {
        try
            {
                int dcc=javacds.JpmcdsStringToDayCountConv("30/360");
                System.out.println("Valid returned value of the DCC "+
                                   dcc);
            }
        catch (java.lang.RuntimeException e)
            {
                System.out.println("Caught an exception from ISDA code: "+
                                   e);
            }
    }

  /// Make a credit spread curve
  static public TCurve mkCleanSpreadCurve(TCurve discCurve)
  {
    int today          = javacds.JpmcdsDate(2008, 2, 1);
    int valueDate      = javacds.JpmcdsDate(2008, 2, 1);
    int startDate      = javacds.JpmcdsDate(2008, 2, 8);
    int stepinDate     = javacds.JpmcdsDate(2008, 2, 9);
    double recoveryRate = 0.4;
    int    payAccOnDefault = 1;
    TDateInterval couponInterval=javacds.JpmcdsStringToDateInterval("1S",
                                                                    "mkCleanSpreadCurve");
    int paymentDcc=javacds.JpmcdsStringToDayCountConv("Act/360");
    TStubMethod stubType=javacds.JpmcdsStringToStubMethod("f/s");
    char badDayConv = 'M';
    String calendar = "None";

    int nbDate=5;
    int[] endDates=  { javacds.JpmcdsDate(2008, 7, 12),
                       javacds.JpmcdsDate(2009, 2, 12),
                       javacds.JpmcdsDate(2009, 7, 12),
                       javacds.JpmcdsDate(2010, 2, 12),
                       javacds.JpmcdsDate(2010, 7, 12) };

    double [] couponRates = { 0.01, 0.02, 0.03, 0.04, 0.05};
    int[] includes =  { 1, 1, 1, 1, 1};


    TCurve res=javacds.JpmcdsCleanSpreadCurve(today,
                                             discCurve,
                                             startDate,
                                             stepinDate,
                                             valueDate,
                                             nbDate,
                                             endDates,
                                             couponRates,
                                             includes,
                                             recoveryRate,
                                             payAccOnDefault,
                                             couponInterval,
                                             paymentDcc,
                                             stubType,
                                             badDayConv,
                                             calendar);
    return res;

  }


  static public double CdsPriceNonFlat(TCurve discCurve,
                                       TCurve spreadCurve,
                                       int    endDate,
                                       double couponRate)
  {
    int today          = javacds.JpmcdsDate(2008, 2, 1);
    int valueDate      = javacds.JpmcdsDate(2008, 2, 1);
    int startDate      = javacds.JpmcdsDate(2008, 2, 8);
    int stepinDate     = javacds.JpmcdsDate(2008, 2, 9);
    double recoveryRate = 0.4;
    int    payAccOnDefault = 1;
    TDateInterval couponInterval=javacds.JpmcdsStringToDateInterval("1S",
                                                                   "mkCleanSpreadCurve");
    int paymentDcc=javacds.JpmcdsStringToDayCountConv("Act/360");
    TStubMethod stubType=javacds.JpmcdsStringToStubMethod("f/s");
    char badDayConv = 'M';
    String calendar = "None";
    int    isPriceClean = 1;

    double price=javacds.JpmcdsCdsPrice(today,
                                       valueDate,
                                       stepinDate,
                                       startDate,
                                       endDate,
                                       couponRate,
                                       payAccOnDefault,
                                       couponInterval,
                                       stubType,
                                       paymentDcc,
                                       badDayConv,
                                       calendar,
                                       discCurve,
                                       spreadCurve,
                                       recoveryRate,
                                       isPriceClean);
    return price;
  }

  static public double CdsParNonFlat(TCurve discCurve,
                                     TCurve spreadCurve,
                                     int    endDate)
  {

    int today          = javacds.JpmcdsDate(2008, 2, 1);
    int startDate      = javacds.JpmcdsDate(2008, 2, 8);
    int stepinDate     = javacds.JpmcdsDate(2008, 2, 9);
    double recoveryRate = 0.4;
    int    payAccOnDefault = 1;
    TDateInterval couponInterval=javacds.JpmcdsStringToDateInterval("1S",
                                                                   "mkCleanSpreadCurve");
    int paymentDcc=javacds.JpmcdsStringToDayCountConv("Act/360");
    TStubMethod stubType=javacds.JpmcdsStringToStubMethod("f/s");
    char badDayConv = 'M';
    String calendar = "None";
    int nbEndDates=1;
    int[] endDates =  {endDate};
    double[] res= {0} ;

    javacds.JpmcdsCdsParSpreads(today,
                               stepinDate,
                               startDate,
                               nbEndDates,
                               endDates,
                               payAccOnDefault,
                               couponInterval,
                               stubType,
                               paymentDcc,
                               badDayConv,
                               calendar,
                               discCurve,
                               spreadCurve,
                               recoveryRate,
                               res);
    return res[0];


  }

    public static void main(String[] args) throws Exception {

        System.out.println("JavaCDS example program");
        System.out.println(javacds.JpmcdsVersionString());

        // Example of getting constants
        System.out.println("Years per day: " + javacdsConstants.JPMCDS_YEARS_PER_DAY + "\n");

        TCurve zerocurve=BuildExampleZeroCurve();

        System.out.println("Discount factor on 3rd Jan 08: " +
                           javacds.JpmcdsZeroPrice(zerocurve,
                                                   javacds.JpmcdsDate(2008,1,3)));

        System.out.println("Discount factor on 3rd Jan 09: " +
                           javacds.JpmcdsZeroPrice(zerocurve,
                                                   javacds.JpmcdsDate(2009,1,3)));

        System.out.println("Discount factor on 3rd Jan 17: " +
                           javacds.JpmcdsZeroPrice(zerocurve,
                                                   javacds.JpmcdsDate(2017,1,3)));

        System.out.println("\nUpfront charge @ cpn = 0bps    ="+
                           CalcUpfrontCharge(zerocurve,
                                             0));

        System.out.println("Upfront charge @ cpn = 3600bps    ="+
                           CalcUpfrontCharge(zerocurve,
                                             3600));

        System.out.println("Upfront charge @ cpn = 7200bps    ="+
                           CalcUpfrontCharge(zerocurve,
                                             7200));

        System.out.println("Test round-trip from flat spread to upfront and back to spread: ");
        System.out.println("Flat par spread  @ cpn = 72000bps, input spread 3600bp:  "+
                           CalcFlatSpread(zerocurve,
                                          7200,
                                          CalcUpfrontCharge(zerocurve,
                                                            7200)));

        System.out.println("\nException handling tests");
        TriggerException();
        NoTriggerException();
        TriggerException();
        NoTriggerException();
        System.out.println("End of exception tests");


        System.out.println("Test round-trip from benchmarks to srpead curve and then back to prices: ");

        TCurve spreadcurve=mkCleanSpreadCurve(zerocurve);
        System.out.println("Pricing from spread curve on 2010-02-12 with original coupon:  "+
                           CdsPriceNonFlat(zerocurve,
                                           spreadcurve,
                                           javacds.JpmcdsDate(2010, 2, 12),
                                           0.04));

        System.out.println("Par coupon  for  2010-02-12 maturity:  "+
                           CdsParNonFlat(zerocurve,
                                         spreadcurve,
                                         javacds.JpmcdsDate(2010, 2, 12)));
    }

}

For more information or pricing enquiries contact us at webs@bnikolic.co.uk.