|
1 |
| -app load ["Real", "Int", "ContractBase", "Contract" ]; |
2 |
| -open ContractBase Contract; |
3 |
| - |
4 |
| -(* |
5 |
| -more JB notes about "trigger value extraction": |
6 |
| -
|
7 |
| -collecting triggers: |
8 |
| -
|
9 |
| -simpleTriggers : contr -> boolE list |
10 |
| -
|
11 |
| -triggers : contr -> (realE (obs, actually)* real list) list |
12 |
| - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
13 |
| -it could be |
14 |
| - (realE * real list) list ; grouped by the actual obs |
15 |
| - (string * int * real list) list ; grouped by the actual obs, decomposed |
16 |
| -(X) |
17 |
| - (string * (int * real list) list ) list ; grouped by observable, then by day |
18 |
| - (int * (string * real list) list ) list ; grouped by day, then observable |
19 |
| -
|
20 |
| -Better: use a "time window" rather than single days. |
21 |
| - (merge becomes more complicated, well-understood) |
22 |
| -
|
23 |
| -Similar to (X) above: |
24 |
| - (string * ((int,int) * real list) list |
25 |
| - start,end |
26 |
| -
|
27 |
| -*) |
28 |
| - |
29 |
| -fun mergeUniq xs [] = xs |
30 |
| - | mergeUniq [] ys = ys |
31 |
| - | mergeUniq (x::xs) (y::ys) |
32 |
| - = case Real.compare (x,y) of |
33 |
| - LESS => x :: mergeUniq xs (y::ys) |
34 |
| - | GREATER => y :: mergeUniq (x::xs) ys |
35 |
| - | EQUAL => x :: mergeUniq xs ys |
36 |
| - |
37 |
| -fun trMerge' (tr as (s,(d1,d2),vs), []) = [tr] |
38 |
| - | trMerge' (tr as (s,(d1,d2),vs), ((tr' as (s',(d1',d2'),vs')) :: trs)) |
39 |
| - = if s = s' then |
40 |
| - (* compares intervals and splits into several (2 or 3) resulting ones: |
41 |
| - --------------------- (3 resulting, overlap) |
42 |
| ----------------------- |
43 |
| -
|
44 |
| - ------------- |
45 |
| ----------------------- (3 resulting, inclusion) |
46 |
| -
|
47 |
| -------- ------- (2 resulting, disjoint) |
48 |
| -
|
49 |
| - ----------- (2 results, simple inclusion) |
50 |
| ------------------- |
51 |
| -
|
52 |
| -------|----- and vs = vs' (merge opportunity) |
53 |
| -*) |
54 |
| - (* merge opportunity. However, might be desirable to keep apart |
55 |
| - if vs = vs' andalso (d2 = d1'+1 orelse d1 = d2'+1) |
56 |
| - then trMerge' ((s, (Int.min (d1,d1'), Int.max (d2,d2')), vs), trs) |
57 |
| - else *) |
58 |
| - if d2 < d1' orelse d2' < d1 (* disjoint, continue merging *) |
59 |
| - then tr' :: trMerge' (tr, trs) |
60 |
| - else |
61 |
| - if d1 = d1' |
62 |
| - then if d2 = d2' (* identical ranges: *) |
63 |
| - then (s,(d1,d2), mergeUniq vs vs') :: trs |
64 |
| - else (* simple inclusion, and we know d2 <> d2' *) |
65 |
| - let val vs'' = if d2 < d2' then vs' else vs |
66 |
| - val lo = Int.min (d2, d2') |
67 |
| - in trMerge ((s,(d1,lo), mergeUniq vs vs') :: |
68 |
| - (s,(lo+1,Int.max (d2,d2')), vs'') :: trs) |
69 |
| - end |
70 |
| - else if d2 = d2' (* simple inclusion, d1 <> d1' *) |
71 |
| - then let val vs'' = if d1 < d1' then vs else vs' |
72 |
| - val hi = Int.max (d1, d1') |
73 |
| - in trMerge ((s,(Int.min (d1,d1'),hi), vs'') :: |
74 |
| - (s,(hi+1,d2), mergeUniq vs vs') :: trs) |
75 |
| - end |
76 |
| - else (* d1 <> d1', d2 <> d2' *) |
77 |
| - if d1 < d1' andalso d2' < d2 (* inclusion of tr' *) |
78 |
| - then trMerge ((s,(d1,d1'-1), vs) :: |
79 |
| - (s,(d1',d2'), mergeUniq vs vs') :: |
80 |
| - (s,(d2'+1,d2), vs) :: trs) |
81 |
| - else if d1' < d1 andalso d2 < d2' (* inclusion of tr *) |
82 |
| - then trMerge ((s,(d1',d1-1), vs') :: |
83 |
| - (s,(d1,d2), mergeUniq vs vs') :: |
84 |
| - (s,(d2+1,d2'), vs) :: trs) |
85 |
| - else (* real overlap *) |
86 |
| - let val v1s = if d1 < d1' then vs else vs' |
87 |
| - val v2s = if d2 < d2' then vs' else vs |
88 |
| - val (mid1,mid2) = (Int.max (d1,d1'),Int.min (d2,d2')) |
89 |
| - in trMerge ((s,(Int.min (d1,d1'),mid1-1), v1s) :: |
90 |
| - (s,(mid1,mid2), mergeUniq vs vs') :: |
91 |
| - (s,(mid2+1,Int.max (d2,d2')), v2s) :: trs ) |
92 |
| - end |
93 |
| - else tr' :: trMerge' (tr, trs) (* different observables *) |
94 |
| -and trMerge ts = foldl trMerge' [] ts |
95 |
| - |
96 |
| -(* triggersExp is where new triggers are added: *) |
97 |
| - |
98 |
| -(* returns a list of triggers (s,(t1,t2),vs) *) |
99 |
| -fun triggersExp (t1,t2) (BinOp ("<", e1, Obs(s,d))) |
100 |
| - = ([(s,(t1+d,t2+d), [evalR emptyEnv e1])] handle Fail _ => []) |
101 |
| - | triggersExp (t1,t2) (BinOp ("<", Obs(s,d), e1)) |
102 |
| - = ([(s,(t1+d,t2+d), [evalR emptyEnv e1])] handle Fail _ => []) |
103 |
| - | triggersExp (t1,t2) (BinOp ("|", e1, e2)) |
104 |
| - = trMerge ((triggersExp (t1,t2) e1) @ (triggersExp (t1,t2) e2)) |
105 |
| - | triggersExp (t1,t2) (UnOp ("not", e1)) = triggersExp (t1,t2) e1 |
106 |
| -(* *) |
107 |
| - | triggersExp ts exp = [] |
108 |
| - |
109 |
| - |
110 |
| -(* triggers : (int,int) -> contr -> trigger list (see above) |
111 |
| - where (int,int) is start+end relative date, starting at (0,0), |
112 |
| - expanded any time a construct introduces a "duration" |
113 |
| -*) |
114 |
| -fun triggers _ (Zero) = [] |
115 |
| - | triggers _ (TransfOne _) = [] |
116 |
| - | triggers ts (Scale (_,c)) = triggers ts c |
117 |
| - | triggers ts (Both (c1,c2)) = trMerge ((triggers ts c1) @ (triggers ts c2)) |
118 |
| - | triggers (t1,t2) (Transl (i,c)) = triggers (t1+i, t2+i) c |
119 |
| - | triggers ts (Let (v,e,c)) |
120 |
| - = raise Fail "clunky: need to consider v=e everywhere. How? Issue with translate, need an environment..." |
121 |
| - | triggers (t1,t2) (If(e,c1,c2)) |
122 |
| - = trMerge ((triggersExp (t1,t2) e) @ |
123 |
| - (triggers (t1,t2) c1) @ |
124 |
| - (triggers (t1,t2) c2)) |
125 |
| - | triggers (t1,t2) (CheckWithin (e,d,c1,c2)) |
126 |
| - = trMerge ((triggersExp (t1,t2+d) e) @ |
127 |
| - (triggers (t1,t2+d) c1) @ |
128 |
| - (triggers (t1+d, t2+d) c2)) |
| 1 | +(* this is a mosml script for development *) |
| 2 | + |
| 3 | +app load ["Real", "Int", "ContractBase", "Contract", "ContractTriggers" ]; |
| 4 | + |
| 5 | +open ContractBase Contract ContractTriggers; |
129 | 6 |
|
130 | 7 | (* copied *)
|
131 | 8 | infix !+! !-! !*! !<! !=! !|! ;
|
@@ -166,6 +43,39 @@ fun ppTriggers [] = ""
|
166 | 43 | ": " ^ (String.concatWith ", " (map Real.toString vs)) ^
|
167 | 44 | "\n" ^ ppTriggers rest
|
168 | 45 |
|
| 46 | +(* some test data *) |
| 47 | +infix !+! !-! !*! !<! !=! !|! ; |
| 48 | + |
| 49 | +load "Currency"; open Currency; |
| 50 | + |
| 51 | +fun M n = n*30 |
| 52 | +fun Y n = n*360 |
| 53 | + |
| 54 | +(* Barrier option on "Carlsberg" stock *) |
| 55 | +val equity = "Carlsberg" |
| 56 | +val maturity = M 3 |
| 57 | +val ex4if = |
| 58 | + let val strike = 50.0 |
| 59 | + val obs = obs(equity,0) |
| 60 | + in checkWithin (R strike !<! obs, maturity, |
| 61 | + scale(obs !-! R strike, |
| 62 | + transfOne(EUR,"you","me")), |
| 63 | + zero) |
| 64 | + end |
| 65 | + |
| 66 | +fun mkOpt i s = |
| 67 | + let val strike = s |
| 68 | + val obs = obs(equity,0) |
| 69 | + in checkWithin (R strike !<! obs, M i, |
| 70 | + scale(obs !-! R strike, |
| 71 | + transfOne(EUR,"you","me")), |
| 72 | + zero) |
| 73 | + end |
| 74 | + |
| 75 | +val test1 = all (List.tabulate (3, fn di => mkOpt 3 (40.0 + real di))) |
| 76 | +val test2 = all (List.tabulate (6, fn i => mkOpt i (real i + 42.0))) |
| 77 | +val test3 = all [test1,test2] |
| 78 | + |
169 | 79 | val () = (print ("Carlsberg barrier options (settled):\n" ^ ppContr test3);
|
170 | 80 | print "\nTrigger values:\n";
|
171 | 81 | print (ppTriggers (triggers (0,10) test3)))
|
|
0 commit comments