packages feed

Hastructure-0.50.3: test/UT/AssetTest.hs

module UT.AssetTest(mortgageTests,mortgageCalcTests,loanTests,leaseTests,installmentTest,armTest,ppyTest
                   ,delinqScheduleCFTest,delinqMortgageTest,btlMortgageTest,nonPayMortgageTest,receivableTest,fixedAssetTest)
where

import Test.Tasty
import Test.Tasty.HUnit

import qualified Data.Time as T
import qualified Lib as L
import qualified Asset as Ast
import qualified Pool as P
import qualified AssetClass.AssetBase as AB
import qualified AssetClass.Mortgage as ACM
import qualified AssetClass.Loan as ACL
import qualified AssetClass.Lease as ACR
import qualified AssetClass.Installment as ACI
import qualified AssetClass.Receivable as AR
import qualified Assumptions as A
import qualified Cashflow as CF
import qualified Deal as D
import Types
import Data.Either
import InterestRate

import Debug.Trace
import Control.Lens hiding (element)
import Control.Lens.TH
debug = flip trace

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

tm = AB.Mortgage
     (AB.MortgageOriginalInfo 10000 (Fix DC_ACT_365F 0.08) 24 L.Monthly (L.toDate "20210101") AB.Level Nothing Nothing)
     8000 0.08 19 
     Nothing
     AB.Current

tm1 = AB.Mortgage
     (AB.MortgageOriginalInfo 240 (Fix DC_ACT_365F 0.08) 24 L.Monthly (L.toDate "20210101") AB.Even Nothing Nothing)
     240 0.08 19 
     Nothing
     AB.Current

tm2 = AB.Mortgage
     (AB.MortgageOriginalInfo 240 (Fix DC_ACT_365F 0.08) 24 L.Monthly (L.toDate "20210101") AB.Even Nothing Nothing)
     240 0.08 19 
     Nothing 
     (AB.Defaulted Nothing)

tm4 = AB.Mortgage
        (AB.MortgageOriginalInfo 240 (Fix DC_30_360_US 0.08) 36 L.Monthly (L.toDate "20210701") (AB.Balloon 120) Nothing Nothing)
        120 0.08 36
        Nothing 
        AB.Current

tm5 = AB.Mortgage
        (AB.MortgageOriginalInfo 240 (Fix DC_ACT_365F 0.08) 36 L.Monthly (L.toDate "20210101") (AB.Balloon 120)  Nothing Nothing)
        100 0.08 24 
        Nothing 
        AB.Current


tm6 = AB.Mortgage
        (AB.MortgageOriginalInfo 240 (Fix DC_ACT_365F 0.08) 36 L.Monthly (L.toDate "20210101") (AB.Balloon 120) Nothing Nothing)
        120 0.08 36
        Nothing 
        AB.Current

tm7 = AB.Mortgage
        (AB.MortgageOriginalInfo 240 (Fix DC_ACT_365F 0.08) 36 L.Monthly (L.toDate "20210101") (AB.Balloon 120)  Nothing Nothing)
        120 0.08 24
        Nothing 
        AB.Current



asOfDate = L.toDate "20210605"

(tmcf_00,_) = case Ast.projCashflow tm asOfDate (A.MortgageAssump Nothing Nothing Nothing Nothing,A.DummyDelinqAssump,A.DummyDefaultAssump) Nothing of
                Left _ -> undefined
                Right x -> x
trs = tmcf_00^.CF.cashflowTxn  
(tmcf_default,_) = case Ast.projCashflow tm asOfDate (A.MortgageAssump (Just (A.DefaultConstant 0.015)) Nothing Nothing Nothing ,A.DummyDelinqAssump,A.DummyDefaultAssump) Nothing of
                     Left _ -> undefined
                     Right x -> x


mortgageCalcTests = testGroup "Mortgage Calc Test" 
  [
    testCase "Calc Pmt 1" $
        assertEqual "PMT 01"
           154.15 (AB.calcPmt 1200 0.12 24),
    testCase "Calc Pmt 2" $
        assertEqual "PMT 02"
           100.0 (AB.calcPmt 1200 0.0 12)
  ]


