Entries by lessCode (29)


Windows Mobile got me fired (or at least it could have done)

After resisting getting a so-called “smart”-phone for the longest time, making do with a pay-as-you-go Virgin Mobile phone (I wasn’t a heavy user), I recently stumped up for the T-Mobile HTC Touch Pro2. I was going to be traveling in Europe, and I also wanted to explore writing an app or two for the device (if I can ever find the time), so I convinced myself that the expense was justified. After three months or so, I think I should have gone for the iPhone 3GS.

Coincidentally, the week I got the HTC, my old alarm clock (a cheap Samsonite travel alarm) bit the dust, and so I started using the phone as a replacement (it was on the nightstand anyway, and the screen slides out and tilts up nicely as a display). I also picked up a wall charger so that it could charge overnight and I wouldn’t risk it running out of juice and not waking me up.

Over the last few weeks, however, the timekeeping on the device has started to become erratic. First it would lose time over the course of a day, to the tune of about 15 minutes or so. Then I’d notice that when I’d set it down and plug it in for the night, the time would just suddenly jump back by several hours, and I’d have to reset it. I guess this must have happened four or five times over the course of a couple of months, but it always woke me up on time.

Today I woke up at 8.30am to bright sunshine, my phone proclaiming it to be 4.15am. My 6.00am alarm clearly useless; and I’m glad the 8am call I had scheduled wasn’t mandatory on my part.

A pretty gnarly bug for a business-oriented smart-phone.


Discount/Zero Curve Construction in F# – Part 4 (Core Math)

All that’s left to cover in this simplistic tour of discount curve construction is to fill in the implementations of the core mathematics underpinning the bootstrapping process.

computeDf simply calculates the next discount factor based on a previously computed one:

let computeDf fromDf toQuote =
    let dpDate, dpFactor = fromDf
    let qDate, qValue = toQuote
    (qDate, dpFactor * (1.0 / 
                        (1.0 + qValue * dayCountFraction { startDate = dpDate; 
                                                           endDate = qDate })))
Where for dayCountFraction we’ll assume an Actual/360 day count convention, but this could be generalized to pass the day counting method as a function parameter to computeDf:
  let dayCountFraction period = double (period.endDate - period.startDate).Days / 360.0

findDf looks up a discount factor on the curve, for a given date, interpolating if necessary. Again, here tail recursion and pattern matching make this relatively clean:

  let rec findDf interpolate sampleDate =
      // exact match
      (dpDate:Date, dpFactor:double) :: tail 
        when dpDate = sampleDate
        -> dpFactor
      // falls between two points - interpolate    
    | (highDate:Date, highFactor:double) :: (lowDate:Date, lowFactor:double) :: tail 
        when lowDate < sampleDate && sampleDate < highDate
        -> interpolate sampleDate (highDate, highFactor) (lowDate, lowFactor)
      // recurse      
    | head :: tail
        -> findDf interpolate sampleDate tail
      // falls outside the curve
    | [] 
        -> failwith "Outside the bounds of the discount curve"

logarithmic does logarithmic interpolation for a date that falls between two points on the discount curve. This function is passed by value as the interpolate parameter to findDf above:

  let logarithmic (sampleDate:Date) highDp lowDp = 
    let (lowDate:Date), lowFactor = lowDp
    let (highDate:Date), highFactor = highDp
    lowFactor * ((highFactor / lowFactor) ** 
                 (double (sampleDate - lowDate).Days / double (highDate - lowDate).Days))

Newton’s Method is quite straightforward in F#:
let newton f df (guess:double) = guess - f guess / df guess

To recursively solve using Newton’s Method to a given accuracy:
  let rec solveNewton f df accuracy guess =
    let root = (newton f df guess)
    if abs(root - guess) < accuracy then root else solveNewton f df accuracy root

And all that remains are the functions that feed Newton; the price of the market swap and its first derivative – note that this is certainly not the most efficient way to do this, because to compute the derivative we recalculate the price in order to approximate the derivative with a finite-difference method:
  let deriv f x =
    let dx = (x + max (1e-6 * x) 1e-12)
    let fv = f x
    let dfv = f dx
    if (dx <= x) then
        (dfv - fv) / 1e-12
        (dfv - fv) / (dx - x)

  let computeSwapDf dayCount spotDate swapQuote discountCurve swapSchedule (guessDf:double) =
    let qDate, qQuote = swapQuote
    let guessDiscountCurve = (qDate, guessDf) :: discountCurve 
    let spotDf = findDf logarithmic spotDate discountCurve
    let swapDf = findPeriodDf { startDate = spotDate; endDate = qDate } guessDiscountCurve
    let swapVal =
        let rec _computeSwapDf a spotDate qQuote guessDiscountCurve =
              swapPeriod :: tail ->
                let couponDf = findPeriodDf { startDate = spotDate; endDate = swapPeriod.endDate } guessDiscountCurve
                _computeSwapDf (couponDf * (dayCount swapPeriod) * qQuote + a) spotDate qQuote guessDiscountCurve tail

            | [] -> a
        _computeSwapDf -1.0 spotDate qQuote guessDiscountCurve swapSchedule
    spotDf * (swapVal + swapDf)

