Hastructure-0.45.0: src/AssetClass/FixedAsset.hs
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE InstanceSigs #-}
module AssetClass.FixedAsset
()
where
import qualified Data.Time as T
import Data.Ratio
import Data.Aeson hiding (json)
import Language.Haskell.TH
import Data.Maybe
import Data.List
import Data.Aeson.TH
import qualified Data.Map as Map
import Data.Aeson.Types
import GHC.Generics
import qualified Assumptions as A
import Types hiding (startDate)
import Lib
import Util
import DateUtil
import qualified Cashflow as CF
import AssetClass.AssetBase
import Debug.Trace
import AssetClass.AssetCashflow
import qualified Asset as Ast
import Asset (Asset(projCashflow))
import Assumptions (AssetDelinqPerfAssumption(DummyDelinqAssump))
debug = flip trace
-- life time schedule amortization amount list
calcAmortAmt ::FixedAsset -> Either String [Balance]
calcAmortAmt fa@(FixedAsset fai@FixedAssetInfo{originBalance=ob, accRule=ar, originTerm=ot
,residualBalance=rb ,capacity=cap} b rt)
= case ar of
StraightLine -> Right $ replicate ot $ divideBI (b-rb) rt
DecliningBalance ->
let
amortizeRate = realToFrac $ 2 % ot
futureBals' = scaleByFstElement b $ lastN (succ rt) $ scanl (\acc r -> acc * (1 - r)) ob (replicate ot amortizeRate)
-- straigh lines
futureBals'' = scanl
(\acc (bal',amt',rt') ->
(acc - (max amt' (divideBI (acc - rb) (rt - rt'))))
)
(head futureBals')
(zip3 futureBals' (diffNum futureBals') [0..succ rt])
in
Right (diffNum futureBals'')
_ -> Left ("Not implemented for depreciation rule"++show ar)
calcAmortBals ::FixedAsset -> Either String [Balance]
calcAmortBals fa@(FixedAsset fai@FixedAssetInfo{originBalance=ob, accRule=ar, originTerm=ot
,residualBalance=rb ,capacity=cap} b rt)
= do
bals <- calcAmortAmt fa
return $ scanl (-) ob bals
instance Ast.Asset FixedAsset where
calcCashflow fa@(FixedAsset {}) asOfDay _ =
fst <$> projCashflow fa asOfDay (A.FixedAssetAssump (mkTs []) (mkTs []) Nothing, A.DummyDelinqAssump, A.DummyDefaultAssump) Nothing
getCurrentBal fa@(FixedAsset fai@FixedAssetInfo{originBalance=ob, accRule=ar, originTerm=ot
,residualBalance=rb ,capacity=cap} curBal rt)
= curBal
resetToOrig fa@(FixedAsset fai@FixedAssetInfo{originBalance=ob, accRule=ar, originTerm=ot
,residualBalance=rb ,capacity=cap} b rt)
= FixedAsset fai b ot
getPaymentDates
(FixedAsset fo@FixedAssetInfo{startDate=sd ,period=p,originTerm=ot} _ rt)
extra
= genDates sd p (ot+extra)
projCashflow fa@(FixedAsset fai@FixedAssetInfo{originBalance=ob, accRule=ar, originTerm=ot
,residualBalance=rb ,capacity=cap} curBalance rt)
asOfDay
(A.FixedAssetAssump uCurve pCurve mExtPeriods,_,_)
_
= let
extPeriods = fromMaybe 0 mExtPeriods
cfLength = rt + extPeriods
pdates = lastN cfLength $ Ast.getPaymentDates fa extPeriods
capacityCaps = case cap of
FixedCapacity b -> replicate cfLength b
CapacityByTerm tbl -> lastN cfLength $ concat [ replicate i b | (i,b) <- tbl ] ++ (replicate extPeriods (snd (last tbl)))
utilsVec = getValByDates uCurve Inc pdates
units = [ mulBR c u | (u,c) <- zip utilsVec capacityCaps]
prices = getValByDates pCurve Inc pdates
cash = [ mulBR u p | (p,u) <- zip prices units]
in
do
scheduleAmt <- calcAmortAmt fa
let amortizedBals = lastN cfLength $ scheduleAmt ++ replicate extPeriods 0
let scheduleBals = tail $ scanl (-) curBalance (amortizedBals ++ [0])
let cumuDep = ob - curBalance
let cumuDepreciation = tail $ scanl (+) cumuDep amortizedBals
let txns = zipWith6 CF.FixedFlow pdates scheduleBals amortizedBals cumuDepreciation units cash
let futureTxns = cutBy Inc Future asOfDay txns
let begBal = CF.buildBegBal futureTxns
return $ (CF.CashFlowFrame (begBal,asOfDay,Nothing) $ futureTxns, Map.empty)