packages feed

Hastructure-0.45.2: test/UT/CashflowTest.hs

module UT.CashflowTest(cfTests,tsSplitTests,testMergePoolCf,combineTest,testHaircut
                      ,testMergeTsRowsFromTwoEntities,testCumStat,testClawIntTest,testPoolAggTest)
where

import Test.Tasty
import Test.Tasty.HUnit

import qualified Data.Time as T
import qualified Lib as L
import qualified Asset as P
import qualified Pool
import qualified Data.Map as Map
import qualified Assumptions as A
import qualified Cashflow as CF
import Types
import Util
import DateUtil

import Debug.Trace
debug = flip trace

dummySt = (0,L.toDate "19000101",Nothing)

trs = [CF.MortgageFlow (L.toDate "20220101") 100 10 10 0 0 0 0 0 Nothing Nothing Nothing
      , CF.MortgageFlow (L.toDate "20220201") 90 10 10 0 0 0 0 0 Nothing Nothing Nothing
      , CF.MortgageFlow (L.toDate "20220211") 80 10 10 0 0 0 0 0 Nothing Nothing Nothing
      , CF.MortgageFlow (L.toDate "20220301") 70 10 10 0 0 0 0 0 Nothing Nothing Nothing]

cf = CF.CashFlowFrame dummySt trs

aggTs1 = CF.aggTsByDates trs [L.toDate "20220110"]
aggTs2 = CF.aggTsByDates trs [L.toDate "20220210"]
aggTs3 = CF.aggTsByDates trs [L.toDate "20220101",L.toDate "20220208"]
aggTs4 = CF.aggTsByDates trs [L.toDate "20220101",L.toDate "20220218"]

findLatestCf1 = CF.getTxnLatestAsOf cf (L.toDate "20220215")
findLatestCf2 = CF.getTxnLatestAsOf cf (L.toDate "20220315")
findLatestCf3 = CF.getTxnLatestAsOf cf (L.toDate "20210315")

cfTests = testGroup "Cashflow Utils"
  [
    testCase "Cashflow Aggregation only one return" $
     assertEqual "only one ts" 1 (length aggTs1)
   ,testCase "Cashflow Aggregation agg correct amount" $
     assertEqual "which bal is 100"
       (CF.MortgageFlow (L.toDate "20220110") 100 10 10 0 0 0 0 0 Nothing Nothing Nothing)
       (head aggTs1)
   ,testCase "Cashflow Aggregation Sum up" $
     assertEqual "Test Sum up" 1 (length aggTs2)
   ,testCase "Cashflow Aggregation agg correct amount" $
     assertEqual "which bal is 90"
       (CF.MortgageFlow (L.toDate "20220210") 90 20 20 0 0 0 0 0 Nothing Nothing Nothing)
       (head aggTs2)

   ,testCase "Cashflow Aggregation with two dates" $
     assertEqual "Test Sum up" 2 (length aggTs3)
   ,testCase "Cashflow Aggregation agg correct amount" $
     assertEqual "which bal is 90"
        [CF.MortgageFlow (L.toDate "20220101") 100 10 10 0 0 0 0 0 Nothing Nothing Nothing
        ,CF.MortgageFlow (L.toDate "20220208") 90 10 10 0 0 0 0 0  Nothing Nothing Nothing]
        aggTs3

   ,testCase "Cashflow Aggregation with two flows at second cutoff" $
     assertEqual "include two cf in one cutoff date"
       [CF.MortgageFlow (L.toDate "20220101") 100 10 10 0 0 0 0 0 Nothing Nothing Nothing
       ,CF.MortgageFlow (L.toDate "20220218") 80 20 20 0 0 0 0 0  Nothing Nothing Nothing]
       aggTs4
   ,testCase "Cashflow Aggregation" $
     assertEqual "aggregate period with no cf"
       [CF.MortgageFlow (L.toDate "20220101") 100 10 10 0 0 0 0 0 Nothing Nothing Nothing
       ,CF.MortgageFlow (L.toDate "20220102") 100 0 0 0 0 0 0 0 Nothing Nothing Nothing
       ,CF.MortgageFlow (L.toDate "20220111") 100 0 0 0 0 0 0 0 Nothing Nothing Nothing
       ]
       (CF.aggTsByDates trs (L.toDates ["20220101","20220102","20220111"]))

   ,testCase "Get Latest Cashflow 1" $
     assertEqual "Found one"
       (Just $ CF.MortgageFlow (L.toDate "20220211") 80 10 10 0 0 0 0 0 Nothing Nothing Nothing)
       findLatestCf1
   ,testCase "Get Latest Cashflow 2" $
     assertEqual "Found one"
       (Just (CF.MortgageFlow (L.toDate "20220301") 70 10 10 0 0 0 0 0 Nothing Nothing Nothing))
       findLatestCf2
   ,testCase "Get Latest Cashflow 3" $
     assertEqual "Nothing found"
       Nothing
       findLatestCf3
    ]