mortgageTests = testGroup "Mortgage cashflow Tests"
  [
    testCase "Fix rate mortgage" $
     --  19 @=? (CF.sizeCashFlowFrame tmcf_00)
     assertEqual "total size of cf" 19 (CF.sizeCashFlowFrame tmcf_00) -- `debug` ("result"++show(tmcf_00))
     ,
     testCase "first Date" $
     assertEqual "first date" (L.toDate "20210701")  (CF.getDate (head trs)) -- `debug` ("result"++show(tmcf_00))
     --assertEqual "total size of cf" 19 19
     ,
     testCase "Even Principal Type of Mortgage" $
     let
        tm1cf_00 = case Ast.calcCashflow tm1 asOfDate Nothing of
                         Left _ -> undefined
                         Right x -> x
        trs = tm1cf_00 ^. CF.cashflowTxn  
     in
        assertEqual "first row" 12.63  (CF.mflowPrincipal (head trs)) -- `debug` ("result"++show(tmcf_00))
     ,
     testCase "Default asset won't have cashflow if no assumption" $
     let
        asDay = L.toDate "20220101"
        (tm2cf_00, _) = case Ast.projCashflow tm2 asDay (A.MortgageAssump Nothing Nothing Nothing Nothing ,A.DummyDelinqAssump,A.DummyDefaultAssump) Nothing of
                         Left _ -> undefined
                         Right x -> x
        trs = tm2cf_00 ^. CF.cashflowTxn  
     in
        assertEqual "Empty for principal"
                    (0.0, asDay, 1)
                    (CF.mflowPrincipal (head trs)
                    ,(view CF.tsDate (head trs))
                    ,length trs)
     ,
     testCase "Balloon Mortgage test 1" $
     let
        tm1cf_00 = case Ast.calcCashflow tm4 asOfDate Nothing of-- `debug` (">>>")
                         Left _ -> undefined
                         Right x -> x
        trs = tm1cf_00 ^. CF.cashflowTxn  
     in
        assertEqual "first & last row row" 
                    [94.29,0.62,0.66, 0.79] 
                    [CF.mflowPrincipal (last trs)
                    ,CF.mflowInterest (last trs)
                    ,(CF.mflowPrincipal . head . tail) trs
                    ,(CF.mflowInterest . head . tail) trs ] -- `debug` ("trs for balloon"++show tm1cf_00)
     ,
     testCase "Balloon Mortgage test 2" $
     let
        tm1cf_00 = case Ast.calcCashflow tm5 asOfDate Nothing of
                         Left _ -> undefined
                         Right x -> x
        trs = tm1cf_00 ^. CF.cashflowTxn 
     in
        assertEqual "first & last row row" 
                    [84.19,0.56,0.64, 0.66] 
                    [CF.mflowPrincipal (last trs)
                    ,CF.mflowInterest (last trs)
                    ,(CF.mflowPrincipal . head . tail) trs
                    ,(CF.mflowInterest . head . tail) trs ] -- `debug` ("trs for balloon"++show tm1cf_00)
     ,testCase "Balloon Mortgage test 3" $
     let
        (tm1cf_00,_) = case Ast.projCashflow tm6 (L.toDate "20201205")
                         (A.MortgageAssump Nothing (Just (A.PrepaymentCPR 0.1)) Nothing Nothing ,A.DummyDelinqAssump,A.DummyDefaultAssump) Nothing of 
                         Left _ -> undefined
                         Right x -> x
        trs = tm1cf_00 ^. CF.cashflowTxn 
     in
        assertEqual "first & last row row" 
                    [68.77, 0.45, 1.06, 0.65, 0.79] 
                    [CF.mflowPrincipal (last trs)
                    ,CF.mflowInterest (last trs)
                    ,(CF.mflowPrepayment) (trs!!1)
                    ,(CF.mflowPrincipal) (trs!!1)
                    ,(CF.mflowInterest) (trs!!1) ] -- `debug` ("trs for balloon"++show tm1cf_00)
    ,testCase "Balloon Mortgage test 4" $
     let
        (tm1cf_00,_) = case Ast.projCashflow tm7 (L.toDate "20201205")
                         (A.MortgageAssump Nothing (Just (A.PrepaymentCPR 0.1)) Nothing Nothing ,A.DummyDelinqAssump,A.DummyDefaultAssump) Nothing of
                         Left _ -> undefined
                         Right x -> x
        trs = tm1cf_00 ^. CF.cashflowTxn
     in
        assertEqual "first & last row row" 
                    ([82, 0.73, 0.54, 1.06, 0.75, 0.79], 25) 
                    ([CF.mflowPrincipal (last trs)
                    ,CF.mflowPrepayment (last trs)
                    ,CF.mflowInterest (last trs)
                    ,(CF.mflowPrepayment) (trs!!1)
                    ,(CF.mflowPrincipal) (trs!!1)
                    ,(CF.mflowInterest) (trs!!1) 
                    ], CF.sizeCashFlowFrame tm1cf_00) -- `debug` ("trs for balloon"++show tm1cf_00)
    ,testCase "Balloon Mortgage test 5" $
     let
        (tm1cf_00,_) = case Ast.projCashflow tm7 (L.toDate "20201205")
                         (A.MortgageAssump (Just (A.DefaultAtEndByRate 0.05 0.1)) Nothing Nothing Nothing ,A.DummyDelinqAssump,A.DummyDefaultAssump) Nothing of
                         Left _ -> undefined
                         Right x -> x
        trs = tm1cf_00 ^. CF.cashflowTxn 
     in
        assertEqual "first & last row row" 
                    ([74.34, 17.43, 0.49, 0.52, 0.76, 0.79], 25) 
                    ([CF.mflowPrincipal (last trs)
                    ,CF.mflowDefault (last trs)
                    ,CF.mflowInterest (last trs)
                    ,(CF.mflowDefault) (trs!!1)
                    ,(CF.mflowPrincipal) (trs!!1)
                    ,(CF.mflowInterest) (trs!!1) 
                    ], CF.sizeCashFlowFrame tm1cf_00) -- `debug` ("trs for balloon"++show tm1cf_00)        
  ]

loanTests = 
    let 
      loan1 =  AB.PersonalLoan
                 (AB.LoanOriginalInfo 180 (Fix DC_ACT_365F 0.08) 36 L.Monthly (L.toDate "20200101") AB.I_P Nothing) 
                 120
                 0.08
                 24
                 AB.Current
      asofDate = L.toDate "20200615"
      loan1Cf = case Ast.calcCashflow loan1 asofDate Nothing of
                  Left _ -> undefined
                  Right x -> x
      (loan2Cf,_) = case Ast.projCashflow loan1 asofDate (A.LoanAssump Nothing Nothing Nothing Nothing ,A.DummyDelinqAssump,A.DummyDefaultAssump) Nothing of 
                  Left _ -> undefined
                  Right x -> x

    in 
      testGroup "Loan cashflow Tests" [ 
       testCase "Loan 1" $
           assertEqual "project period"
             25
             (CF.sizeCashFlowFrame loan1Cf)
      -- ,testCase "First cashflow" $
      --     assertEqual ""
      --      (Just (CF.LoanFlow (L.toDate "20210201") 120 0 0.82 0 0 0 0 0.08))
      --      (CF.cfAt loan1Cf 0)
      -- ,testCase "Last Principal Amount" $
      --     assertEqual ""
      --      (Just (CF.LoanFlow (L.toDate "20230101") 0 120 0.82 0 0 0 0 0.08))
      --      (CF.cfAt loan1Cf 23)
      -- ,testCase "calcCashflow == projCashflow when assump = []" $
      --     assertEqual ""
      --     loan1Cf
      --     loan2Cf
     ]

leaseTests = 
    let 
      lease1 = AB.RegularLease
                (AB.LeaseInfo (L.toDate "20230101") 12 (AB.ByDayRate 1 MonthEnd) Nothing)
                100
                12
                AB.Current
      asofDate = L.toDate "20230615"
      cf1 = case Ast.calcCashflow lease1 asofDate Nothing of 
              Left _ -> undefined
              Right x -> x
 
      lease2 = AB.StepUpLease
                (AB.LeaseInfo (L.toDate "20230601") 12 (AB.ByDayRate 1 MonthEnd) Nothing)
                (AB.FlatRate 1.02)
                100
                12
                AB.Current
      cf2 = case Ast.calcCashflow lease2 asofDate Nothing of -- 2020 06 15
              Left _ -> undefined
              Right x -> x
      
      lease3 = AB.StepUpLease
                (AB.LeaseInfo (L.toDate "20230401") 4 (AB.ByDayRate 1 MonthEnd) Nothing)
                (AB.ByRateCurve [1.04,1.05,1.06])
                100
                4
                AB.Current
      cf3_0 = case Ast.calcCashflow lease3 (L.toDate "20230415") Nothing of
              Left _ -> undefined
              Right x -> x
      cf3 = case Ast.calcCashflow lease3 asofDate Nothing of
              Left _ -> undefined
              Right x -> x
      (cf4,_) = case Ast.projCashflow lease1 asofDate 
                  (A.LeaseAssump Nothing
                                 (A.GapDays 45)
                                 (A.BaseAnnualRate 0.0)
                                 (A.CutByDate (L.toDate "20240601"))
                                 
                   ,A.DummyDelinqAssump,A.DummyDefaultAssump)
                   Nothing of 
                  Left _ -> undefined
                  Right x -> x
      -- (cf5,_) =  case Ast.projCashflow lease1 asofDate 
      --              (A.LeaseAssump Nothing
      --                             (A.GapDaysByAmount [(0.5,12),(1,22),(2,62),(3,82)] 92)
      --                             (A.BaseAnnualRate 0.0)
      --                             (A.CutByDate (L.toDate "20240601"))
      --                             
      --              ,A.DummyDelinqAssump,A.DummyDefaultAssump)
      --              Nothing of
      --             Left _ -> undefined
      --             Right x -> x
    in 
      testGroup "Lease CF Test" [
        testCase "1 year Regular Lease sum of rentals/dates" $
            assertEqual "Dates"
                (L.toDates ["20230131","20230228","20230331","20230430","20230531","20230630"
                            ,"20230731","20230831","20230930","20231031","20231130","20231231"])
                (Ast.getPaymentDates lease1 0)
        ,testCase "1 year Regular Lease sum of rentals/dates" $
            assertEqual "cf dates"
                (L.toDates ["20230630","20230731","20230831","20230930","20231031","20231130","20231231"])
                (CF.getDate <$> (cf1 ^. CF.cashflowTxn))
        ,testCase "1 year Regular Lease sum of rentals/first" $
            assertEqual "First flow"
                (CF.LeaseFlow (L.toDate "20230630") 184.00 30.0 0.0)
                (head (cf1 ^. CF.cashflowTxn))
        ,testCase "1 year Regular Lease sum of rentals/last" $
            assertEqual "Last flow"
                (CF.LeaseFlow (L.toDate "20231231") 0.00 31.0 0.0)
                (last (cf1 ^. CF.cashflowTxn))
        ,testCase "1 year Regular Lease sum of rentals" $
            assertEqual "total rental"
                214
                (sum $ map CF.tsTotalCash (cf1 ^. CF.cashflowTxn))
        ,testCase "1 year Regular Lease first pay date" $
            assertEqual "first date of regular lease"
                (L.toDate "20230630")
                (head (CF.getDatesCashFlowFrame cf1))
        ,testCase "1 year Stepup lease first pay" $
            assertEqual "first pay"
                (CF.LeaseFlow (L.toDate "20230630") 376.24 29 0.0)
                (head (cf2 ^. CF.cashflowTxn))
        ,testCase "1 year Stepup lease" $
            assertEqual "total rental"
                405.24
                (sum $ map CF.tsTotalCash (cf2 ^. CF.cashflowTxn))
        ,testCase "1 year Stepup lease" $
            assertEqual "first rental step up at Month 2"
                (CF.LeaseFlow (L.toDate "20230731") 344.62 31.62 0.0)
                ((cf2 ^. CF.cashflowTxn)!!1)
        ,testCase "1 year Stepup Curve lease" $
            assertEqual "first rental step up at Month 0"
                (CF.LeaseFlow (L.toDate "20230430") 100.59 29.0 0.0)
                (head (cf3_0 ^. CF.cashflowTxn )) 
        ,testCase "1 year Stepup Curve lease" $
            assertEqual "first rental step up at Month 1"
                (CF.LeaseFlow (L.toDate "20230630") 35.65 32.7 0.0)
                (head (cf3 ^. CF.cashflowTxn)) -- `debug` ("CF3->"++show cf3)
        ,testCase "1 year Stepup Curve lease" $
            assertEqual "first rental step up at Month 2"
                (CF.LeaseFlow (L.toDate "20230731") 0 35.65 0.0)
                ((cf3 ^. CF.cashflowTxn)!!1)
        ,testCase "Lease with Assumptions" $ 
            assertEqual "Month Gap=45 days"
            ((CF.LeaseFlow (L.toDate "20240630") 215 30.0 0.0),(CF.LeaseFlow (L.toDate "20250131") 0 31 0))
            (((cf4 ^. CF.cashflowTxn)!!11),(last (cf4 ^. CF.cashflowTxn))) -- `debug` ("CF4->"++show cf4)
        -- ,testCase "Lease with Assumptions" $ 
        --     assertEqual "Month Gap by Table : New Lease at period 0"
        --     (CF.LeaseFlow (L.toDate "20240131") 335 8)
        --     ((cf5 ^. CF.cashflowTxn)!!7) `debug` ("CF5->"++show cf5)
        -- ,testCase "Lease with Assumptions" $ 
        --     assertEqual "Month Gap by Table : New Lease at period 1"
        --     (CF.LeaseFlow (L.toDate "20240229") 306 29)
        --     ((cf5 ^. CF.cashflowTxn)!!8)
      ]

installmentTest = 
    let 
      loan1 =  AB.Installment
                 (AB.LoanOriginalInfo 1000 (Fix DC_ACT_365F 0.01) 12 L.Monthly (L.toDate "20220101") AB.F_P Nothing)
                 1000 
                 12 
                 AB.Current
      asofDate1 = L.toDate "20220115"
      loan1Cf = case Ast.calcCashflow loan1 asofDate1 Nothing of
                  Left _ -> undefined
                  Right x -> x

      loan2 =  AB.Installment
                 (AB.LoanOriginalInfo 1000 (Fix DC_ACT_365F 0.01) 12 L.Monthly (L.toDate "20220101") AB.F_P Nothing) 
                 500 
                 12
                 AB.Current
      loan2Cf = case Ast.calcCashflow loan2 asofDate1 Nothing of
                  Left _ -> undefined
                  Right x -> x

      asofDate2 = L.toDate "20220815"
      loan3 =  AB.Installment
                 (AB.LoanOriginalInfo 1000 (Fix DC_ACT_365F 0.01) 12 L.Monthly (L.toDate "20220101") AB.F_P Nothing) 
                 416.69 
                 5
                 AB.Current
      loan3Cf = case Ast.calcCashflow loan3 asofDate2 Nothing of
                  Left _ -> undefined
                  Right x -> x

      loan4 =  AB.Installment
                 (AB.LoanOriginalInfo 1000 (Fix DC_ACT_365F 0.01) 12 L.Monthly (L.toDate "20220101") AB.F_P Nothing) 
                 208.35 
                 5
                 AB.Current
      loan4Cf = case Ast.calcCashflow loan4 asofDate2 Nothing of
                  Left _ -> undefined
                  Right x -> x
      
      loan5 =  AB.Installment
                 (AB.LoanOriginalInfo 1200 (Fix DC_ACT_365F 0.01) 12 L.Monthly (L.toDate "20220101") (AB.PO_FirstN 4) Nothing) 
                 1000
                 10
                 AB.Current
      loan5Cf = case Ast.calcCashflow loan5 (L.toDate "20220101") Nothing of 
                  Left _ -> undefined
                  Right x -> x
    in 
      testGroup "Installment cashflow Tests" [ 
       testCase "Loan 1" $
           assertEqual "project period size"
             12 
             (CF.sizeCashFlowFrame loan1Cf)
      ,testCase "Loan 1 (on schedule)" $
           assertEqual "Balance/Principal/Int at period 1"
             (Just (CF.LoanFlow (L.toDate "20220201") 916.67 83.33 10 0 0 0 0 0.01 Nothing))
             (CF.cfAt loan1Cf 0)
      ,testCase "Stressed Loan 1" $
           assertEqual "Balance/Principal/Int at period 1"
             (Just (CF.LoanFlow (L.toDate "20220201") 458.33 41.66 5 0 0 0 0 0.01 Nothing))
             (CF.cfAt loan2Cf 0)
      ,testCase "Loan 2 with aging(on schedule)" $
           assertEqual "Balance/Principal/Int at period 1"
             (Just (CF.LoanFlow (L.toDate "20220901") 333.36 83.33 10 0 0 0 0 0.01 Nothing))
             (CF.cfAt loan3Cf 0)
      ,testCase "Stress Loan 2 with aging" $
           assertEqual "Balance/Principal/Int at period 1"
             (Just (CF.LoanFlow (L.toDate "20220901") 166.68 41.66 5 0 0 0 0 0.01 Nothing))
             (CF.cfAt loan4Cf 0)
      ,testCase "First No Fee Loan at first period" $
           assertEqual "Balance/Principal/Int at period 1"
             (Just (CF.LoanFlow (L.toDate "20220301") 1000 0 0 0 0 0 0 0.01 Nothing))
             (CF.cfAt loan5Cf 0)
      ,testCase "First No Fee Loan at first period" $
           assertEqual "Balance/Principal/Int at period 3"
             (Just (CF.LoanFlow (L.toDate "20220501") 800 100 0 0 0 0 0 0.01 Nothing))
             (CF.cfAt loan5Cf 2)
      ,testCase "First No Fee Loan at first period" $
           assertEqual "Balance/Principal/Int at period 4"
             (Just (CF.LoanFlow (L.toDate "20220601") 700 100 12 0 0 0 0 0.01 Nothing))
             (CF.cfAt loan5Cf 3) -- `debug` (show loan5Cf)
      ]


