8 people like it.
Like the snippet!
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:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
|
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
// Simple contracts representing sale and repeated purchase
let msft =
sellOn (DateTime(2012, 4, 21)) ("MSFT", 350.0)
let appl =
purchaseRepeatedly (DateTime(2012, 4, 23)) (TimeSpan.FromDays(7.0))
10 ("AAPL", 220.0)
// Combination of the two above contracts in one
let itcontract =
sellOn
(DateTime(2012, 4, 30)) ("MSFT", 23.0) $
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
val itcontract : Contract
Full name: Script.itcontract
More information