tsSplitTests = 
    let 
      cf1 = CF.CashFlow (L.toDate "20230101") 100
      cf2 = CF.CashFlow (L.toDate "20230201") 100
      cf3 = CF.CashFlow (L.toDate "20230301") 100
      cf4 = CF.CashFlow (L.toDate "20230401") 100
      ts1 = [cf1,cf2,cf3,cf4]
      ts2 = [cf1,cf2,cf2,cf3,cf4]
      cff = CF.CashFlowFrame dummySt [cf1,cf2,cf3,cf4]
    in 
      testGroup "Slice Time Series" 
      [ testCase "Cashflow" $
          assertEqual "by middle left"
          ([cf1,cf2],[cf3,cf4]) $
          splitByDate ts1 (L.toDate "20230215") EqToLeft
        ,testCase "Cashflow" $
          assertEqual "on left" 
          ([cf1,cf2,cf3],[cf4]) $
          splitByDate ts1 (L.toDate "20230301") EqToLeft
        ,testCase "Cashflow" $
          assertEqual "on right"
          ([cf1,cf2],[cf3,cf4]) $
          splitByDate ts1 (L.toDate "20230301") EqToRight
        ,testCase "Cashflow" $
          assertEqual "by middle right"
          ([cf1],[cf2, cf3,cf4]) $
          splitByDate ts1 (L.toDate "20230110") EqToRight
        ,testCase "Cashflow" $
          assertEqual "Keep previous one"
          ([cf1],[cf2, cf3,cf4]) $
          splitByDate ts1 (L.toDate "20230210") EqToLeftKeepOne
        ,testCase "Cashflow" $
          assertEqual "Keep previous one"
          ([],[cf1,cf2, cf3,cf4]) $
          splitByDate ts1 (L.toDate "20230201") EqToLeftKeepOne
        ,testCase "Range of Ts" $
          assertEqual "get subset of Ts between two dates"
          [cf2, cf3,cf4] $
          sliceBy II (L.toDate "20230201") (L.toDate "20230401") ts1
        ,testCase "Range of Ts" $
          assertEqual "get subset of Ts between two dates"
          [cf3,cf4] $
          sliceBy EI (L.toDate "20230201") (L.toDate "20230401") ts1
        ,testCase "Range of Ts" $
          assertEqual "get subset of Ts between two dates"
          [cf2, cf3] $
          sliceBy IE (L.toDate "20230201") (L.toDate "20230401") ts1
        ,testCase "Range of Ts" $
          assertEqual "get subset of Ts between two dates"
          [cf3] $
          sliceBy EE (L.toDate "20230201") (L.toDate "20230401") ts1
      ]

