Wednesday, May 29, 2013

Implementing simple pricer with Visitor Design Pattern in VBA

In this short post, we are using Visitor Design Pattern for implementing simple pricer design in VBA. In essence, Visitor enables us to separate data and algorithms. Instrument knows all its parameters for a specific financial instrument and Pricer knows its specific pricing algorithm for a specific financial instrument. Somehow, we need to pair these two components together. Visitor enables that.

Instrument

Instrument class is there only for setting, holding and distributing all instrument-related parameters inside parameter wrapper. In essence, it is only having setter and getter methods. If you do not have any idea what is going on with parameter wrapper, you can read the following post http://mikejuniperhill.blogspot.fi/2013/05/handling-parameters-dynamically-with.html

IPricer

This is a public interface, which has only one method - visit, which takes in Instrument object as an argument. All concrete Pricers are implemented from this interface. Pricer implementation has specific pricing algorithm for some specific type of financial instrument, which has some specific input parameters. With the mechanism used in Visitor, a Pricer has an access to parameter wrapper of Instrument and hereby, it can use all instrument-related parameters for its specific pricing algorithm.

Example

First, enumerator for the needed parameter wrapper is given below. Note, that you could add any number of enumerated constants, as long as those constants are unique:

Option Explicit
'
Public Enum PRM
    '
    s = 1 'spot
    y = 2 'yield
    m = 3 'maturity
    p = 4 'price
End Enum
' 

So, let us go through one simple example program, where we are pricing a simple non-cashflow-paying forward with cost-of-carry-method. First, we create a set of needed parameters into parameter wrapper. Remember to reference Microsoft Scripting Runtime library from VB editor:

Option Explicit
'
Sub tester()
    '
    Dim parameters As New Scripting.Dictionary
    parameters.Add PRM.s, CDbl(100)
    parameters.Add PRM.y, CDbl(0.02)
    parameters.Add PRM.m, CDbl(1.25)
    '
End Sub
'

After this, we create desired Pricer implementation, which has a specific pricing algorithm for a simple forward:


Option Explicit
'
Sub tester()
    '
    Dim parameters As New Scripting.Dictionary
    parameters.Add PRM.s, CDbl(100)
    parameters.Add PRM.y, CDbl(0.02)
    parameters.Add PRM.m, CDbl(1.25)
    '
    Dim pricer As IPricer
    Set pricer = New CostOfCarry
    '
End Sub
'

Next, we create the actual Instrument and feed our parameter wrapper for it. Then, we set up desired Pricer implementation by using accept function of Instrument object. Inside this accept function, Pricer’s visit function is then going to get called. In this visit function, we are giving Instrument itself as an argument for Pricer. Effectively, Pricer now has an access into parameter wrapper of Instrument and it can use all forward parameters for its specific pricing algorithm for a simple forward. Finally, Pricer saves the result of the pricing algorithm directly back to parameter wrapper, from which we can get the result of pricing. Finally, we release all objects involved:

Option Explicit
'
Sub tester()
    '
    Dim parameters As New Scripting.Dictionary
    parameters.Add PRM.s, CDbl(100)
    parameters.Add PRM.y, CDbl(0.02)
    parameters.Add PRM.m, CDbl(1.25)
    '
    Dim pricer As IPricer
    Set pricer = New CostOfCarry
    '
    Dim forward As New Instrument
    forward.setParameters parameters
    forward.accept pricer
    Debug.Print forward.getParameters.Item(PRM.p)
    '
    Set forward = Nothing
    Set pricer = Nothing
    Set parameters = Nothing
End Sub
'

All Modules and Classes involved are given here below.

' STANDARD VBA MODULE
Option Explicit
'
Sub tester()
    '
    Dim parameters As New Scripting.Dictionary
    parameters.Add PRM.s, CDbl(100)
    parameters.Add PRM.y, CDbl(0.02)
    parameters.Add PRM.m, CDbl(1.25)
    '
    Dim pricer As IPricer
    Set pricer = New CostOfCarry
    '
    Dim forward As New Instrument
    forward.setParameters parameters
    forward.accept pricer
    Debug.Print forward.getParameters.Item(PRM.p)
    '
    Set forward = Nothing
    Set pricer = Nothing
    Set parameters = Nothing
End Sub
'
'
' STANDARD VBA MODULE
Option Explicit
'
Public Enum PRM
    '
    s = 1 'spot
    y = 2 'yield
    m = 3 'maturity
    p = 4 'price
End Enum
'
'
' VBA CLASS MODULE (NAME = IPricer)
Option Explicit
'
Public Function visit(ByRef security As Instrument)
End Function
'
'
'
Option Explicit
'
' VBA CLASS MODULE (NAME = CostOfCarry)
Implements IPricer
'
Private Function IPricer_visit(ByRef security As Instrument)
    '
    Dim s As Double: s = security.getParameters.Item(PRM.s)
    Dim y As Double: y = security.getParameters.Item(PRM.y)
    Dim m As Double: m = security.getParameters.Item(PRM.m)
    security.getParameters.Item(PRM.p) = s * Exp(y * m)
End Function
'
'
' VBA CLASS MODULE (NAME = Instrument)
Option Explicit
'
Private p As Scripting.Dictionary
'
Public Function accept(ByRef pricer As IPricer)
    pricer.visit Me
End Function
'
Public Function getParameters() As Scripting.IDictionary
    Set getParameters = p
End Function
'
Public Function setParameters(ByRef parameters As Scripting.IDictionary)
    Set p = parameters
End Function
'
 

The purpose of this posting was to open up one possible approach for implementing Visitor pattern in VBA. Visitor itself enables us to separate data and algorithms, which enables us to create easily extendable designs. For example, if we ever need any new pricing algorithm for that forward in our example, we just need to plug-in a new Pricer implementation for a forward into our existing design.

Moreover, since all instrument-related parameters are managed inside that dynamic parameter wrapper, there is no need to modify Instrument object in any way. The only thing what changes for specific instrument, is the content of that parameter wrapper. Note, that we can also store objects inside that parameter wrapper. This means, that we could store Term Structure object, which contains the complete valuation curve, as a one Instrument-related parameter in that wrapper, for example.

I hope that you have got some kind of an idea about my Visitor pattern implementation and what is going on in that program. Personally, I find this scheme of separating data and algorithms to be extremely valuable.
-Mike



1 comment: