7 people like it.

DSL for financial contracts

Simple domain-specific language (DSL) for describing financial contracts in F#. A contract is represented using a discriminated union. Evaluating a contract gives the orders that may happen at a given date.

Implementation

 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: 
open System

/// Defines how a contract can be constructed
type Contract = 
  | Trade of int * string
  | After of DateTime * Contract
  | Until of DateTime * Contract
  | Combine of Contract * Contract


/// Evaluate contract on a specific day
let rec eval contract (day:DateTime) = 
  [ match contract with
    | Trade(a, n) -> yield (a, n) 
    | Combine(c1, c2) -> 
        yield! eval c1 day
        yield! eval c2 day
    | After(dt, c) when day > dt -> yield! eval c day
    | Until(dt, c) when day < dt -> yield! eval c day
    | _ -> () ]


// Functions for creating contracts
let trade (amount, what) = Trade (amount, what)
let after dt contract = After (dt, contract)
let until dt contract = Until (dt, contract)
let ($) c1 c2 = Combine(c1, c2)

Examples of a trade description

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
let msft = trade (500, "MSFT")
let goog = trade (100, "GOOG")

// What trades may happen today?
eval msft DateTime.Now
eval goog DateTime.Now

// Compose more complex contracts and evaluate them
let itstocks =   
  after (DateTime(2009, 4, 15)) msft $
  after 
    (DateTime(2009, 4, 10)) 
    (until (DateTime(2009, 4, 20)) goog)

eval itstocks DateTime.Now
eval itstocks (DateTime(2009, 4, 12))
eval itstocks (DateTime(2009, 4, 18))
namespace System
type Contract =
  | Trade of int * string
  | After of DateTime * Contract
  | Until of DateTime * Contract
  | Combine of Contract * Contract

Full name: Script.Contract


 Defines how a contract can be constructed
union case Contract.Trade: int * string -> Contract
Multiple items
val int : value:'T -> int (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.int

--------------------
type int = int32

Full name: Microsoft.FSharp.Core.int

--------------------
type int<'Measure> = int

Full name: Microsoft.FSharp.Core.int<_>
Multiple items
val string : value:'T -> string

Full name: Microsoft.FSharp.Core.Operators.string

--------------------
type string = String

Full name: Microsoft.FSharp.Core.string
union case Contract.After: DateTime * Contract -> Contract
Multiple items
type DateTime =
  struct
    new : ticks:int64 -> DateTime + 10 overloads
    member Add : value:TimeSpan -> DateTime
    member AddDays : value:float -> DateTime
    member AddHours : value:float -> DateTime
    member AddMilliseconds : value:float -> DateTime
    member AddMinutes : value:float -> DateTime
    member AddMonths : months:int -> DateTime
    member AddSeconds : value:float -> DateTime
    member AddTicks : value:int64 -> DateTime
    member AddYears : value:int -> DateTime
    ...
  end

Full name: System.DateTime

--------------------
DateTime()
   (+0 other overloads)
DateTime(ticks: int64) : unit
   (+0 other overloads)
DateTime(ticks: int64, kind: DateTimeKind) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int, calendar: Globalization.Calendar) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, kind: DateTimeKind) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, calendar: Globalization.Calendar) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, millisecond: int) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, millisecond: int, kind: DateTimeKind) : unit
   (+0 other overloads)
union case Contract.Until: DateTime * Contract -> Contract
union case Contract.Combine: Contract * Contract -> Contract
val eval : contract:Contract -> day:DateTime -> (int * string) list

Full name: Script.eval


 Evaluate contract on a specific day
val contract : Contract
val day : DateTime
val a : int
val n : string
val c1 : Contract
val c2 : Contract
val dt : DateTime
val c : Contract
val trade : amount:int * what:string -> Contract

Full name: Script.trade
val amount : int
val what : string
val after : dt:DateTime -> contract:Contract -> Contract

Full name: Script.after
val until : dt:DateTime -> contract:Contract -> Contract

Full name: Script.until
val msft : Contract

Full name: Script.msft
val goog : Contract

Full name: Script.goog
property DateTime.Now: DateTime
val itstocks : Contract

Full name: Script.itstocks

More information

Link:http://fssnip.net/9z
Posted:5 years ago
Author:Tomas Petricek
Tags: dsl , domain-specific language , discriminated union , financial