And finally, the zero coupon rates can be found with something like the following direct mapping, on the basis that there are 365 days in a year:
  let zeroCouponRates = discs
                      |> Seq.map (fun (d, f) 
                                    -> (d, 100.0 * -log(f) * 365.0 / double (d - curveDate).Days))

All in all, I think that a functional language like F# provides a much simpler means to code these types of calculation over a typical C or C++ implementation (notwithstanding performance considerations, which I’ve yet to study in any depth, but I have a hunch that with the advent of cloud computing and massively multicore hardware, that for this kind of work it’s going to become less and less about “straight-line” speed in clock cycles or operations, and more and more about the simplicity with which we can reason about such code in order to find inherent functional parallelism).
I’m also wondering about the benefits of functional programming when it comes to pricing certain derivative trades with payoff formulae that might be maintained by an end-user-trader or quantitative analyst without requiring anything we’d currently regard as “software engineering”. This question touches on the use of functional languages as Domain-Specific Languages (DSLs), and may be the topic of a future series of posts as time permits…

Discount/Zero Curve Construction in F# – Part 3 (Bootstrapping)


In Part 1, the first lines of code we saw formed the final step in the construction of the discount curve:

let discs = [ (curveDate, 1.0) ]
            |> bootstrap spotPoints 
            |> bootstrapCash spotDate cashPoints
            |> bootstrapFutures futuresStartDate futuresPoints
            |> bootstrapSwaps spotDate USD swapPoints
            |> Seq.sortBy (fun (qDate, _) -> qDate)

The curve begins with today’s discount factor of 1.0 in a one-element list, which is passed to the bootstrap function along with the spot quotes.

let rec bootstrap quotes discountCurve =
    match quotes with
      quote :: tail -> 
        let newDf = computeDf (List.hd discountCurve) quote
        bootstrap tail (newDf :: discountCurve)
    | [] -> discountCurve

This tail recursion works through the given quotes, computing the discount factor for each based on the previous discount factor in the curve (the details of this we’ll cover in Part 4), and places that new discount factor at the head of a new curve, that is used to continue the recursion. When there are no more quotes, the discount curve is returned, ending the recursion. After bootstrapping the spot quotes, the curve looks like this:



Cash quotes are bootstrapped with respect to the spot discount factor, rather than their previous cash point:

let rec bootstrapCash spotDate quotes discountCurve =
    match quotes with
      quote :: tail -> 
        let spotDf = (spotDate, findDf logarithmic spotDate discountCurve)
        let newDf = computeDf spotDf quote
        bootstrapCash spotDate tail (newDf :: discountCurve)
    | [] -> discountCurve
Here we find the discount factor at the spot date (more about findDf in Part4), tail recurse to compute each cash quote’s corresponding discount factor with respect to the spot discount factor, and prepend that new factor to the discount curve in a similar fashion to the standard bootstrap function. After the cash points are all computed, the curve will be as follows:


Once again, the futures offer a twist, albeit a minor one this time:

let bootstrapFutures futuresStartDate quotes discountCurve =
    match futuresStartDate with
    | Some d ->
        bootstrap (Seq.to_list quotes) 
                  ((d, findDf logarithmic d discountCurve) :: discountCurve)
    | None -> discountCurve
The futures are bootstrapped starting from the beginning of the futures schedule – this is the reason why we calculated futuresStartDate in Part2. For the discount factor at this point, we interpolate using the curve we’ve built thus far. Once that first futures discount point is established, we can place that at the head of a new curve that is subsequently used to bootstrap the futures quotes using the standard approach we employed previously for spot quotes (i.e. each factor is with respect to the last). After the futures, we have this curve:


Note that these aren’t in date order at this point, since we bootstrapped from the futures start date of Jun 17th, but that’s OK for our purposes – it won’t affect the accuracy of the final curve once we sort it chronologically.

Now to the swaps -- this time it’s the swaps that complicate the procedure. With the assumption that the swap quotes are fair market rates (present value zero), we use a root solver (in this case Newton’s method) to find the discount factor of each swap, pricing them using the curve we’ve built thus far:

let rec bootstrapSwaps spotDate calendar swapQuotes discountCurve =
    match swapQuotes with
      (qDate, qQuote) :: tail ->
        // build the schedule for this swap                
        let swapDates = schedule semiAnnual { startDate = spotDate; endDate = qDate }
        let rolledSwapDates = Seq.map (fun (d:Date) -> roll RollRule.Following calendar d) 
        let swapPeriods = Seq.to_list (Seq.map (fun (s, e) -> { startDate = s; endDate = e }) 
                                      (Seq.pairwise rolledSwapDates))
        // solve
        let accuracy = 1e-12
        let spotFactor = findDf logarithmic spotDate discountCurve
        let f = computeSwapDf dayCount spotDate (qDate, qQuote) discountCurve swapPeriods 
        let newDf = solveNewton f accuracy spotFactor                   

        bootstrapSwaps spotDate calendar tail ((qDate, newDf) :: discountCurve)
    | [] -> discountCurve