armTest = 
  let 
    arm1 = AB.AdjustRateMortgage
            (AB.MortgageOriginalInfo 
              240 
              (Floater DC_ACT_365F SOFR3M 0.01 0.03 (EveryNMonth (L.toDate "20240801") 2) Nothing Nothing Nothing)
              30
              Monthly
              (L.toDate "20230501")
              AB.Level
              Nothing
              Nothing)
            (ARM 12 (Just 0.015) (Just 0.01) (Just 0.09) (Just 0.02) )  
            240 0.08 19 
            Nothing 
            AB.Current
    assump1 = RateCurve 
                SOFR3M
                (IRateCurve [TsPoint (L.toDate "20240501") 0.05 
                            ,TsPoint (L.toDate "20240901") 0.065
                            ,TsPoint (L.toDate "20241215") 0.07
                            ,TsPoint (L.toDate "20250315") 0.10
                            ,TsPoint (L.toDate "20251001") 0.12
                            ])
                
    (arm1_cf,_) = let 
                    cf = Ast.projCashflow arm1 (L.toDate "20230601") (A.MortgageAssump Nothing Nothing Nothing Nothing
                                                            ,A.DummyDelinqAssump,A.DummyDefaultAssump) 
                                                            (Just [assump1])
                  in 
                    case cf of 
                      Left _ -> undefined 
                      Right x -> x

  in 
    testGroup "ARM cashflow tests" [
      testCase "ARM case 1/ cf length" $
        assertEqual "should be 19"
        20
        (CF.sizeCashFlowFrame arm1_cf)
      ,testCase "ARM case 1/ first cash" $
        assertEqual "first cash row"
        (Just (CF.MortgageFlow (L.toDate "20240501") 227.66 12.34 0.6 0 0 0 0 0.03 Nothing Nothing (Just (12.34,0.00,0.00,0.00,0.00,0.00)) ))
        (CF.cfAt arm1_cf 1)
      ,testCase "ARM case 1/ frist reset" $
        assertEqual "first rate"
        (Just (CF.MortgageFlow (L.toDate "20240601") 215.41 12.25 0.85 0 0 0 0 0.045 Nothing Nothing (Just (24.59,0.00,0.00,0.00,0.00,0.00))))
        (CF.cfAt arm1_cf 2)
      ,testCase "ARM case 1/periodic reset " $
        assertEqual "first rate"
        (Just (CF.MortgageFlow (L.toDate "20240801") 190.85 12.26 0.93 0 0 0 0 0.055 Nothing Nothing (Just (49.15,0.00,0.00,0.00,0.00,0.00)) ))
        (CF.cfAt arm1_cf 4)
      ,testCase "ARM case 1/remains same before next reset" $
        assertEqual "period before first reset"
        (Just (CF.MortgageFlow (L.toDate "20240901") 178.53 12.32 0.87 0 0 0 0 0.055 Nothing Nothing (Just (61.47,0.00,0.00,0.00,0.00,0.00))))
        (CF.cfAt arm1_cf 5)
      ,testCase "ARM case 1" $
        assertEqual "reset with periodic cap"
        (Just (CF.MortgageFlow (L.toDate "20241201") 141.47 12.38 0.96 0 0 0 0 0.075 Nothing Nothing (Just (98.53,0.00,0.00,0.00,0.00,0.00))))
        (CF.cfAt arm1_cf 8)
      ,testCase "ARM case 1" $
        assertEqual "Period 9"
        (Just (CF.MortgageFlow (L.toDate "20250101") 129.01 12.46 0.88 0 0 0 0 0.075 Nothing Nothing (Just (110.99,0.00,0.00,0.00,0.00,0.00))))
        (CF.cfAt arm1_cf 9)
      ,testCase "ARM case 1" $
        assertEqual "Period 10"
        (Just (CF.MortgageFlow (L.toDate "20250201") 116.49 12.52 0.85 0 0 0 0 0.08 Nothing Nothing (Just (123.51,0.00,0.00,0.00,0.00,0.00))))
        (CF.cfAt arm1_cf 10)
      ,testCase "ARM case 1" $
        assertEqual "life cap"
        (Just (CF.MortgageFlow (L.toDate "20250401") 91.24 12.65 0.77 0 0 0 0 0.09 Nothing Nothing (Just (148.76,0.00,0.00,0.00,0.00,0.00))))
        (CF.cfAt arm1_cf 12)

    ]

---- prepayment penalty 

ppy_1 = Just $ AB.ByTerm 3 0.1 0.01
ppy_2 = Just $ AB.FixAmount 100 Nothing
ppy_2_1 = Just $ AB.FixAmount 100 (Just 2)
ppy_3 = Just $ AB.FixPct 0.01 Nothing
ppy_3_1 = Just $ AB.FixPct 0.01 (Just 2)
ppy_4 = Just $ AB.Sliding 0.1 0.01
ppy_5 = Just $ AB.StepDown [(2,0.5),(12,0.2)]

origin_info = AB.MortgageOriginalInfo 10000 (Fix DC_ACT_365F 0.08) 24 L.Monthly (L.toDate "20210101") AB.Level Nothing Nothing

tm_ppy_1 = AB.Mortgage (origin_info { AB.prepaymentPenalty = ppy_1}) 10000 0.08 24 Nothing AB.Current
tm_ppy_2 = AB.Mortgage (origin_info { AB.prepaymentPenalty = ppy_2}) 10000 0.08 24 Nothing AB.Current
tm_ppy_2_1 = AB.Mortgage (origin_info { AB.prepaymentPenalty = ppy_2_1}) 10000 0.08 24 Nothing AB.Current
tm_ppy_3 = AB.Mortgage (origin_info { AB.prepaymentPenalty = ppy_3}) 10000 0.08 24 Nothing AB.Current
tm_ppy_3_1 = AB.Mortgage (origin_info { AB.prepaymentPenalty = ppy_3_1}) 10000 0.08 24 Nothing AB.Current
tm_ppy_4 = AB.Mortgage (origin_info { AB.prepaymentPenalty = ppy_4}) 10000 0.08 24 Nothing AB.Current
tm_ppy_5 = AB.Mortgage (origin_info { AB.prepaymentPenalty = ppy_5}) 10000 0.08 24 Nothing AB.Current

ppyTest = 
  let 
    assump1 = (A.MortgageAssump Nothing (Just (A.PrepaymentCPR 0.03)) Nothing Nothing,A.DummyDelinqAssump,A.DummyDefaultAssump)

    (ppy_cf_1,_) = case Ast.projCashflow tm_ppy_1 (L.toDate "20210101") assump1 Nothing of 
                    Left _ -> undefined
                    Right x -> x
    (ppy_cf_2,_) = case Ast.projCashflow tm_ppy_2 (L.toDate "20210101") assump1 Nothing of
                    Left _ -> undefined
                    Right x -> x
    (ppy_cf_2_1,_) = case Ast.projCashflow tm_ppy_2_1 (L.toDate "20210101") assump1 Nothing of
                    Left _ -> undefined
                    Right x -> x
    (ppy_cf_3,_) = case Ast.projCashflow tm_ppy_3 (L.toDate "20210101") assump1 Nothing of
                    Left _ -> undefined
                    Right x -> x
    (ppy_cf_3_1,_) = case Ast.projCashflow tm_ppy_3_1 (L.toDate "20210101") assump1 Nothing of
                    Left _ -> undefined
                    Right x -> x
    (ppy_cf_4,_) = case Ast.projCashflow tm_ppy_4 (L.toDate "20210101") assump1 Nothing of
                    Left _ -> undefined
                    Right x -> x
    (ppy_cf_5,_) = case  Ast.projCashflow tm_ppy_5 (L.toDate "20210101") assump1 Nothing of
                    Left _ -> undefined
                    Right x -> x

  in 
    testGroup "Prepay Penalty tests" [
      testCase "ppy case 1" $
        assertEqual " using rate0"
        (Just (CF.MortgageFlow (L.toDate "20210201") 9589.55 384.62 66.48 25.83 0 0 0 0.08 Nothing (Just 2.58) (Just (384.62,25.83,0.00,0.00,0.00,0.00))))
        (CF.cfAt ppy_cf_1 1)
      ,testCase "ppy case 1" $
        assertEqual " using rate1"
        (Just (CF.MortgageFlow (L.toDate "20210501") 8357.98 389.45 58.31 21.92 0 0 0 0.08 Nothing (Just 0.21 ) (Just (1548.18,93.84,0.00,0.00,0.00,0.00))))
        (CF.cfAt ppy_cf_1 4)
      ,testCase "ppy case 2" $
        assertEqual " using fix amount"
        (Just (CF.MortgageFlow (L.toDate "20210501") 8357.98 389.45 58.31 21.92 0 0 0 0.08 Nothing (Just 100 ) (Just (1548.18,93.84,0.00,0.00,0.00,0.00))))
        (CF.cfAt ppy_cf_2 4)
      ,testCase "ppy case 2 1_0" $
        assertEqual " using fix amount in period"
        (Just (CF.MortgageFlow (L.toDate "20210201")  9589.55 384.62 66.48 25.83 0 0 0 0.08 Nothing  (Just 100 ) (Just (384.62,25.83,0.00,0.00,0.00,0.00))))
        (CF.cfAt ppy_cf_2_1 1)
      ,testCase "ppy case 2 1" $
        assertEqual " using fix amount out of period"
        (Just (CF.MortgageFlow (L.toDate "20210501") 8357.98 389.45 58.31 21.92 0 0 0 0.08 Nothing (Just 0 ) (Just (1548.18,93.84,0.00,0.00,0.00,0.00))))
        (CF.cfAt ppy_cf_2_1 4)
      ,testCase "ppy case 3" $
        assertEqual " using life time pct"
        (Just (CF.MortgageFlow (L.toDate "20210501") 8357.98 389.45 58.31 21.92 0 0 0 0.08 Nothing (Just 0.21 ) (Just (1548.18,93.84,0.00,0.00,0.00,0.00))))
        (CF.cfAt ppy_cf_3 4)
      ,testCase "ppy case 3 1_0" $
        assertEqual " using pct in period"
        (Just (CF.MortgageFlow (L.toDate "20210201")  9589.55 384.62 66.48 25.83 0 0 0 0.08 Nothing  (Just 0.25 ) (Just (384.62,25.83,0.00,0.00,0.00,0.00))))
        (CF.cfAt ppy_cf_3_1 1)
      ,testCase "ppy case 3 1" $
        assertEqual " using pct out of period"
        (Just (CF.MortgageFlow (L.toDate "20210501") 8357.98 389.45 58.31 21.92 0 0 0 0.08 Nothing (Just 0 ) (Just (1548.18,93.84,0.00,0.00,0.00,0.00))))
        (CF.cfAt ppy_cf_3_1 4)
      ,testCase "ppy case 4" $
        assertEqual " using slide at period 0"
        (Just (CF.MortgageFlow (L.toDate "20210201")  9589.55 384.62 66.48 25.83 0 0 0 0.08 Nothing  (Just 2.58 ) (Just (384.62,25.83,0.00,0.00,0.00,0.00))))
        (CF.cfAt ppy_cf_4 1)
      ,testCase "ppy case 4 1" $
        assertEqual " using slide at period 1"
        (Just (CF.MortgageFlow (L.toDate "20210501") 8357.98 389.45 58.31 21.92 0 0 0 0.08 Nothing (Just (0.07*21.92)) (Just (1548.18,93.84,0.00,0.00,0.00,0.00))))
        (CF.cfAt ppy_cf_4 4)     
      ,testCase "ppy case 5" $
        assertEqual " using rate 0 before 2 periods"
        (Just (CF.MortgageFlow (L.toDate "20210201")  9589.55 384.62 66.48 25.83 0 0 0 0.08 Nothing  (Just (25.83*0.5) ) (Just (384.62,25.83,0.00,0.00,0.00,0.00))))
        (CF.cfAt ppy_cf_5 1)
      ,testCase "ppy case 5 1" $
        assertEqual " using rate 1 after 2 periods"
        (Just (CF.MortgageFlow (L.toDate "20210501") 8357.98 389.45 58.31 21.92 0 0 0 0.08 Nothing (Just (0.2*21.92)) (Just (1548.18,93.84,0.00,0.00,0.00,0.00))))
        (CF.cfAt ppy_cf_5 4)   
    ]

