import Control.Monad alphaValues = [2.0, 20.0, 40.0] beta = 0.03 gamma = 2.0 delta = 1/1.5 muHi = 0.05 -- optimistic drift muLo = 0.00 -- pessimistic drift sigma = 0.03 nPeriods = 520 :: Int -- total number of periods h = 10.0 / (fromIntegral nPeriods) c0 = 100.0 -- initial consumption pHi = (1 + (muHi/sigma)*(sqrt h)) / 2 pLo = (1 + (muLo/sigma)*(sqrt h)) / 2 upGrowth = exp (sigma*(sqrt h)) dnGrowth = 1 / upGrowth discount = exp (-beta * h) siCE p cRRA (dn,up) = if power == 1 then exp (q*(log dn) + p*(log up)) else (q*(dn**power)+p*(up**power))**(1/power) where power = 1 - cRRA; q = 1 - p agg = siCE discount delta -- time aggregator hiCE = siCE pHi gamma -- optimistic EU CE loCE = siCE pLo gamma -- pessimistic EU CE -- Consumption values at a given time are represented as a list, -- with the head corresponding to least consumption (bottom of the tree) -- Function to move forward one step on the consumption tree: fwd xs = ((head xs)*dnGrowth):(map (*upGrowth) xs) -- Function to move backward one stepn the consumption tree: bwd (x:xs) = map (/upGrowth) xs -- Forward recursion to get terminal consumption values: cVals acc t = if t <= 0 then acc else cVals (fwd acc) (t-1) csLast = cVals [c0] (nPeriods-1) -- consumption at beginning of final period -- Function computing time-zero utility as a function of alpha. -- The tail-recursion uses accumulator acc = (cs,vs), -- where cs lists beginning-of-period consumption -- and vs lists end-of-period continuation utility. utility alpha = timeZeroUtility where soCE (x,y) = siCE 0.5 alpha (hiCE (x,y), loCE (x,y)) backStep (cs,vs) = ( bwd cs, map agg $ zip cs $ map soCE $ zip vs (tail vs)) uVals acc time2go = if time2go == 1 then snd (backStep acc) else uVals (backStep acc) (time2go - 1) [timeZeroUtility] = uVals (csLast, fwd csLast) nPeriods main = do forM_ alphaValues (\a -> do let alpha = show a let util = show (utility a) putStrLn $ "For alpha = " ++ alpha ++ " the time-zero utility is " ++ util)