|
| 1 | + |
| 2 | +-- contracts from Lexifi, used with the generic pricing engine |
| 3 | + |
| 4 | +module LexifiContracts |
| 5 | + where |
| 6 | + |
| 7 | +-- MEMO: clean up imports and exports of umbrella file "Contract.hs" |
| 8 | +import Contract |
| 9 | +import Contract.Type |
| 10 | +import Contract.Date |
| 11 | +import Contract.Expr |
| 12 | + |
| 13 | +-- European option on DJ_Eurostoxx_50, starting |
| 14 | +european :: MContract |
| 15 | +european = (start, -- 2011-12-09 |
| 16 | + transl duration -- on 2012-11-30 |
| 17 | + (scale (maxx 0 (obs (idx,0) - strike)) |
| 18 | + (transfOne EUR "them" "us"))) |
| 19 | + where start = at "2011-12-09" :: Date |
| 20 | + duration = dateDiff start (at "2012-11-30") |
| 21 | + -- MEMO this fct. should be called "daysBetween" |
| 22 | + idx = "DJ_Eurostoxx_50" |
| 23 | + strike = 4000 |
| 24 | + |
| 25 | +-- worst-off contract on five fixed dates (chain of iff) |
| 26 | +worstOff :: MContract |
| 27 | +worstOff = (start, foldr mkDateCheck endCase (zip dDiffs premiums)) |
| 28 | + where start = at "2012-01-27" |
| 29 | + dates = map (\s -> at (show s ++ "-01-27")) [2013..2017] |
| 30 | + dDiffs = zipWith dateDiff (start:dates) dates |
| 31 | + premiums = [1150.0, 1300.0, 1450.0, 1600.0, 1750] |
| 32 | + -- on the five dates (offset): one below initial spot => pay premium |
| 33 | + mkDateCheck (offset, premium) cont |
| 34 | + = transl offset $ iff barrier (collectEUR premium) cont |
| 35 | + barrier = nott (foldl1 minn (zipWith mkDiff idxs spots) !<! 0) |
| 36 | + -- MEMO we should have <= , > and >= as smart constructors |
| 37 | + mkDiff idx spot = obs (idx, 0) - spot |
| 38 | + -- MEMO we should have RealE division. |
| 39 | + idxs = [ "DJ_Eurostoxx_50", "Nikkei_225", "SP_500" ] |
| 40 | + spots = [ 3758.05, 11840, 1200 ] |
| 41 | + -- if end (date 5) reached: pay 1000 if all above 0.75, |
| 42 | + -- otherwise pay the fraction of the worst (HOW? no division) |
| 43 | + endCase = iff (allAbove 0.75) (collectEUR 1000) |
| 44 | + (collectEUR (1000 * minRatio)) |
| 45 | + minRatio = error "cannot define minimum ratio without division" |
| 46 | + allAbove d = nott (foldl1 (!|!) |
| 47 | + (zipWith (fractionSmaller d) idxs spots)) |
| 48 | + {- 0.75 < minimum [ obs(id,0) / sp | (id, sp) <- zip idxs spots ] |
| 49 | + <==> |
| 50 | + and [ 0.75 * sp !<! obs (id, 0) | (id, sp) <- zip idxs spots ] |
| 51 | + <==> |
| 52 | + not (or [obs(id, 0) !<! 0.75 * sp | (id, sp) <- zip idxs spots]) -} |
| 53 | + fractionSmaller d idx spot = obs(idx, 0) !<! d * spot |
| 54 | + collectEUR amount = scale amount (transfOne EUR "them" "us") |
| 55 | + |
| 56 | +-- |
0 commit comments