delinqScheduleCFTest = 
  let 
    cfs = [CF.MortgageDelinqFlow (L.toDate "20230901") 1000  0 0 0 0 0 0 0 0.08 Nothing Nothing Nothing
          ,CF.MortgageDelinqFlow (L.toDate "20231001") 500 500 0 0 0 0 0 0 0.08 Nothing Nothing Nothing
          ]
    pool = P.Pool ([]::[AB.Mortgage])
                  (Just (CF.CashFlowFrame dummySt cfs,Nothing))
                  Nothing
                  (L.toDate "20230801")
                  Nothing
                  (Just MonthEnd)
    assump1 = Just (A.PoolLevel 
                      (A.MortgageDeqAssump (Just (A.DelinqCDR 0.05 (5,0.3))) Nothing Nothing Nothing
                      ,A.DummyDelinqAssump
                      ,A.DummyDefaultAssump))
    assump2 = Just (A.PoolLevel 
                      (A.MortgageDeqAssump (Just (A.DelinqCDR 0.05 (5,0.3))) (Just (A.PrepaymentCPR 0.08)) Nothing Nothing
                      ,A.DummyDelinqAssump
                      ,A.DummyDefaultAssump))

    poolCf = fst . head $ 
               case P.runPool pool assump1 Nothing of
                 Left errorMsg -> undefined `debug` ("Error in pool run"++show errorMsg)
                 Right x -> x  `debug` ("pool run resp"++show x)
    poolCf2 = fst . head $ 
                case P.runPool pool assump2 Nothing of
                  Left _ -> undefined
                  Right x -> x
  in 
    testGroup "delinq run on schedule flow" [
      testCase "case 01" $
        assertEqual "size of cashflow" 
        7
        (CF.sizeCashFlowFrame poolCf) -- `debug` ("\n>>>>> Pool cf from test schedule delinq\n >>>>"++ show poolCf)
      ,testCase "case 01_Dates" $
        assertEqual "Dates of cashflow" 
        (L.toDate <$> ["20230901","20231001","20231031","20231130","20231231","20240131","20240229"])
        (CF.getDatesCashFlowFrame poolCf)
      ,testCase "case 02" $
        assertEqual "first row of cf"
        (Just (CF.MortgageDelinqFlow (L.toDate "20230901") 995.66  0 0 0 4.34 0 0 0 0.08 Nothing Nothing (Just (0.00,0.00,4.34,0.00,0.00,0.00))))
        (CF.cfAt poolCf 0)
      ,testCase "case 03" $
        assertEqual "second row of cf"
        (Just (CF.MortgageDelinqFlow (L.toDate "20231001") 493.66  497.82 0 0 4.18 0 0 0 0.08 Nothing Nothing (Just (497.82,0.00,8.52,0.00,0.00,0.00))))
        (CF.cfAt poolCf 1)
      ,testCase "case 04" $
        assertEqual "first extended cf, nothing"
        (Just (CF.MortgageDelinqFlow (L.toDate "20231031") 493.66  0.0 0 0 0 0 0 0 0.00 Nothing Nothing (Just (497.82,0.00,8.52,0.00,0.00,0.00))))
        (CF.cfAt poolCf 2)
      ,testCase "case 05" $
        assertEqual "first default from delinq"
        (Just (CF.MortgageDelinqFlow (L.toDate "20240131") 499.61  0.0 0 0 0 1.3 0 1.3 0.000952 Nothing Nothing (Just (497.82,0.00,8.52,1.30,0.00,1.30))))
        (CF.cfAt poolCf 5)
      ,testCase "case 06" $
        assertEqual "first loss/recovery from default & first back to perf"
        (Just (CF.MortgageDelinqFlow (L.toDate "20240229") 496.64  2.97 0 0 0 1.25 0 1.25 0.000480 Nothing Nothing (Just (500.79,0.00,8.52,2.55,0.00,2.55))))
        (CF.cfAt poolCf 6)
      -- ,testCase "case 07" $
      --   assertEqual "first loss/recovery from default & first back to perf"
      --   (Just (CF.MortgageFlow (L.toDate "20240229") 492.36  0.0 0 0 0 1.25 0 1.25 0.0 Nothing Nothing))
      --   (CF.cfAt poolCf 7)
      ,testCase "case with prepay assump" $
        assertEqual "01"
        (Just (CF.MortgageDelinqFlow (L.toDate "20230901") 988.64 0 0 7.02 4.34  0.0 0.0 0.0 0.08 Nothing Nothing  (Just (0.00,7.02,4.34,0.00,0.00,0.00))))
        (CF.cfAt poolCf2 0)
    ]

delinqMortgageTest = 
  let 
    tm1 = AB.Mortgage
           (AB.MortgageOriginalInfo 12 (Fix DC_ACT_365F 0.08) 12 L.Monthly (L.toDate "20210101") AB.Level Nothing Nothing)
           240 0.08 3
           Nothing
           AB.Current
    assump1 = (A.MortgageDeqAssump   
                        (Just (A.DelinqCDR 0.05 (2,0.3)))
                        -- (Just (A.PrepaymentCPR 0.08))
                        Nothing
                        Nothing 
                        Nothing
              ,A.DummyDelinqAssump,A.DummyDefaultAssump)
    (CF.CashFlowFrame _ txns,m) = case Ast.projCashflow tm1 (L.toDate "20200101") assump1 Nothing of
                                    Left _ -> undefined
                                    Right x -> x

  in 
    testGroup "Mortgage Delinq Projection" [
      testCase "" $
        assertEqual "Length of cf"
        5
        (length txns) -- `debug` ("Delinq CF"++show txns)
      ,testCase "first row" $
        assertEqual "delinq = 1"
        (CF.MortgageDelinqFlow (L.toDate "20211101") 159.84 79.12 1.59 0 1.04 0.0 0.0 0.0 0.08 Nothing Nothing (Just (79.12,0.00,1.04,0.00,0.00,0.00)))
        (txns!!0)
      ,testCase "second row" $
        assertEqual "with first default/loss/recovery"
        (CF.MortgageDelinqFlow (L.toDate "20211201") 79.85 79.32 1.06  0 0.67 0.0 0.0 0.0 0.08 Nothing Nothing (Just (158.44,0.00,1.71,0.00,0.00,0.00)))
        (txns!!1)
      ,testCase "last row" $
        assertEqual "with first default/loss/recovery"
        (CF.MortgageDelinqFlow (L.toDate "20220101") 1.17 79.75 0.53  0 0.34 0.31 0.0 0.31 0.08 Nothing Nothing (Just (238.19,0.00,2.05,0.31,0.00,0.31)))
        (txns!!2)
      ,testCase "extend 1st flow" $
        assertEqual "check default"
        (CF.MortgageDelinqFlow (L.toDate "20220201") 0.70 0.47 0.0  0.0 0.0 0.20 0.0 0.2 0.08 Nothing Nothing (Just (238.66,0.00,2.05,0.51,0.00,0.51)))
        (txns!!3)
      -- ,testCase "extend 2st flow" $
      --   assertEqual "check default"
      --   (CF.MortgageDelinqFlow (L.toDate "20220201") 1.08 0.36 0.0  0.0 0.0 0.11 0.0 0.11 0.08 Nothing Nothing)
      --   (txns!!4)
      -- ,testCase "extend 3st flow" $
      --   assertEqual "check default"
      --   (CF.MortgageDelinqFlow (L.toDate "20220201") 1.08 0.36 0.0  0.0 0.0 0.0 0.0 0.0 0.08 Nothing Nothing)
      --   (txns!!5)
    ]