combineTest = 
  let 
    txn1 = CF.MortgageFlow (L.toDate "20230101") 100 10 10 0 0 0 0 0.0 Nothing Nothing Nothing
    txn2 = CF.MortgageFlow (L.toDate "20230201") 90 10 10 0 0 0 0 0.0 Nothing Nothing Nothing
    txn3 = CF.MortgageFlow (L.toDate "20230301") 50 10 10 0 0 0 0 0.0 Nothing Nothing Nothing
    txn4 = CF.MortgageFlow (L.toDate "20230401") 40 10 10 0 0 0 0 0.0 Nothing Nothing Nothing
    cf1 = CF.CashFlowFrame dummySt [txn1,txn2] 
    cf2 = CF.CashFlowFrame dummySt [txn3,txn4] 
  in 
    testGroup "Combine Cashflow Test"
    [ testCase "No overlap combine" $
        assertEqual "No overlap combine"
        (CF.CashFlowFrame dummySt 
          [CF.MortgageFlow (L.toDate "20230101") 160 10 10 0 0 0 0 0.0 Nothing Nothing Nothing
          ,CF.MortgageFlow (L.toDate "20230201") 150 10 10 0 0 0 0 0.0 Nothing Nothing Nothing
          ,CF.MortgageFlow (L.toDate "20230301") 140 10 10 0 0 0 0 0.0 Nothing Nothing Nothing
          ,CF.MortgageFlow (L.toDate "20230401") 130 10 10 0 0 0 0 0.0 Nothing Nothing Nothing])
        (CF.combine cf1 cf2)
      ,testCase "Overlap combine" $
        let 
          txn1 = CF.MortgageFlow (L.toDate "20230101") 100 10 10 0 0 0 0 0.0 Nothing Nothing Nothing
          txn2 = CF.MortgageFlow (L.toDate "20230201") 90 10 10 0 0 0 0 0.0 Nothing Nothing Nothing
          txn3 = CF.MortgageFlow (L.toDate "20230301") 80 10 10 0 0 0 0 0.0 Nothing Nothing Nothing
          cf1 = CF.CashFlowFrame dummySt [txn1,txn2] 
          cf2 = CF.CashFlowFrame dummySt [txn2,txn3] 
        in 
          assertEqual "Overlap combine"
          (CF.CashFlowFrame dummySt $
            [CF.MortgageFlow (L.toDate "20230101") 200 10 10 0 0 0 0 0.0 Nothing Nothing Nothing
            ,CF.MortgageFlow (L.toDate "20230201") 180 20 20 0 0 0 0 0.0 Nothing Nothing Nothing
            ,CF.MortgageFlow (L.toDate "20230301") 170 10 10 0 0 0 0 0.0 Nothing Nothing Nothing])
          (CF.combine cf1 cf2)
       ,testCase "Intersection" $
        let 
          txn1 = CF.MortgageFlow (L.toDate "20230101") 100 10 10 0 0 0 0 0.0 Nothing Nothing Nothing
          txn2 = CF.MortgageFlow (L.toDate "20230201") 80 10 10 0 0 0 0 0.0 Nothing Nothing Nothing
          txn3 = CF.MortgageFlow (L.toDate "20230301") 90 10 10 0 0 0 0 0.0 Nothing Nothing Nothing
          txn4 = CF.MortgageFlow (L.toDate "20230401") 70 10 10 0 0 0 0 0.0 Nothing Nothing Nothing
          cf1 = CF.CashFlowFrame dummySt [txn1,txn3] 
          cf2 = CF.CashFlowFrame dummySt [txn2,txn4] 
        in 
          assertEqual "Intersection CF"
          (CF.CashFlowFrame dummySt $
            [CF.MortgageFlow (L.toDate "20230101") 190 10 10 0 0 0 0 0.0 Nothing Nothing Nothing
            ,CF.MortgageFlow (L.toDate "20230201") 180 10 10 0 0 0 0 0.0 Nothing Nothing Nothing
            ,CF.MortgageFlow (L.toDate "20230301") 170 10 10 0 0 0 0 0.0 Nothing Nothing Nothing
            ,CF.MortgageFlow (L.toDate "20230401") 160 10 10 0 0 0 0 0.0 Nothing Nothing Nothing])
          (CF.combine cf1 cf2)
    ]


