import Control.Monad import Data.List 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 -- assumes cRRA = 1 or is away from 1 | cRRA == 1 = exp (q * log dn + p * log up) | otherwise = (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 soCE alpha dn up = siCE 0.5 alpha (hiCE dn up) (loCE dn up) -- second-order EU CE -- Time-t consumption is a list ordered from lowest to highest consumption scenarios. -- The consumption tree is the list of lists: -- [time-T consumption, time-(T-1) consumption, ... , time-0 consumption] -- Function to move forward in time one step on the consumption tree: fwd :: [Double] -> [Double] fwd xs = head xs * dnGrowth : map (*upGrowth) xs -- Construct the constant volatility consumption tree constVolTree :: [[Double]] constVolTree = foldl' (\css _ -> fwd (head css) : css) [[c0]] [1..nPeriods] -- Computation representing the back-recursion on the consumption tree as a function of alpha -- The terminal consumption (head of list) is assumed equal to the continuation utility bwd :: Double -> [[Double]] -> [[Double]] bwd alpha css = case css of _:[] -> css vs:cs:rest -> uts:rest where ces = zipWith (soCE alpha) vs (tail vs) uts = zipWith agg cs ces timeZeroUtility alpha = u where [[u]] = foldl' (\css _ -> bwd alpha css) constVolTree [1..nPeriods] main = forM_ alphaValues (\alpha -> do let u = timeZeroUtility alpha putStrLn $ "For alpha = " ++ show alpha ++ " the time-zero utility is " ++ show u) -- to compile, type: ghc --make -O2 funcRec.hs