8 people like it.

DSL for Financial Contracts

Simple domain-specific language for modeling of financial contracts.

 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: 
28: 
29: 
30: 
31: 
32: 
33: 
34: 
35: 
36: 
37: 
38: 
39: 
40: 
41: 
42: 
43: 
44: 
45: 
46: 
47: 
48: 
49: 
50: 
51: 
52: 
53: 
54: 
open System

// ------------------------------------------------------------------
// Implementation of the DSL

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

/// Evaluate contract on a specific day
let rec run contract (day:DateTime) = seq {
  match contract with 
  | Trade(what, amount) -> 
      yield what, amount
  | Opposite(contract) ->
      for what, amount in run contract day do
        yield what, amount * -1.0 
  | After(dt, contract) ->
      if day >= dt then yield! run contract day
  | Until(dt, contract) ->
      if day <= dt then yield! run contract day
  | Combine(contract1, contract2) ->
      yield! run contract1 day
      yield! run contract2 day }

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

// Functions for creating advanced contracts
let purchase (what, amount) = trade(what, amount)
let sell (what, amount) = trade(what, amount) |> opposite
let onDate dt contract = after dt (until dt contract)
let repeatedly (start:DateTime) (span:TimeSpan) times contract = 
  [ for n in 0 .. times -> 
      onDate (start + TimeSpan(span.Ticks * int64 n)) contract ]
  |> Seq.reduce ($)
let purchaseOn date what = onDate date (purchase what)
let sellOn date what = onDate date (sell what)
let purchaseRepeatedly dt ts n what = repeatedly dt ts n (purchase what)

// ------------------------------------------------------------------
// Example - evaluating contracts

let msft = purchaseOn (DateTime(2012, 4, 21)) ("MSFT", 350.0)
let appl = purchaseRepeatedly (DateTime(2012, 4, 23)) (TimeSpan.FromDays(7.0))
                              10 ("AAPL", 220.0)
namespace System
type Contract =
  | Trade of string * float
  | Opposite of Contract
  | 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: string * float -> Contract
Multiple items
val string : value:'T -> string

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

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

Full name: Microsoft.FSharp.Core.string
Multiple items
val float : value:'T -> float (requires member op_Explicit)

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

--------------------
type float = Double

Full name: Microsoft.FSharp.Core.float

--------------------
type float<'Measure> = float

Full name: Microsoft.FSharp.Core.float<_>
union case Contract.Opposite: Contract -> Contract
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 run : contract:Contract -> day:DateTime -> seq<string * float>

Full name: Script.run


 Evaluate contract on a specific day
val contract : Contract
val day : DateTime
Multiple items
val seq : sequence:seq<'T> -> seq<'T>

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

--------------------
type seq<'T> = Collections.Generic.IEnumerable<'T>

Full name: Microsoft.FSharp.Collections.seq<_>
val what : string
val amount : float
val dt : DateTime
val contract1 : Contract
val contract2 : Contract
val trade : what:string * amount:float -> Contract

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

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

Full name: Script.until
val opposite : contract:Contract -> Contract

Full name: Script.opposite
val c1 : Contract
val c2 : Contract
val purchase : what:string * amount:float -> Contract

Full name: Script.purchase
val sell : what:string * amount:float -> Contract

Full name: Script.sell
val onDate : dt:DateTime -> contract:Contract -> Contract

Full name: Script.onDate
val repeatedly : start:DateTime -> span:TimeSpan -> times:int -> contract:Contract -> Contract

Full name: Script.repeatedly
val start : DateTime
val span : TimeSpan
Multiple items
type TimeSpan =
  struct
    new : ticks:int64 -> TimeSpan + 3 overloads
    member Add : ts:TimeSpan -> TimeSpan
    member CompareTo : value:obj -> int + 1 overload
    member Days : int
    member Duration : unit -> TimeSpan
    member Equals : value:obj -> bool + 1 overload
    member GetHashCode : unit -> int
    member Hours : int
    member Milliseconds : int
    member Minutes : int
    ...
  end

Full name: System.TimeSpan

--------------------
TimeSpan()
TimeSpan(ticks: int64) : unit
TimeSpan(hours: int, minutes: int, seconds: int) : unit
TimeSpan(days: int, hours: int, minutes: int, seconds: int) : unit
TimeSpan(days: int, hours: int, minutes: int, seconds: int, milliseconds: int) : unit
val times : int
val n : int
property TimeSpan.Ticks: int64
Multiple items
val int64 : value:'T -> int64 (requires member op_Explicit)

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

--------------------
type int64 = Int64

Full name: Microsoft.FSharp.Core.int64

--------------------
type int64<'Measure> = int64

Full name: Microsoft.FSharp.Core.int64<_>
module Seq

from Microsoft.FSharp.Collections
val reduce : reduction:('T -> 'T -> 'T) -> source:seq<'T> -> 'T

Full name: Microsoft.FSharp.Collections.Seq.reduce
val purchaseOn : date:DateTime -> string * float -> Contract

Full name: Script.purchaseOn
val date : DateTime
val what : string * float
val sellOn : date:DateTime -> string * float -> Contract

Full name: Script.sellOn
val purchaseRepeatedly : dt:DateTime -> ts:TimeSpan -> n:int -> string * float -> Contract

Full name: Script.purchaseRepeatedly
val ts : TimeSpan
val msft : Contract

Full name: Script.msft
val appl : Contract

Full name: Script.appl
TimeSpan.FromDays(value: float) : TimeSpan

More information

Link:http://fssnip.net/bJ
Posted:12 years ago
Author:Tomas Petricek
Tags: dsl