testMergeTsRowsFromTwoEntities = 
  let 
    txn1 = CF.MortgageDelinqFlow (L.toDate "20230101") 100 10 10 0 0 0 0 0 0.0 Nothing Nothing Nothing
    txn4 = CF.MortgageDelinqFlow (L.toDate "20230401") 90 10 10 0 0 0 0 0 0.0 Nothing Nothing Nothing 
    
    txn2 = CF.MortgageDelinqFlow (L.toDate "20230201") 100 10 10 0 0 0 0 0 0.0 Nothing Nothing Nothing 
    txn3 = CF.MortgageDelinqFlow (L.toDate "20230301") 90 10 10 0 0 0 0 0 0.0 Nothing Nothing Nothing
  in
    testGroup "Merge Two CF from two entities"
    [testCase "txn1 + txn 2" $ 
      assertEqual "Merge Two CF from two entities"
      [CF.MortgageDelinqFlow (L.toDate "20230101") 210 10 10 0 0 0 0 0 0.0 Nothing Nothing Nothing
       ,CF.MortgageDelinqFlow (L.toDate "20230201") 200 10 10 0 0 0 0 0 0.0 Nothing Nothing Nothing]
      (CF.combineTss [] [txn1] [txn2])
    ,testCase "txn1 + txn 2/3" $ 
      assertEqual "Merge Two CF from two entities"
      [CF.MortgageDelinqFlow (L.toDate "20230101") 210 10 10 0 0 0 0 0 0.0 Nothing Nothing Nothing 
       ,CF.MortgageDelinqFlow (L.toDate "20230201") 200 10 10 0 0 0 0 0 0.0 Nothing Nothing Nothing 
       ,CF.MortgageDelinqFlow (L.toDate "20230301") 190 10 10 0 0 0 0 0 0.0 Nothing Nothing Nothing]
      (CF.combineTss [] [txn1] [txn2,txn3])
    ,testCase "txn1/4 + txn 2/3" $ 
      assertEqual "Merge Two CF from two entities"
      [CF.MortgageDelinqFlow (L.toDate "20230101") 210 10 10 0 0 0 0 0 0.0 Nothing Nothing Nothing 
       ,CF.MortgageDelinqFlow (L.toDate "20230201") 200 10 10 0 0 0 0 0 0.0 Nothing Nothing Nothing 
       ,CF.MortgageDelinqFlow (L.toDate "20230301") 190 10 10 0 0 0 0 0 0.0 Nothing Nothing Nothing 
       ,CF.MortgageDelinqFlow (L.toDate "20230401") 180 10 10 0 0 0 0 0 0.0 Nothing Nothing Nothing ]
      (CF.combineTss [] [txn1,txn4] [txn2,txn3])
    ,testCase "txn1/2 + txn 1/2" $
      assertEqual "Merge Two CF from two entities with same dates"
      [CF.MortgageDelinqFlow (L.toDate "20230101") 200 20 20 0 0 0 0 0 0.0 Nothing Nothing Nothing 
       ,CF.MortgageDelinqFlow (L.toDate "20230201") 180 20 20 0 0 0 0 0 0.0 Nothing Nothing Nothing]
      (CF.combineTss [] [txn1,txn2] [txn1,txn2])
    ,testCase "txn1/2/3 + txn 1/2" $
      assertEqual "Merge Two CF from two entities with same dates"
      [CF.MortgageDelinqFlow (L.toDate "20230101") 200 20 20 0 0 0 0 0 0.0 Nothing Nothing Nothing 
       ,CF.MortgageDelinqFlow (L.toDate "20230201") 180 20 20 0 0 0 0 0 0.0 Nothing Nothing Nothing
       ,CF.MortgageDelinqFlow (L.toDate "20230301") 170 10 10 0 0 0 0 0 0.0 Nothing Nothing Nothing
       ]
      (CF.combineTss [] [txn1,txn2,txn3] [txn1,txn2])
      
      
      ]