btlMortgageTest = 
  let 
    btl = AB.Mortgage
            (AB.MortgageOriginalInfo 240 (Fix DC_ACT_365F 0.08) 24 L.Monthly (L.toDate "20210101") AB.I_P Nothing Nothing)
            240 0.08 2
            Nothing
            AB.Current
    assump1 = (A.MortgageAssump   
                        Nothing
                        -- (Just (A.PrepaymentCPR 0.08))
                        Nothing
                        Nothing 
                        Nothing
              ,A.DummyDelinqAssump,A.DummyDefaultAssump)            
    (CF.CashFlowFrame _ txns,m) = case Ast.projCashflow btl (L.toDate "20200101") assump1 Nothing of 
                                    Left _ -> undefined
                                    Right x -> x
  in 
    testGroup "Buy to let Mortgage Projection" [
      testCase "" $
        assertEqual "Length of cf"
        3
        (length txns)
      ,testCase "extend 1st flow" $
        assertEqual "1st row"
        (CF.MortgageFlow (L.toDate "20221201") 240 0 1.59  0.0 0.0 0.0 0.0 0.08 Nothing Nothing (Just (0.0,0.00,0.0,0.0,0.00,0.0)))
        (txns!!1)
      ,testCase "extend 1st flow" $
        assertEqual "last row"
        (CF.MortgageFlow (L.toDate "20230101") 0 240 1.59  0.0 0.0 0.0 0.0 0.08 Nothing Nothing (Just (240,0.00,0.0,0.0,0.00,0.0)))
        (txns!!2)
    ]

nonPayMortgageTest = 
  let 
    m = AB.Mortgage
          (AB.MortgageOriginalInfo 240 (Fix DC_ACT_365F 0.08) 24 L.Monthly (L.toDate "20210101") (AB.NO_FirstN 3 AB.Level) Nothing Nothing)
          240 0.08 24
          Nothing
          AB.Current
    assump1 = (A.MortgageAssump   
                        Nothing
                        Nothing
                        Nothing 
                        Nothing
              ,A.DummyDelinqAssump,A.DummyDefaultAssump)
    (CF.CashFlowFrame _ txns,_) = case Ast.projCashflow m (L.toDate "20200101") assump1 Nothing of 
                                    Left _ -> undefined
                                    Right x -> x
    m1 = AB.Mortgage
          (AB.MortgageOriginalInfo 240 (Fix DC_ACT_365F 0.08) 24 L.Monthly (L.toDate "20210101") (AB.IO_FirstN 3 AB.Level) Nothing Nothing)
          240 0.08 24
          Nothing
          AB.Current
    (CF.CashFlowFrame _ txns2,_) = case Ast.projCashflow m1 (L.toDate "20200101") assump1 Nothing of 
                                     Left _ -> undefined
                                     Right x -> x
 
  in 
    testGroup "Non Payment Mortgage Projection" [
      testCase "NonPay" $
        assertEqual "Length of cf"
        25
        (length txns)
      ,testCase "first accured" $
        assertEqual "1st row"
        (CF.MortgageFlow (L.toDate "20210201") 241.59 (-1.59) 0 0.0 0.0 0.0 0.0 0.08 Nothing Nothing (Just (-1.59,0.00,0.0,0.0,0.00,0.0)))
        (txns!!1)
      ,testCase "first amort" $
        assertEqual "4st row"
        (CF.MortgageFlow (L.toDate "20210501") 233.92 10.9 1.63 0.0 0.0 0.0 0.0 0.08 Nothing Nothing (Just (6.08,0.00,0.0,0.0,0.00,0.0)))
        (txns!!4)
      ,testCase "IO" $
        assertEqual "Length of cf"
        25
        (length txns)
      ,testCase "first accured" $
        assertEqual "1st row"
        (CF.MortgageFlow (L.toDate "20210201") 240 0.0 1.59 0.0 0.0 0.0 0.0 0.08 Nothing Nothing (Just (0,0.0,0.0,0.0,0.00,0.0)))
        (txns2!!1)
      ,testCase "first amort" $
        assertEqual "4st row"
        (CF.MortgageFlow (L.toDate "20210501") 229.31 10.69 1.59 0.0 0.0 0.0 0.0 0.08 Nothing Nothing (Just (10.69,0.00,0.0,0.0,0.00,0.0)))
        (txns2!!4)
      
    ]

receivableTest = 
  let 
    invoice1 = AB.Invoice (AB.ReceivableInfo (L.toDate "20240401") 1500 1000 (L.toDate "20240601") Nothing Nothing) AB.Current
    invoice2 = AB.Invoice (AB.ReceivableInfo (L.toDate "20240401") 1500 1000 (L.toDate "20240601") (Just (AB.FixedFee 50)) Nothing ) AB.Current
    invoice0 = AB.Invoice (AB.ReceivableInfo (L.toDate "20240401") 1500 1000 (L.toDate "20240601") Nothing Nothing) (AB.Defaulted Nothing)
    invoiceAssump = (A.ReceivableAssump   
                        Nothing
                        Nothing 
                        Nothing
                    ,A.DummyDelinqAssump,A.DummyDefaultAssump)
  in 
    testGroup "Invoice CF test" [
      testCase "Plain Receivable" $
        assertEqual "Last Payment"
        (Right (Just (CF.ReceivableFlow (L.toDate "20240601") 0 0 1500 0 0 0 0 (Just (0.0,0.0,0.0,0.0,0.0,0.0)))))
        ((`CF.cfAt` 1) <$>  (fst <$> Ast.projCashflow invoice1 (L.toDate "20240101") invoiceAssump Nothing) )
      ,testCase "Fix Fee" $
        assertEqual "Last Payment"
        (Right (Just (CF.ReceivableFlow (L.toDate "20240601") 0 0 1450 50 0 0 0 (Just (0.0,0.0,0.0,0.0,0.0,0.0)))))
        ((`CF.cfAt` 1) <$> (fst <$> Ast.projCashflow invoice2 (L.toDate "20240101") invoiceAssump Nothing))
      ,testCase "Defaulted invoice" $
        assertEqual "Defauted invoice "
        (Right (Just (CF.ReceivableFlow (L.toDate "20240501") 0 0 0 0 1500 0 1500.0 (Just (0.0,0.0,0.0,1500.0,0.0,1500.0)))))
        ((`CF.cfAt` 0) <$> (fst <$> Ast.projCashflow invoice0 (L.toDate "20240501") invoiceAssump Nothing))
    ]
  
