-
Notifications
You must be signed in to change notification settings - Fork 0
/
contract.hs
99 lines (76 loc) · 2.57 KB
/
contract.hs
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
module Contract where
-- Zero-Coupon Bond
-- "Ich bekomme am 24.12.2020 100EUR"
-- "Ich bekomme am 30.12.2021 100GBP"
-- 1. Atomare Bestandteile:
-- "Später"
-- Währung
-- Stückzahl
-- 2. Kombinatoren suchen
-- 3. wiederholen mit mehr Beispielen
-- Swap: Ich bekomme 100EUR und zahle 100GBP.
-- 4. Semantik
newtype Date = Date String
deriving (Eq, Ord, Show)
type Amount = Double
data Currency = EUR | GBP
deriving (Eq, Show)
-- Idee: Vertrag ist immer "jetzt"
data Contract =
-- Zcb Date Amount Currency
Zero
| One Currency
| Multiple Amount Contract
-- Later d c: Zum Zeitpunkt d werde ich den Vertrag c abschließen
| Later Date Contract
| Give Contract -- dreht Richtung aller Zahlungen um
-- And :: Contract -> Contract -> Contract
-- Halbgruppe - check
| And Contract Contract
deriving (Eq, Show)
zcb1 = Later (Date "2020-12-24") (Multiple 100 (One EUR))
zcb2 = Later (Date "2021-12-30") (Multiple 100 (One GBP))
zcb date amount currency = Later date (Multiple amount (One currency))
contract1 = And zcb1 zcb2
-- Semantik
-- Für einen Vertrag die Zahlungen ausspucken
data Direction = Long | Short
deriving Show
data Payment = Payment Direction Amount Currency
deriving Show
scalePayment factor (Payment direction amount currency) =
Payment direction (factor * amount) currency
invertPayment (Payment direction amount currency) =
Payment (invertDirection direction) amount currency
invertDirection Long = Short
invertDirection Short = Long
-- smart constructor
and :: Contract -> Contract -> Contract
and Zero contract = contract
and contract Zero = contract
and contract1 contract2 = And contract1 contract2
multiple factor contract =
if factor == 0.0
then Zero
else if factor == 1.0
then contract
else Multiple factor contract
step :: Contract -> Date -> ([Payment], Contract)
-- "Residualvertrag"
step Zero date = ([], Zero)
step (One currency) date =
([Payment Long 1 currency], Zero)
step (Multiple amount contract) date =
let (payments, residual) = step contract date
in (map (scalePayment amount) payments, multiple amount residual)
step env@(Later date' contract) date =
if date >= date'
then step contract date
else ([], env)
step (Give contract) date =
let (payments, residual) = step contract date
in (map invertPayment payments, Give residual)
step (And contract1 contract2) date =
let (payments1, residual1) = step contract1 date
(payments2, residual2) = step contract2 date
in (payments1 ++ payments2, Contract.and residual1 residual2)