testMergePoolCf = 
  let 
    txn1 = CF.MortgageDelinqFlow (L.toDate "20230101") 100 10 10 0 0 0 0 0 0.0 Nothing Nothing Nothing
    txn2 = CF.MortgageDelinqFlow (L.toDate "20230201") 100 10 10 0 0 0 0 0 0.0 Nothing Nothing Nothing
    txn3 = CF.MortgageDelinqFlow (L.toDate "20230301") 90 10 10 0 0 0 0 0 0.0 Nothing Nothing Nothing
    txn4 = CF.MortgageDelinqFlow (L.toDate "20230401") 90 10 10 0 0 0 0 0 0.0 Nothing Nothing Nothing
    
    cf1 = CF.CashFlowFrame (110, L.toDate "20221201", Nothing) [txn1,txn4]
    cf2 = CF.CashFlowFrame (110, L.toDate "20230101", Nothing) [txn2,txn3]

    cf3 = CF.CashFlowFrame (110, L.toDate "20221201", Nothing) [txn2,txn4]
    cf4 = CF.CashFlowFrame (110, L.toDate "20221201", Nothing) [txn1,txn3]

    cf5 = CF.CashFlowFrame (100, L.toDate "20221201", Nothing) [txn3,txn4]
    cf6 = CF.CashFlowFrame (110, L.toDate "20230101", Nothing) [txn2]

  in 
    testGroup "Merge Cashflow Test from two entities"  -- merge cashflow into existing one without update previous balance
    [ testCase "Merge Cashflow Test 1" $
        assertEqual ""
        (CF.CashFlowFrame (110 , L.toDate "20221201", Nothing)
                           [(CF.MortgageDelinqFlow (L.toDate "20230101") 210 10 10 0 0 0 0 0 0.0 Nothing Nothing (Just (10,0,0,0,0,0)))
                           ,(CF.MortgageDelinqFlow (L.toDate "20230201") 200 10 10 0 0 0 0 0 0.0 Nothing Nothing (Just (20,0,0,0,0,0)))
                           ,(CF.MortgageDelinqFlow (L.toDate "20230301") 190 10 10 0 0 0 0 0 0.0 Nothing Nothing (Just (30,0,0,0,0,0)))
                           ,(CF.MortgageDelinqFlow (L.toDate "20230401") 180 10 10 0 0 0 0 0 0.0 Nothing Nothing (Just (40,0,0,0,0,0)))]) 
        (CF.mergePoolCf2 cf1 cf2)
      ,testCase "Merge Cashflow with same begin date 1" $
        assertEqual ""
        (CF.CashFlowFrame (220 , L.toDate "20221201", Nothing)
                           [(CF.MortgageDelinqFlow (L.toDate "20230101") 210 10 10 0 0 0 0 0 0.0 Nothing Nothing (Just (10,0,0,0,0,0)))
                           ,(CF.MortgageDelinqFlow (L.toDate "20230201") 200 10 10 0 0 0 0 0 0.0 Nothing Nothing (Just (20,0,0,0,0,0)))
                           ,(CF.MortgageDelinqFlow (L.toDate "20230301") 190 10 10 0 0 0 0 0 0.0 Nothing Nothing (Just (30,0,0,0,0,0)))
                           ,(CF.MortgageDelinqFlow (L.toDate "20230401") 180 10 10 0 0 0 0 0 0.0 Nothing Nothing (Just (40,0,0,0,0,0)))]) 
        (CF.mergePoolCf2 cf3 cf4)
      ,testCase "Merge Cashflow with diff begin date 2" $
        assertEqual ""
        (CF.CashFlowFrame (100 , L.toDate "20221201", Nothing)
                           [(CF.MortgageDelinqFlow (L.toDate "20230201") 200 10 10 0 0 0 0 0 0.0 Nothing Nothing (Just (10,0,0,0,0,0)))
                           ,(CF.MortgageDelinqFlow (L.toDate "20230301") 190 10 10 0 0 0 0 0 0.0 Nothing Nothing (Just (20,0,0,0,0,0)))
                           ,(CF.MortgageDelinqFlow (L.toDate "20230401") 180 10 10 0 0 0 0 0 0.0 Nothing Nothing (Just (30,0,0,0,0,0)))]) 
        (CF.mergePoolCf2 cf5 cf6)
      ]