fixedAssetTest = 
  let 
    assetInfo = AB.FixedAssetInfo (L.toDate "20250101") 11000 1000 10 Monthly AB.StraightLine (AB.FixedCapacity 100)
    assetInfo2 = AB.FixedAssetInfo (L.toDate "20250101") 10000 1000 10 Monthly AB.DecliningBalance (AB.FixedCapacity 100)
    asset = AB.FixedAsset assetInfo 11000 10
    priceCurve = L.mkTs [(L.toDate "20250101",50), (L.toDate "20251231", 150)]
    utilCurve = L.mkTs [(L.toDate "20250101",1.0), (L.toDate "20251231", 1.0)]
  in 
    testGroup "fixed Asset Test" [
      testCase "StraightLine:init Asset: size" $ 
        assertEqual "StraightLine:init Asset: size"
        (Right 10)
        (let 
            asset1 = asset
          in 
            (CF.sizeCashFlowFrame <$> (fst <$> (Ast.projCashflow asset1 (L.toDate "20240101") 
                                  ((A.FixedAssetAssump utilCurve priceCurve  Nothing) ,A.DummyDelinqAssump ,A.DummyDefaultAssump) Nothing))))
      ,testCase "StraightLine:init Asset with ext " $ 
        assertEqual "StraightLine:init Asset"
        (Right (Just (CF.FixedFlow (L.toDate "20260201") 1000 0 10000 100.0 15000.0)))
        (let 
            asset1 = asset
          in 
            ((`CF.cfAt` 12) <$> (fst <$> (Ast.projCashflow asset1 (L.toDate "20240101") 
                                  ((A.FixedAssetAssump utilCurve priceCurve (Just 3)) ,A.DummyDelinqAssump ,A.DummyDefaultAssump) Nothing))))
      ,testCase "StraightLine:init Asset with diff cur balance " $ 
        assertEqual "StraightLine:init Asset"
        (Right (Just (CF.FixedFlow (L.toDate "20250701") 3400 600.0 7600 100.0 5000.0)))
        (let 
            asset2 = AB.FixedAsset assetInfo 4000 5
          in 
            ((`CF.cfAt` 0) <$> (fst <$> (Ast.projCashflow asset2 (L.toDate "20240101") 
                                  ((A.FixedAssetAssump utilCurve priceCurve Nothing) ,A.DummyDelinqAssump ,A.DummyDefaultAssump) Nothing))))
      ,testCase "StraightLine:init Asset with diff cur balance " $ 
        assertEqual "StraightLine:init Asset"
        (Right (Just (CF.FixedFlow (L.toDate "20260201") 1000 0 10000 100.0 15000.0)))
        (let 
            asset2 = AB.FixedAsset assetInfo 4000 5
          in 
            ((`CF.cfAt` 7) <$> (fst <$> (Ast.projCashflow asset2 (L.toDate "20240101") 
                                  ((A.FixedAssetAssump utilCurve priceCurve (Just 3)) ,A.DummyDelinqAssump ,A.DummyDefaultAssump) Nothing))))
      ,testCase "StraightLine:init Asset with diff cur balance " $ 
        assertEqual "StraightLine:init Asset"
        (Right (Just (CF.FixedFlow (L.toDate "20251101") 1000 3000 10000 100.0 5000.0)))
        (let 
            asset2 = AB.FixedAsset assetInfo 4000 1
          in 
            ((`CF.cfAt` 0) <$> (fst <$> (Ast.projCashflow asset2 (L.toDate "20240101") 
                                  ((A.FixedAssetAssump utilCurve priceCurve (Just 3)) ,A.DummyDelinqAssump ,A.DummyDefaultAssump) Nothing))))
      ,testCase "Double Decline:size" $ 
        assertEqual "Double Decline:size "
        (Right 10)
        (let 
            asset2 = AB.FixedAsset assetInfo2 10000 10
          in 
            (CF.sizeCashFlowFrame <$> (fst <$> (Ast.projCashflow asset2 (L.toDate "20240101") 
                                  ((A.FixedAssetAssump utilCurve priceCurve Nothing) ,A.DummyDelinqAssump ,A.DummyDefaultAssump) Nothing))))
      ,testCase "Double Decline:first row with full cur bal" $ 
        assertEqual "Double Decline:init Asset"
        (Right (Just (CF.FixedFlow (L.toDate "20250201") 8000 2000 2000 100.0 5000.0)))
        (let 
            asset2 = AB.FixedAsset assetInfo2 10000 10
          in 
            ((`CF.cfAt` 0) <$> (fst <$> (Ast.projCashflow asset2 (L.toDate "20240101") 
                                  ((A.FixedAssetAssump utilCurve priceCurve (Just 3)) ,A.DummyDelinqAssump ,A.DummyDefaultAssump) Nothing))))
      ,testCase "Double Decline:init Asset :last" $ 
        assertEqual "Double Decline:init Asset :last"
        (Right (Just (CF.FixedFlow (L.toDate "20251101") 1000.0 338.86 9000.0 100.0 5000.0)))
        (let 
            asset2 = AB.FixedAsset assetInfo2 10000 10
          in 
            ((`CF.cfAt` 9) <$> (fst <$> (Ast.projCashflow asset2 (L.toDate "20240101") 
                                  ((A.FixedAssetAssump utilCurve priceCurve Nothing) ,A.DummyDelinqAssump ,A.DummyDefaultAssump) Nothing))))
      ,testCase "Double Decline:init Asset: with ext periods" $ 
        assertEqual "Double Decline:init Asset: with ext periods"
        (Right (Just (CF.FixedFlow (L.toDate "20260201") 1000.00 0.0 9000 100.0 15000.0)))
        (let 
            asset2 = AB.FixedAsset assetInfo2 10000 10
          in 
            ((`CF.cfAt` 12) <$> (fst <$> (Ast.projCashflow asset2 (L.toDate "20240101") 
                                  ((A.FixedAssetAssump utilCurve priceCurve (Just 3)) ,A.DummyDelinqAssump ,A.DummyDefaultAssump) Nothing))))

      -- ,testCase "Double Decline" $ 
      --   assertEqual "Double Decline:init Asset : current with less balance "
      --   (Right (Just (CF.FixedFlow (L.toDate "20251101") 1073.73 268.44 8926.27 100.0 5000.0)))
      --   (let 
      --       asset2 = AB.FixedAsset assetInfo2 5000 5
      --     in 
      --       ((`CF.cfAt` 9) <$> (fst <$> (Ast.projCashflow asset2 (L.toDate "20240101") 
      --                             ((A.FixedAssetAssump utilCurve priceCurve Nothing) ,A.DummyDelinqAssump ,A.DummyDefaultAssump) Nothing))))
    ]