For each swap we build a semi-annual schedule from spot to swap maturity using the schedule function, which recursively builds a sequence of dates six months apart:

let rec schedule frequency period =
    seq {
        yield period.startDate
        let next = frequency period.startDate
        if (next <= period.endDate) then
            yield! schedule frequency { startDate = next; endDate = period.endDate }
Where frequency (in this case semiAnnual) is a function in its own right, that does – guess what?
let semiAnnual (from:Date) = from.AddMonths(6)
Each of the schedule dates in the sequence is then rolled according to the Following rolling rule, and then taken pairwise to generate a schedule of unbroken start and end dates for each period. This schedule is used to calculate both the discount factor and the first derivative of each swap quote, which in turn feed Newton’s method along with our desired accuracy of twelve decimals. Each result is placed at the head of our growing discount curve which will be used to compute the next swap discount factor. In the end our complete curve looks like this:




In Part 4, we’ll dive into to (relatively simple) math functions that underpin the bootstrapping calculations.


No State Machines in Windows Workflow 4.0?

After learning that Workflow Foundation 4.0 is likely to be missing StateMachineActivity, I think I’m going to hold off on any more research into lifecycle-of-OTC-derivative-as-Workflow, until 4.0 is released. Which is a shame, because in 3.5 I actually liked what I saw so far and was formulating some interesting posts on this.


Convert Word Documents to PDF with an MSBuild Task

I needed to convert a lot of Microsoft Word documents to PDF format, as one step in a continuous integration build of a Visual Studio project. To save a lot of build time, an incremental build of this project needs to only spend time converting the Word documents that actually changed since the last build. Rather than write a Powershell script, or other such out-of-band mechanism, a simple custom MSBuild task does the trick nicely.

using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.Build.Framework;
using Microsoft.Office.Interop.Word;

namespace MSBuild.Tasks {
  public class Doc2Pdf : Microsoft.Build.Utilities.Task {

    private static object missing = Type.Missing;

    public ITaskItem[] Inputs { get; set; }

    public ITaskItem[] Outputs { get; set; }

    public ITaskItem[] ConvertedFiles { get; set; }

    public override bool Execute() {
      _Application word = (_Application) new Application();
      _Document doc = null;

      try {
        List<ITaskItem> convertedFiles = new List<ITaskItem>();

        for (int i = 0; i < Inputs.Length; i++ ) {
          ITaskItem docFile = Inputs[i];
          ITaskItem pdfFile = Outputs[i];

                           "DOC2PDF: Converting {0} -> {1}", 
                           docFile.ItemSpec, pdfFile.ItemSpec));

          FileInfo docFileInfo = new FileInfo(docFile.ItemSpec);
          if (!docFileInfo.Exists) {
            throw new FileNotFoundException("No such file", docFile.ItemSpec);

          object docFileName = docFileInfo.FullName;

          FileInfo pdfFileInfo = new FileInfo(pdfFile.ItemSpec);

          object pdfFileName = pdfFileInfo.FullName;

          word.Visible = false;
          doc = word.Documents.Open(ref docFileName, 
                    ref missing, ref missing, ref missing, ref missing, ref missing, 
                    ref missing, ref missing, ref missing, ref missing, ref missing, 
                    ref missing, ref missing, ref missing, ref missing, ref missing);

          object fileFormat = 17;
          doc.SaveAs(ref pdfFileName, ref fileFormat, 
                     ref missing, ref missing, ref missing, ref missing, ref missing, 
                     ref missing, ref missing, ref missing, ref missing, ref missing, 
                     ref missing, ref missing, ref missing, ref missing);


        return true;
      catch (Exception ex) {
        return false;
      finally {
        object saveChanges = false;
        if (doc != null)
          doc.Close(ref saveChanges, ref missing, ref missing);
        word.Quit(ref saveChanges, ref missing, ref missing);

The Office interop APIs make this code messier than it needs to be, with all the optional parameters that we don’t care about in this case. Fortunately this story gets better in C#4.0 with the new optional parameters feature.

Assuming you build the above into an assembly called Doc2PdfTask.dll, and put the assembly in the MSBuild extensions directory, you can then set up your project file to do something like this:

<Project DefaultTargets="Build"
  <UsingTask AssemblyFile="$(MSBuildExtensionsPath)\Doc2PdfTask.dll"
             TaskName="MSBuild.Tasks.Doc2Pdf" />
  <Target Name="Build"
          DependsOnTargets="Convert" />
  <Target Name="Convert"
    <Doc2Pdf Inputs="%(WordDocuments.Identity)"
      <Output TaskParameter="ConvertedFiles"
              ItemName="PdfDocuments" />
    <WordDocuments Include="**\*.doc" />
    <WordDocuments Include="**\*.docx" />

All Word documents under the project directory (recursively), will be converted if necessary. Obviously, you’ll need Microsoft Word installed for this to work (I have Office 2007).