testHaircut = 
  let 
    cflow = CF.CashFlowFrame dummySt [(CF.MortgageDelinqFlow (L.toDate "20230101") 100 20 10 20 0 0 5  0 0.0 Nothing (Just 10) Nothing)
                             ,(CF.MortgageDelinqFlow (L.toDate "20230201") 200 30 20 30 0 0 10 0 0.0 Nothing (Just 15) Nothing)
                             ,(CF.MortgageDelinqFlow (L.toDate "20230301") 190 40 30 40 0 0 15 0 0.0 Nothing (Just 20) Nothing)
                             ,(CF.MortgageDelinqFlow (L.toDate "20230401") 180 50 40 50 0 0 20 0 0.0 Nothing (Just 30) Nothing)]
  in 
    testGroup "Test on Haircut"
    [ testCase "Haircut of Nothing" $
        assertEqual "" 
        cflow 
        (P.applyHaircut Nothing cflow)
    ,testCase "Haircut on principal" $
        assertEqual "" 
        (Just (CF.MortgageDelinqFlow (L.toDate "20230101") 100 10 10 20 0 0 5  0 0.0 Nothing (Just 10) Nothing ))
        (CF.cfAt (P.applyHaircut (Just A.ExtraStress{A.poolHairCut = Just [(CollectedPrincipal,0.5)]}) cflow) 0)
    ,testCase "Haircut on interest" $
        assertEqual "" 
        (Just (CF.MortgageDelinqFlow (L.toDate "20230101") 100 20 7 20 0 0 5  0 0.0 Nothing (Just 10) Nothing))
        (CF.cfAt (P.applyHaircut (Just A.ExtraStress{A.poolHairCut = Just [(CollectedInterest,0.3)]}) cflow) 0)
    ,testCase "Haircut on prepayment" $
        assertEqual "" 
        (Just (CF.MortgageDelinqFlow (L.toDate "20230101") 100 20 10 12 0 0 5  0 0.0 Nothing (Just 10) Nothing))
        (CF.cfAt (P.applyHaircut (Just A.ExtraStress{A.poolHairCut = Just [(CollectedPrepayment,0.4)]}) cflow) 0)
    ,testCase "Haircut on recoveries" $
        assertEqual "" 
        (Just (CF.MortgageDelinqFlow (L.toDate "20230101") 100 20 10 20 0 0 4.5  0 0.0 Nothing (Just 10) Nothing))
        (CF.cfAt (P.applyHaircut (Just A.ExtraStress{A.poolHairCut = Just [(CollectedRecoveries,0.1)]}) cflow) 0)
    ,testCase "Haircut on prepay penalty" $
        assertEqual "" 
        (Just (CF.MortgageDelinqFlow (L.toDate "20230101") 100 20 10 20 0 0 5  0 0.0 Nothing (Just 8) Nothing))
        (CF.cfAt (P.applyHaircut (Just A.ExtraStress{A.poolHairCut = Just [(CollectedPrepaymentPenalty,0.2)]}) cflow) 0)
    ,testCase "Haircut on mix" $
        assertEqual "" 
        (Just (CF.MortgageDelinqFlow (L.toDate "20230101") 100 10 7 20 0 0 5  0 0.0 Nothing (Just 8) Nothing))
        (CF.cfAt (P.applyHaircut (Just A.ExtraStress{A.poolHairCut = Just [(CollectedPrepaymentPenalty,0.2)
                                                                          ,(CollectedPrincipal,0.5)
                                                                          ,(CollectedInterest,0.3)]}) cflow) 0)
    ]

