{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE DeriveGeneric #-}
module AssetClass.Loan
(projectLoanFlow,updateOriginDate)
where
import qualified Data.Time as T
import qualified Cashflow as CF
import qualified Assumptions as A
import InterestRate
import Asset
import Lib
import Util
import DateUtil
import Types
import qualified Data.Map as Map
import Data.List
import Data.Maybe
import Data.Aeson hiding (json)
import Language.Haskell.TH
import Data.Aeson.TH
import Data.Aeson.Types
import GHC.Generics
import AssetClass.AssetBase
import AssetClass.AssetCashflow
import Debug.Trace
import Assumptions (AssetDefaultAssumption(DefaultCDR))
import qualified Asset as A
import Control.Lens hiding (element)
import Control.Lens.TH
debug :: c -> String -> c
debug = (String -> c -> c) -> c -> String -> c
forall a b c. (a -> b -> c) -> b -> a -> c
flip String -> c -> c
forall a. String -> a -> a
trace
projectLoanFlow :: ((Balance,Int,IRate), Balance, Date, AmortPlan, DayCount, IRate, Rational) -> (Dates, [DefaultRate],[PrepaymentRate],[IRate],[Int]) -> ([CF.TsRow],Rational)
projectLoanFlow :: ((Recovery, Int, IRate), Recovery, Date, AmortPlan, DayCount,
IRate, Rational)
-> (Dates, [Rational], [Rational], [IRate], [Int])
-> ([TsRow], Rational)
projectLoanFlow ((Recovery
originBal,Int
ot,IRate
or), Recovery
startBal, Date
lastPayDate, AmortPlan
pt, DayCount
dc,IRate
startRate, Rational
begFactor) (Dates
cfDates,[Rational]
defRates,[Rational]
ppyRates,[IRate]
rateVector,[Int]
remainTerms) =
let
initRow :: TsRow
initRow = Date
-> Recovery
-> Recovery
-> Recovery
-> Recovery
-> Recovery
-> Recovery
-> Recovery
-> IRate
-> Maybe CumulativeStat
-> TsRow
CF.LoanFlow Date
lastPayDate Recovery
startBal Recovery
0.0 Recovery
0.0 Recovery
0.0 Recovery
0.0 Recovery
0.0 Recovery
0.0 IRate
startRate Maybe CumulativeStat
forall a. Maybe a
Nothing
in
(([TsRow], Rational)
-> (Date, Rational, Rational, IRate, Int) -> ([TsRow], Rational))
-> ([TsRow], Rational)
-> [(Date, Rational, Rational, IRate, Int)]
-> ([TsRow], Rational)
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl
(\([TsRow]
acc,Rational
factor) (Date
pDate, Rational
ppyRate, Rational
defRate, IRate
intRate, Int
rt)
-> let
begBal :: Recovery
begBal = Getting Recovery TsRow Recovery -> TsRow -> Recovery
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting Recovery TsRow Recovery
Lens' TsRow Recovery
CF.tsRowBalance ([TsRow] -> TsRow
forall a. HasCallStack => [a] -> a
last [TsRow]
acc)
lastPaidDate :: Date
lastPaidDate = TsRow -> Date
forall ts. TimeSeries ts => ts -> Date
getDate ([TsRow] -> TsRow
forall a. HasCallStack => [a] -> a
last [TsRow]
acc)
newDefault :: Recovery
newDefault = Recovery -> Rational -> Recovery
mulBR Recovery
begBal Rational
defRate
newPrepay :: Recovery
newPrepay = Recovery -> Rational -> Recovery
mulBR (Recovery
begBal Recovery -> Recovery -> Recovery
forall a. Num a => a -> a -> a
- Recovery
newDefault) Rational
ppyRate
intBal :: Recovery
intBal = Recovery
begBal Recovery -> Recovery -> Recovery
forall a. Num a => a -> a -> a
- Recovery
newDefault Recovery -> Recovery -> Recovery
forall a. Num a => a -> a -> a
- Recovery
newPrepay
newFactor :: Rational
newFactor = Rational
factor Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* (Rational
1Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
-Rational
defRate) Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* (Rational
1Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
- Rational
ppyRate )
newInt :: Recovery
newInt = case (Int
rt,AmortPlan
pt) of
(Int
0,AmortPlan
F_P) -> Recovery
0
(Int
_,AmortPlan
F_P) -> Recovery -> Rational -> Recovery
mulBR (Recovery -> IRate -> Recovery
mulBIR Recovery
originBal IRate
or) Rational
newFactor
(Int, AmortPlan)
_ -> Recovery -> Date -> Date -> IRate -> DayCount -> Recovery
calcInt Recovery
intBal Date
lastPaidDate Date
pDate IRate
intRate DayCount
dc
newPrin :: Recovery
newPrin = case (Int
rt,AmortPlan
pt) of
(Int
1,AmortPlan
I_P) -> Recovery
intBal
(Int
1,AmortPlan
F_P) -> Recovery
intBal
(Int
0,AmortPlan
F_P) -> Recovery
0
(Int
_,AmortPlan
F_P) -> Recovery -> Rational -> Recovery
mulBR (Recovery -> Int -> Recovery
divideBI Recovery
intBal Int
rt) Rational
newFactor
(Int
_,AmortPlan
I_P) -> Recovery
0
(Int
0,ScheduleRepayment Ts
cf Maybe DatePattern
_) -> Recovery
intBal
(Int
_,ScheduleRepayment Ts
cf Maybe DatePattern
_) ->
let
projAmt :: Recovery
projAmt = Rational -> Recovery
forall a. Fractional a => Rational -> a
fromRational (Rational -> Recovery) -> Rational -> Recovery
forall a b. (a -> b) -> a -> b
$ Ts -> CutoffType -> Date -> Rational
getValByDate Ts
cf CutoffType
Inc Date
pDate
in
if Int
rt Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1 then
Recovery
intBal
else
Recovery -> Rational -> Recovery
mulBR Recovery
projAmt Rational
newFactor
(Int, AmortPlan)
_ -> String -> Recovery
forall a. HasCallStack => String -> a
error (String -> Recovery) -> String -> Recovery
forall a b. (a -> b) -> a -> b
$ String
"failed to match Loan Project newPrin"String -> String -> String
forall a. [a] -> [a] -> [a]
++ (Int, AmortPlan) -> String
forall a. Show a => a -> String
show (Int
rt,AmortPlan
pt)
endBal :: Recovery
endBal = Recovery
intBal Recovery -> Recovery -> Recovery
forall a. Num a => a -> a -> a
- Recovery
newPrin
in
([TsRow]
acc [TsRow] -> [TsRow] -> [TsRow]
forall a. [a] -> [a] -> [a]
++ [Date
-> Recovery
-> Recovery
-> Recovery
-> Recovery
-> Recovery
-> Recovery
-> Recovery
-> IRate
-> Maybe CumulativeStat
-> TsRow
CF.LoanFlow Date
pDate Recovery
endBal Recovery
newPrin Recovery
newInt Recovery
newPrepay Recovery
newDefault Recovery
0.0 Recovery
0.0 IRate
intRate Maybe CumulativeStat
forall a. Maybe a
Nothing]
,Rational
newFactor))
([TsRow
initRow],Rational
begFactor)
(Dates
-> [Rational]
-> [Rational]
-> [IRate]
-> [Int]
-> [(Date, Rational, Rational, IRate, Int)]
forall a b c d e.
[a] -> [b] -> [c] -> [d] -> [e] -> [(a, b, c, d, e)]
zip5 Dates
cfDates [Rational]
ppyRates [Rational]
defRates [IRate]
rateVector [Int]
remainTerms)
instance Asset Loan where
calcCashflow :: Loan
-> Date -> Maybe [RateAssumption] -> Either String CashFlowFrame
calcCashflow pl :: Loan
pl@(PersonalLoan (LoanOriginalInfo Recovery
ob RateType
or Int
ot Period
p Date
sd AmortPlan
ptype Maybe Obligor
_) Recovery
bal IRate
rate Int
term Status
_ ) Date
asOfDay Maybe [RateAssumption]
mRates
= (CashFlowFrame, Map CutoffFields Recovery) -> CashFlowFrame
forall a b. (a, b) -> a
fst ((CashFlowFrame, Map CutoffFields Recovery) -> CashFlowFrame)
-> Either String (CashFlowFrame, Map CutoffFields Recovery)
-> Either String CashFlowFrame
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>
Loan
-> Date
-> AssetPerf
-> Maybe [RateAssumption]
-> Either String (CashFlowFrame, Map CutoffFields Recovery)
forall a.
Asset a =>
a
-> Date
-> AssetPerf
-> Maybe [RateAssumption]
-> Either String (CashFlowFrame, Map CutoffFields Recovery)
projCashflow Loan
pl
Date
asOfDay
(Maybe AssetDefaultAssumption
-> Maybe AssetPrepayAssumption
-> Maybe RecoveryAssumption
-> Maybe ExtraStress
-> AssetPerfAssumption
A.LoanAssump Maybe AssetDefaultAssumption
forall a. Maybe a
Nothing Maybe AssetPrepayAssumption
forall a. Maybe a
Nothing Maybe RecoveryAssumption
forall a. Maybe a
Nothing Maybe ExtraStress
forall a. Maybe a
Nothing
,AssetDelinqPerfAssumption
A.DummyDelinqAssump
,AssetDefaultedPerfAssumption
A.DummyDefaultAssump)
Maybe [RateAssumption]
mRates
getCurrentBal :: Loan -> Recovery
getCurrentBal pl :: Loan
pl@(PersonalLoan (LoanOriginalInfo Recovery
ob RateType
or Int
ot Period
p Date
sd AmortPlan
ptype Maybe Obligor
_) Recovery
_bal IRate
_rate Int
_term Status
_ )
= Recovery
_bal
getOriginRate :: Loan -> IRate
getOriginRate pl :: Loan
pl@(PersonalLoan (LoanOriginalInfo Recovery
ob RateType
or Int
ot Period
p Date
sd AmortPlan
ptype Maybe Obligor
_) Recovery
_bal IRate
_rate Int
_term Status
_ )
= case RateType
or of
Fix DayCount
_ IRate
_r -> IRate
_r
Floater DayCount
_ Index
_ IRate
_ IRate
_r DatePattern
_ RateFloor
_ RateFloor
_ Maybe (RoundingBy IRate)
_ -> IRate
_r
getCurrentRate :: Loan -> IRate
getCurrentRate pl :: Loan
pl@(PersonalLoan (LoanOriginalInfo Recovery
ob RateType
or Int
ot Period
p Date
sd AmortPlan
ptype Maybe Obligor
_) Recovery
_bal IRate
_rate Int
_term Status
_ )
= IRate
_rate
getOriginBal :: Loan -> Recovery
getOriginBal pl :: Loan
pl@(PersonalLoan (LoanOriginalInfo Recovery
ob RateType
_ Int
_ Period
_ Date
_ AmortPlan
_ Maybe Obligor
_) Recovery
_ IRate
_ Int
_ Status
_ ) = Recovery
ob
isDefaulted :: Loan -> Bool
isDefaulted pl :: Loan
pl@(PersonalLoan OriginalInfo
_ Recovery
_ IRate
_ Int
_ (Defaulted Maybe Date
_)) = Bool
True
isDefaulted PersonalLoan {} = Bool
False
getOriginInfo :: Loan -> OriginalInfo
getOriginInfo (PersonalLoan OriginalInfo
oi Recovery
cb IRate
cr Int
rt Status
st) = OriginalInfo
oi
getOriginDate :: Loan -> Date
getOriginDate (PersonalLoan (LoanOriginalInfo Recovery
ob RateType
or Int
ot Period
p Date
sd AmortPlan
I_P Maybe Obligor
_) Recovery
cb IRate
cr Int
rt Status
st ) = Date
sd
resetToOrig :: Loan -> Loan
resetToOrig m :: Loan
m@(PersonalLoan (LoanOriginalInfo Recovery
ob RateType
or Int
ot Period
p Date
sd AmortPlan
I_P Maybe Obligor
obr) Recovery
cb IRate
cr Int
rt Status
st )
= OriginalInfo -> Recovery -> IRate -> Int -> Status -> Loan
PersonalLoan (Recovery
-> RateType
-> Int
-> Period
-> Date
-> AmortPlan
-> Maybe Obligor
-> OriginalInfo
LoanOriginalInfo Recovery
ob RateType
or Int
ot Period
p Date
sd AmortPlan
I_P Maybe Obligor
obr) Recovery
ob (Loan -> IRate
forall a. Asset a => a -> IRate
getOriginRate Loan
m) Int
ot Status
st
getRemainTerms :: Loan -> Int
getRemainTerms (PersonalLoan (LoanOriginalInfo Recovery
ob RateType
or Int
ot Period
p Date
sd AmortPlan
I_P Maybe Obligor
_) Recovery
cb IRate
cr Int
rt Status
st ) = Int
rt
updateOriginDate :: Loan -> Date -> Loan
updateOriginDate (PersonalLoan (LoanOriginalInfo Recovery
ob RateType
or Int
ot Period
p Date
sd AmortPlan
I_P Maybe Obligor
obr) Recovery
cb IRate
cr Int
rt Status
st ) Date
nd
= OriginalInfo -> Recovery -> IRate -> Int -> Status -> Loan
PersonalLoan (Recovery
-> RateType
-> Int
-> Period
-> Date
-> AmortPlan
-> Maybe Obligor
-> OriginalInfo
LoanOriginalInfo Recovery
ob RateType
or Int
ot Period
p Date
nd AmortPlan
I_P Maybe Obligor
obr) Recovery
cb IRate
cr Int
rt Status
st
getPaymentDates :: Loan -> Int -> Dates
getPaymentDates pl :: Loan
pl@(PersonalLoan (LoanOriginalInfo Recovery
ob RateType
_ Int
ot Period
p Date
sd (ScheduleRepayment Ts
ts Maybe DatePattern
mDp) Maybe Obligor
_) Recovery
_bal IRate
_rate Int
_term Status
_ ) Int
extra
= let
pdays :: Dates
pdays = Ts -> Dates
getTsDates Ts
ts
extraDates :: Dates
extraDates = DatePattern -> CutoffType -> Date -> Int -> Dates
genSerialDates (DatePattern -> Maybe DatePattern -> DatePattern
forall a. a -> Maybe a -> a
fromMaybe DatePattern
MonthEnd Maybe DatePattern
mDp) CutoffType
Inc (Dates -> Date
forall a. HasCallStack => [a] -> a
last Dates
pdays) Int
extra
in
Dates
pdays Dates -> Dates -> Dates
forall a. [a] -> [a] -> [a]
++ Dates
extraDates
getPaymentDates pl :: Loan
pl@(PersonalLoan (LoanOriginalInfo Recovery
ob RateType
_ Int
ot Period
p Date
sd AmortPlan
_ Maybe Obligor
_) Recovery
_bal IRate
_rate Int
_term Status
_ ) Int
extra
= Date -> Period -> Int -> Dates
genDates Date
sd Period
p (Int
otInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
extra)
projCashflow :: Loan
-> Date
-> AssetPerf
-> Maybe [RateAssumption]
-> Either String (CashFlowFrame, Map CutoffFields Recovery)
projCashflow pl :: Loan
pl@(PersonalLoan (LoanOriginalInfo Recovery
ob RateType
or Int
ot Period
p Date
sd AmortPlan
prinPayType Maybe Obligor
_) Recovery
cb IRate
cr Int
rt Status
Current)
Date
asOfDay
(A.LoanAssump Maybe AssetDefaultAssumption
defaultAssump Maybe AssetPrepayAssumption
prepayAssump Maybe RecoveryAssumption
recoveryAssump Maybe ExtraStress
ams,AssetDelinqPerfAssumption
_,AssetDefaultedPerfAssumption
_)
Maybe [RateAssumption]
mRate
= let
recoveryLag :: Int
recoveryLag = Int
-> (RecoveryAssumption -> Int) -> Maybe RecoveryAssumption -> Int
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Int
0 RecoveryAssumption -> Int
getRecoveryLag Maybe RecoveryAssumption
recoveryAssump
Date
lastPayDate:Dates
cfDates = Int -> Dates -> Dates
forall a. Int -> [a] -> [a]
lastN (Int
rt Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
recoveryLag Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) (Dates -> Dates) -> Dates -> Dates
forall a b. (a -> b) -> a -> b
$ Date
sdDate -> Dates -> Dates
forall a. a -> [a] -> [a]
:Loan -> Int -> Dates
forall a. Asset a => a -> Int -> Dates
getPaymentDates Loan
pl Int
recoveryLag
in
do
[IRate]
rateVector <- IRate
-> RateType
-> Maybe [RateAssumption]
-> Dates
-> Either String [IRate]
A.projRates IRate
cr RateType
or Maybe [RateAssumption]
mRate Dates
cfDates
[Rational]
ppyRates <- Loan
-> Dates -> Maybe AssetPrepayAssumption -> Either String [Rational]
forall b.
Asset b =>
b
-> Dates -> Maybe AssetPrepayAssumption -> Either String [Rational]
A.buildPrepayRates Loan
pl (Date
lastPayDateDate -> Dates -> Dates
forall a. a -> [a] -> [a]
:Dates
cfDates) Maybe AssetPrepayAssumption
prepayAssump
[Rational]
defRates <- Loan
-> Dates
-> Maybe AssetDefaultAssumption
-> Either String [Rational]
forall b.
Asset b =>
b
-> Dates
-> Maybe AssetDefaultAssumption
-> Either String [Rational]
A.buildDefaultRates Loan
pl (Date
lastPayDateDate -> Dates -> Dates
forall a. a -> [a] -> [a]
:Dates
cfDates) Maybe AssetDefaultAssumption
defaultAssump
let dc :: DayCount
dc = RateType -> DayCount
getDayCount RateType
or
let remainTerms :: [Int]
remainTerms = [Int] -> [Int]
forall a. [a] -> [a]
reverse ([Int] -> [Int]) -> [Int] -> [Int]
forall a b. (a -> b) -> a -> b
$ Int -> Int -> [Int]
forall a. Int -> a -> [a]
replicate Int
recoveryLag Int
0 [Int] -> [Int] -> [Int]
forall a. [a] -> [a] -> [a]
++ [Int
0..Int
rt]
let initFactor :: Rational
initFactor = case AmortPlan
prinPayType of
ScheduleRepayment Ts
ts Maybe DatePattern
_ ->
let
scheduleBals :: [Recovery]
scheduleBals = (Recovery -> Recovery -> Recovery)
-> Recovery -> [Recovery] -> [Recovery]
forall b a. (b -> a -> b) -> b -> [a] -> [b]
scanl (-) Recovery
ob ([Recovery] -> [Recovery]) -> [Recovery] -> [Recovery]
forall a b. (a -> b) -> a -> b
$ Rational -> Recovery
forall a. Fractional a => Rational -> a
fromRational (Rational -> Recovery) -> [Rational] -> [Recovery]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ts -> [Rational]
getTsVals Ts
ts
in
Recovery -> Recovery -> Rational
divideBB Recovery
cb ([Recovery]
scheduleBals[Recovery] -> Int -> Recovery
forall a. HasCallStack => [a] -> Int -> a
!!(Int
ot Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
rt))
AmortPlan
_ -> Rational
1.0
let ([TsRow]
txns,Rational
_) = ((Recovery, Int, IRate), Recovery, Date, AmortPlan, DayCount,
IRate, Rational)
-> (Dates, [Rational], [Rational], [IRate], [Int])
-> ([TsRow], Rational)
projectLoanFlow ((Recovery
ob,Int
ot,Loan -> IRate
forall a. Asset a => a -> IRate
getOriginRate Loan
pl), Recovery
cb,Date
lastPayDate,AmortPlan
prinPayType,DayCount
dc,IRate
cr,Rational
initFactor) (Dates
cfDates,[Rational]
defRates,[Rational]
ppyRates,[IRate]
rateVector,[Int]
remainTerms)
let ([TsRow]
futureTxns,Map CutoffFields Recovery
historyM) = Date -> [TsRow] -> ([TsRow], Map CutoffFields Recovery)
CF.cutoffTrs Date
asOfDay ([TsRow] -> Maybe RecoveryAssumption -> [TsRow]
patchLossRecovery [TsRow]
txns Maybe RecoveryAssumption
recoveryAssump)
let begBal :: Recovery
begBal = [TsRow] -> Recovery
CF.buildBegBal [TsRow]
futureTxns
(CashFlowFrame, Map CutoffFields Recovery)
-> Either String (CashFlowFrame, Map CutoffFields Recovery)
forall a. a -> Either String a
forall (m :: * -> *) a. Monad m => a -> m a
return ((CashFlowFrame, Map CutoffFields Recovery)
-> Either String (CashFlowFrame, Map CutoffFields Recovery))
-> (CashFlowFrame, Map CutoffFields Recovery)
-> Either String (CashFlowFrame, Map CutoffFields Recovery)
forall a b. (a -> b) -> a -> b
$ (Maybe ExtraStress -> CashFlowFrame -> CashFlowFrame
applyHaircut Maybe ExtraStress
ams (BeginStatus -> [TsRow] -> CashFlowFrame
CF.CashFlowFrame (Recovery
begBal,Date
asOfDay,Maybe Recovery
forall a. Maybe a
Nothing) [TsRow]
futureTxns), Map CutoffFields Recovery
historyM)
projCashflow m :: Loan
m@(PersonalLoan (LoanOriginalInfo Recovery
ob RateType
or Int
ot Period
p Date
sd AmortPlan
prinPayType Maybe Obligor
_) Recovery
cb IRate
cr Int
rt (Defaulted (Just Date
defaultedDate)))
Date
asOfDay
(AssetPerfAssumption
_,AssetDelinqPerfAssumption
_,A.DefaultedRecovery Rational
rr Int
lag [Rational]
timing)
Maybe [RateAssumption]
_
= let
(Dates
cf_dates1,Dates
cf_dates2) = Int -> Dates -> (Dates, Dates)
forall a. Int -> [a] -> ([a], [a])
splitAt (Int -> Int
forall a. Enum a => a -> a
pred Int
lag) (Dates -> (Dates, Dates)) -> Dates -> (Dates, Dates)
forall a b. (a -> b) -> a -> b
$ Date -> Period -> Int -> Dates
genDates Date
defaultedDate Period
p (Int
lagInt -> Int -> Int
forall a. Num a => a -> a -> a
+ [Rational] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Rational]
timing)
beforeRecoveryTxn :: [TsRow]
beforeRecoveryTxn = [ Date
-> Recovery
-> Recovery
-> Recovery
-> Recovery
-> Recovery
-> Recovery
-> Recovery
-> IRate
-> Maybe CumulativeStat
-> TsRow
CF.LoanFlow Date
d Recovery
cb Recovery
0 Recovery
0 Recovery
0 Recovery
0 Recovery
0 Recovery
0 IRate
cr Maybe CumulativeStat
forall a. Maybe a
Nothing| Date
d <- Dates
cf_dates1 ]
recoveries :: [Recovery]
recoveries = Recovery -> Rational -> [Rational] -> [Recovery]
calcRecoveriesFromDefault Recovery
cb Rational
rr [Rational]
timing
_txns :: [TsRow]
_txns = [ Date
-> Recovery
-> Recovery
-> Recovery
-> Recovery
-> Recovery
-> Recovery
-> Recovery
-> IRate
-> Maybe CumulativeStat
-> TsRow
CF.LoanFlow Date
d Recovery
0 Recovery
0 Recovery
0 Recovery
0 Recovery
0 Recovery
r Recovery
0 IRate
cr Maybe CumulativeStat
forall a. Maybe a
Nothing | (Date
d,Recovery
r) <- Dates -> [Recovery] -> [(Date, Recovery)]
forall a b. [a] -> [b] -> [(a, b)]
zip Dates
cf_dates2 [Recovery]
recoveries ]
([TsRow]
_, [TsRow]
txns) = [TsRow] -> Date -> SplitType -> ([TsRow], [TsRow])
forall a. TimeSeries a => [a] -> Date -> SplitType -> ([a], [a])
splitByDate ([TsRow]
beforeRecoveryTxn[TsRow] -> [TsRow] -> [TsRow]
forall a. [a] -> [a] -> [a]
++[TsRow]
_txns) Date
asOfDay SplitType
EqToRight
([TsRow]
futureTxns,Map CutoffFields Recovery
historyM) = Date -> [TsRow] -> ([TsRow], Map CutoffFields Recovery)
CF.cutoffTrs Date
asOfDay [TsRow]
txns
begBal :: Recovery
begBal = [TsRow] -> Recovery
CF.buildBegBal [TsRow]
futureTxns
in
(CashFlowFrame, Map CutoffFields Recovery)
-> Either String (CashFlowFrame, Map CutoffFields Recovery)
forall a b. b -> Either a b
Right ((CashFlowFrame, Map CutoffFields Recovery)
-> Either String (CashFlowFrame, Map CutoffFields Recovery))
-> (CashFlowFrame, Map CutoffFields Recovery)
-> Either String (CashFlowFrame, Map CutoffFields Recovery)
forall a b. (a -> b) -> a -> b
$ (BeginStatus -> [TsRow] -> CashFlowFrame
CF.CashFlowFrame (Recovery
begBal,Date
asOfDay,Maybe Recovery
forall a. Maybe a
Nothing) [TsRow]
futureTxns, Map CutoffFields Recovery
historyM)
projCashflow m :: Loan
m@(PersonalLoan (LoanOriginalInfo Recovery
ob RateType
or Int
ot Period
p Date
sd AmortPlan
prinPayType Maybe Obligor
_) Recovery
cb IRate
cr Int
rt (Defaulted Maybe Date
Nothing)) Date
asOfDay AssetPerf
assumps Maybe [RateAssumption]
_
= (CashFlowFrame, Map CutoffFields Recovery)
-> Either String (CashFlowFrame, Map CutoffFields Recovery)
forall a b. b -> Either a b
Right ((CashFlowFrame, Map CutoffFields Recovery)
-> Either String (CashFlowFrame, Map CutoffFields Recovery))
-> (CashFlowFrame, Map CutoffFields Recovery)
-> Either String (CashFlowFrame, Map CutoffFields Recovery)
forall a b. (a -> b) -> a -> b
$ (BeginStatus -> [TsRow] -> CashFlowFrame
CF.CashFlowFrame (Recovery
cb,Date
asOfDay,Maybe Recovery
forall a. Maybe a
Nothing) [Date
-> Recovery
-> Recovery
-> Recovery
-> Recovery
-> Recovery
-> Recovery
-> Recovery
-> IRate
-> Maybe CumulativeStat
-> TsRow
CF.LoanFlow Date
asOfDay Recovery
0 Recovery
0 Recovery
0 Recovery
0 Recovery
0 Recovery
0 Recovery
0 IRate
cr Maybe CumulativeStat
forall a. Maybe a
Nothing],Map CutoffFields Recovery
forall k a. Map k a
Map.empty)
projCashflow Loan
a Date
b AssetPerf
c Maybe [RateAssumption]
d = String -> Either String (CashFlowFrame, Map CutoffFields Recovery)
forall a b. a -> Either a b
Left (String
-> Either String (CashFlowFrame, Map CutoffFields Recovery))
-> String
-> Either String (CashFlowFrame, Map CutoffFields Recovery)
forall a b. (a -> b) -> a -> b
$ String
"failed to match projCashflow for Loan "String -> String -> String
forall a. [a] -> [a] -> [a]
++Loan -> String
forall a. Show a => a -> String
show Loan
aString -> String -> String
forall a. [a] -> [a] -> [a]
++Date -> String
forall a. Show a => a -> String
show Date
bString -> String -> String
forall a. [a] -> [a] -> [a]
++AssetPerf -> String
forall a. Show a => a -> String
show AssetPerf
cString -> String -> String
forall a. [a] -> [a] -> [a]
++Maybe [RateAssumption] -> String
forall a. Show a => a -> String
show Maybe [RateAssumption]
d
splitWith :: Loan -> [Rational] -> [Loan]
splitWith l :: Loan
l@(PersonalLoan (LoanOriginalInfo Recovery
ob RateType
or Int
ot Period
p Date
sd AmortPlan
prinPayType Maybe Obligor
obr) Recovery
cb IRate
cr Int
rt Status
st) [Rational]
rs
= [ OriginalInfo -> Recovery -> IRate -> Int -> Status -> Loan
PersonalLoan (Recovery
-> RateType
-> Int
-> Period
-> Date
-> AmortPlan
-> Maybe Obligor
-> OriginalInfo
LoanOriginalInfo (Recovery -> Rational -> Recovery
mulBR Recovery
ob Rational
ratio) RateType
or Int
ot Period
p Date
sd AmortPlan
prinPayType Maybe Obligor
obr) (Recovery -> Rational -> Recovery
mulBR Recovery
cb Rational
ratio) IRate
cr Int
rt Status
st | Rational
ratio <- [Rational]
rs ]