testCumStat = 
  let 
    cflow =[CF.MortgageDelinqFlow (L.toDate "20230101") 100 20 10 20 1 2 3 4 0.0 Nothing (Just 10) Nothing
           ,CF.MortgageDelinqFlow (L.toDate "20230201") 200 30 20 30 1 2 3 4 0.0 Nothing (Just 15) Nothing
           ,CF.MortgageDelinqFlow (L.toDate "20230301") 190 40 30 40 1 2 3 4 0.0 Nothing (Just 20) Nothing
           ,CF.MortgageDelinqFlow (L.toDate "20230401") 180 50 40 50 1 2 3 4 0.0 Nothing (Just 30) Nothing]

    cflow1 = [CF.MortgageDelinqFlow (L.toDate "20230201") 200 30 20 30 1 2 3 4 0.0 Nothing (Just 15) (Just (30,30,1,2,3,4))
             ,CF.MortgageDelinqFlow (L.toDate "20230301") 190 40 30 40 1 2 3 4 0.0 Nothing (Just 20) (Just (70,70,2,4,6,8))
             ,CF.MortgageDelinqFlow (L.toDate "20230401") 180 50 40 50 1 2 3 4 0.0 Nothing (Just 30) (Just (120,120,3,6,9,12))]
    
    cflow2 =[CF.MortgageDelinqFlow (L.toDate "20230101") 100 20 10 20 1 2 3 4 0.0 Nothing (Just 10) Nothing
        ,CF.MortgageDelinqFlow (L.toDate "20230201") 200 30 20 30 1 2 3 4 0.0 Nothing (Just 15) Nothing
        ,CF.MortgageDelinqFlow (L.toDate "20230301") 190 40 30 40 1 2 3 4 0.0 Nothing (Just 20) Nothing
        ,CF.MortgageDelinqFlow (L.toDate "20230401") 180 50 40 50 1 2 3 4 0.0 Nothing (Just 30) Nothing]
  in 
    testGroup "Test on calc CumStat"
    [ testCase "MortDelinq CumStat" $
        assertEqual "" 
        cflow1
        (fst (CF.cutoffTrs (L.toDate "20230201") cflow))
      ,testCase "Sum on pool fields-prin" $
        assertEqual "sum principal"
        120.0
        (CF.sumPoolFlow (CF.CashFlowFrame dummySt cflow1) CollectedPrincipal)
      ,testCase "Sum on pool fields-int" $
        assertEqual "sum interest"
        90.0
        (CF.sumPoolFlow (CF.CashFlowFrame dummySt cflow1) CollectedInterest)
      ,testCase "Sum on pool fields-ppy" $
        assertEqual "sum prepayment"
        120.0
        (CF.sumPoolFlow (CF.CashFlowFrame dummySt cflow1) CollectedPrepayment)
      ,testCase "Sum on pool fields-delinq" $
        assertEqual "sum delinq"
        3.0
        (CF.sumPoolFlow (CF.CashFlowFrame dummySt cflow1) NewDelinquencies)
      ,testCase "Sum on pool fields-default" $
        assertEqual "sum default"
        6
        (CF.sumPoolFlow (CF.CashFlowFrame dummySt cflow1) NewDefaults)
      ,testCase "Sum on pool fields-recovery" $
        assertEqual "sum recovery"
        9
        (CF.sumPoolFlow (CF.CashFlowFrame dummySt cflow1) CollectedRecoveries)
      ,testCase "Sum on pool fields-loss" $
        assertEqual "sum loss"
        12
        (CF.sumPoolFlow (CF.CashFlowFrame dummySt cflow1) NewLosses)
      ,testCase "Sum on pool fields-cash" $
        assertEqual "sum cash"
        404.0
        (CF.sumPoolFlow (CF.CashFlowFrame dummySt cflow1) CollectedCash)
      ,testCase "Sum on pool fields-prepay penalty" $
        assertEqual "sum prepayment penalty"
        65
        (CF.sumPoolFlow (CF.CashFlowFrame dummySt cflow1) CollectedPrepaymentPenalty)
      ,testCase "Patch Cumulative 0" $
        assertEqual "patch cum stats"
        [CF.MortgageDelinqFlow (L.toDate "20230101") 100 20 10 20 1 2 3 4 0.0 Nothing (Just 10) (Just (20,20,1,2,3,4))
        ,CF.MortgageDelinqFlow (L.toDate "20230201") 200 30 20 30 1 2 3 4 0.0 Nothing (Just 15) (Just (50,50,2,4,6,8))
        ,CF.MortgageDelinqFlow (L.toDate "20230301") 190 40 30 40 1 2 3 4 0.0 Nothing (Just 20) (Just (90,90,3,6,9,12))
        ,CF.MortgageDelinqFlow (L.toDate "20230401") 180 50 40 50 1 2 3 4 0.0 Nothing (Just 30) (Just (140,140,4,8,12,16))
        ]
        (CF.patchCumulative (0,0,0,0,0,0) [] cflow2)
    ]

testClawIntTest = 
  let 
    cflow =[CF.MortgageDelinqFlow (L.toDate "20230101") 100 20 10 20 1 2 3 4 0.0 Nothing (Just 10) Nothing
           ,CF.MortgageDelinqFlow (L.toDate "20230201") 200 30 20 30 1 2 3 4 0.0 Nothing (Just 15) Nothing ]
  in         
    testGroup "test on interest claw"   
    [
      testCase "claw in first" $
        assertEqual "AA"
        [0,0]
        (CF.mflowInterest <$> CF.clawbackInt 30 cflow)
      ,testCase "claw in second" $
        assertEqual "AA"
        [0,15]
        (CF.mflowInterest <$> CF.clawbackInt 15 cflow)
      ,testCase "claw in all" $
        assertEqual "AA"
        [5,20]
        (CF.mflowInterest <$> CF.clawbackInt 5 cflow)
    ]

testPoolAggTest = 
  let 
    trs = [CF.MortgageFlow (L.toDate "20220101") 100 10 10 0 0 0 0 0 Nothing Nothing (Just (10,0,0,0,0,0))
          , CF.MortgageFlow (L.toDate "20220301") 70 10 10 0 0 0 0 0 Nothing Nothing (Just (20,0,0,0,0,0)) ]
    trs1 = [CF.MortgageFlow (L.toDate "20220101") 100 10 10 0 0 0 0 0 Nothing Nothing (Just (10,0,0,0,0,0))
          , CF.MortgageFlow (L.toDate "20220401") 70 10 10 0 0 0 0 0 Nothing Nothing (Just (20,0,0,0,0,0)) ]
    trs2 = [CF.MortgageFlow (L.toDate "20220101") 100 10 10 0 0 0 0 0 Nothing Nothing (Just (10,0,0,0,0,0))
          , CF.MortgageFlow (L.toDate "20220401") 70 10 10 0 10 0 0 0 Nothing Nothing (Just (20,0,0,10,0,0)) ]
          
    cf = CF.CashFlowFrame dummySt trs    
    cf1 = CF.CashFlowFrame dummySt trs1
    cf2 = CF.CashFlowFrame dummySt trs2
    
  in 
    testGroup "test on combine cashflow with stats"   
    [
      testCase "combineCF one extra row" $
        assertEqual "cum stats should patch at last"
        (CF.CashFlowFrame dummySt
          [
            CF.MortgageFlow (L.toDate "20220101") 200 20 20 0 0 0 0 0 Nothing Nothing (Just (20,0,0,0,0,0))
            ,CF.MortgageFlow (L.toDate "20220301") 190 10 10 0 0 0 0 0 Nothing Nothing (Just (30,0,0,0,0,0))
            ,CF.MortgageFlow (L.toDate "20220401") 180 10 10 0 0 0 0 0 Nothing Nothing (Just (40,0,0,0,0,0))
          ]
          )
        (fst (Pool.aggPool Nothing [(cf,Map.empty),(cf1,Map.empty)]))
      ,testCase "pool agg with init default=100" $
        assertEqual "cum stats with default=100,no default on cfs"
        (Map.fromList [(HistoryDefaults,100)])
        (snd (Pool.aggPool (Just (Map.fromList [(HistoryDefaults,100)])) 
                            [(cf,Map.empty),(cf1,Map.empty)]
                            ))
      ,testCase "pool agg with init default=100 and projected cf default" $
        assertEqual "cum stats with default=100, projected default on cfs"
        (Map.fromList [(HistoryDefaults,200)])
        (snd (Pool.aggPool (Just (Map.fromList [(HistoryDefaults,100)])) 
                            [(cf, (Map.fromList [(HistoryDefaults,100)])),(cf1,Map.empty)]
                            ))
      ,testCase "pool agg with init default=100 and projected cf default2" $
        assertEqual "cum stats with default=100, projected default on cfs"
        (Map.fromList [(HistoryDefaults,200)])
        (snd (Pool.aggPool (Just (Map.fromList [(HistoryDefaults,100)])) 
                            [(cf, (Map.fromList [(HistoryDefaults,100)])),(cf2, Map.empty)]
                            ))                            
    ]