Liquidate Pools
We build an waterfall action which will be executed when running date between “2022-09-01” and “2022-11-01”.
The action will sell all assets with 1:1 on performing balance and save proceeds to account liqAcc
sellBothPool = ["If", ["all", ['>',"2022-09-01"], ['<',"2022-11-01"] ]
,["sellAsset", ["Current|Defaulted", 1.0, 0], "liqAcc"]
]
insert this action to deal
from lenses import lens
from absbox import API,mkDeal,EnginePath
localAPI = API(EnginePath.DEV,check=False)
deal_data = {
"name":"Multiple Pools with Mixed Asset"
,"dates":{"cutoff":"2021-06-01"
,"closing":"2021-07-15"
,"firstPay":"2021-08-26"
,"payFreq":["DayOfMonth",20]
,"poolFreq":"MonthEnd"
,"stated":"2030-01-01"}
,"pool":{"PoolA":{'assets':[["Mortgage"
,{"originBalance":2200,"originRate":["fix",0.045],"originTerm":30
,"freq":"Monthly","type":"Level","originDate":"2021-02-01"}
,{"currentBalance":2200
,"currentRate":0.08
,"remainTerm":30
,"status":"current"}]]},
"PoolB":{'assets':[["Loan"
,{"originBalance": 80000
,"originRate": ["floater",0.045,{"index":"SOFR3M"
,"spread":0.01
,"reset":"QuarterEnd"}]
,"originTerm": 60
,"freq": "Monthly"
,"type": "i_p"
,"originDate": "2021-02-01"}
,{"currentBalance": 65000
,"currentRate": 0.06
,"remainTerm": 60
,"status": "Current"}]]}
}
,"accounts":{"acc01":{"balance":0}
,"acc02":{"balance":0}
,"liqAcc":{"balance":0}}
,"bonds":{"A1":{"balance":1000
,"rate":0.07
,"originBalance":1000
,"originRate":0.07
,"startDate":"2020-01-03"
,"rateType":{"Fixed":0.08}
,"bondType":{"Sequential":None}}
,"B":{"balance":1000
,"rate":0.0
,"originBalance":1000
,"originRate":0.07
,"startDate":"2020-01-03"
,"rateType":{"Fixed":0.00}
,"bondType":{"Equity":None}}}
,"fees":{}
,"collect":[[["PoolA"],"CollectedCash","acc01"]
,[["PoolB"],"CollectedCash","acc02"]]
,"waterfall":{"Amortizing":[
["accrueAndPayInt","acc01",["A1"]]
,["payPrin","acc01",["A1"]]
,["payPrin","acc01",["B"]]
,sellBothPool
,["payPrinResidual","acc01",["B"]]
]}
,"status":("PreClosing","Amortizing")
}
deal = mkDeal(deal_data)
Connecting engine server -> https://absbox.org/api/dev
/home/docs/checkouts/readthedocs.org/user_builds/absbox-doc/envs/stable/lib/python3.11/site-packages/urllib3/connectionpool.py:1097: InsecureRequestWarning: Unverified HTTPS request is being made to host 'absbox.org'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#tls-warnings
warnings.warn(
✅Connected, local lib:0.52.3, server:0.52.3
myAssump = {"poolAssump" : ("ByName"
,{"PoolA":
(("Mortgage",{"CDR":0.02} ,None, None, None)
,None
,None)
,"PoolB":
(("Loan",{"CDR":0.01} ,None, None, None)
,None
,None)}
)
,"runAssump" : [("interest",("LIBOR6M",0.04)
,("SOFR3M",0.04))
,("inspect",("MonthEnd",("poolBalance","PoolB"))
,("MonthEnd",("poolBalance","PoolA")))
]
,"read":True}
r = localAPI.run(deal,**myAssump)
/home/docs/checkouts/readthedocs.org/user_builds/absbox-doc/envs/stable/lib/python3.11/site-packages/urllib3/connectionpool.py:1097: InsecureRequestWarning: Unverified HTTPS request is being made to host 'absbox.org'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#tls-warnings
warnings.warn(
Warning Message from server:Bond B is not paid off Account acc02 has cash to be distributed Account liqAcc has cash to be distributed
Now when sell assets in the pool, the balance equals to the liquidation proceeds
r['pool']['flow']['PoolB'].loc["2022-08-31"].Balance + r['pool']['flow']['PoolA'].loc["2022-08-31"].Balance
np.float64(64935.41)
r['accounts']['liqAcc']
| balance | change | memo | |
|---|---|---|---|
| date | |||
| 2022-09-20 | 64935.41 | 64935.41 | <Liquidation:> |
| 2022-10-20 | 64935.41 | 0.00 | <Liquidation:> |
Sell A Pool Only
Notice there are two pools in the deal, user has the option to sell one of them
sellAPool = ["If", ["all", ['>',"2022-09-01"], ['<',"2022-10-01"] ]
,["sellAsset", ["Current|Defaulted", 1.0, 0], "liqAcc", ['PoolA']]
]
Let’s swap the waterfall action with the one selling PoolA only
sellPoolADeal = deal & lens.waterfall['Amortizing'][3].set(sellAPool)
## it's fancy lens' way to do it , you can do it a straight forwad way like:
## deal.waterfall['Amortizing'][3] = sellAPool
## which will change the data in-place
r = localAPI.run(sellPoolADeal,**myAssump)
/home/docs/checkouts/readthedocs.org/user_builds/absbox-doc/envs/stable/lib/python3.11/site-packages/urllib3/connectionpool.py:1097: InsecureRequestWarning: Unverified HTTPS request is being made to host 'absbox.org'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#tls-warnings
warnings.warn(
Warning Message from server:Bond B is not paid off Account acc02 has cash to be distributed Account liqAcc has cash to be distributed
Now , the selling only have proceeds from pool A
r['accounts']['liqAcc']
| balance | change | memo | |
|---|---|---|---|
| date | |||
| 2022-09-20 | 905.23 | 905.23 | <Liquidation:PoolA> |
Now , once the pool has been liquidated, no more cash will be collected after 2022-9-20
r["pool"]['flow']['PoolA'].tail(5)
| Balance | Principal | Interest | Prepayment | Default | Recovery | Loss | WAC | BorrowerNum | PrepayPenalty | CumPrincipal | CumPrepay | CumDelinq | CumDefault | CumRecovery | CumLoss | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Date | ||||||||||||||||
| 2022-04-30 | 1199.32 | 70.81 | 8.46 | 0 | 2.18 | 0 | 2.18 | 0.08 | None | None | 759.85 | 0 | 0 | 30.23 | 0 | 30.23 |
| 2022-05-31 | 1126.18 | 71.16 | 7.98 | 0 | 1.98 | 0 | 1.98 | 0.08 | None | None | 831.01 | 0 | 0 | 32.21 | 0 | 32.21 |
| 2022-06-30 | 1052.74 | 71.51 | 7.49 | 0 | 1.93 | 0 | 1.93 | 0.08 | None | None | 902.52 | 0 | 0 | 34.14 | 0 | 34.14 |
| 2022-07-31 | 979.13 | 71.87 | 7.00 | 0 | 1.74 | 0 | 1.74 | 0.08 | None | None | 974.39 | 0 | 0 | 35.88 | 0 | 35.88 |
| 2022-08-31 | 905.23 | 72.23 | 6.51 | 0 | 1.67 | 0 | 1.67 | 0.08 | None | None | 1046.62 | 0 | 0 | 37.55 | 0 | 37.55 |
r["pool"]['flow']['PoolB'].tail(5)
| Balance | Principal | Interest | Prepayment | Default | Recovery | Loss | WAC | CumPrincipal | CumPrepay | CumDelinq | CumDefault | CumRecovery | CumLoss | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Date | ||||||||||||||
| 2025-10-31 | 62022.65 | 0.00 | 254.88 | 0 | 51.25 | 0 | 51.25 | 0.05 | 0.00 | 0 | 0 | 2818.27 | 0 | 2818.27 |
| 2025-11-30 | 61969.74 | 0.00 | 263.15 | 0 | 52.91 | 0 | 52.91 | 0.05 | 0.00 | 0 | 0 | 2871.18 | 0 | 2871.18 |
| 2025-12-31 | 61918.58 | 0.00 | 254.45 | 0 | 51.16 | 0 | 51.16 | 0.05 | 0.00 | 0 | 0 | 2922.34 | 0 | 2922.34 |
| 2026-01-31 | 61865.75 | 0.00 | 262.71 | 0 | 52.83 | 0 | 52.83 | 0.05 | 0.00 | 0 | 0 | 2975.17 | 0 | 2975.17 |
| 2026-02-28 | 0.00 | 61812.97 | 262.49 | 0 | 52.78 | 0 | 52.78 | 0.05 | 61812.97 | 0 | 0 | 3027.95 | 0 | 3027.95 |
Sell Both Pool Explicitly
sellABPool = ["If", ["all", ['>',"2022-09-01"], ['<',"2022-10-01"] ]
,["sellAsset", ["Current|Defaulted", 1.0, 0], "liqAcc", ['PoolA','PoolB']]
]
sellPoolABDeal = deal & lens.waterfall['Amortizing'][3].set(sellABPool)
r = localAPI.run(sellPoolABDeal,**myAssump)
/home/docs/checkouts/readthedocs.org/user_builds/absbox-doc/envs/stable/lib/python3.11/site-packages/urllib3/connectionpool.py:1097: InsecureRequestWarning: Unverified HTTPS request is being made to host 'absbox.org'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#tls-warnings
warnings.warn(
Warning Message from server:Bond B is not paid off Account acc02 has cash to be distributed Account liqAcc has cash to be distributed
r['accounts']['liqAcc']
| balance | change | memo | |
|---|---|---|---|
| date | |||
| 2022-09-20 | 64935.41 | 64935.41 | <Liquidation:PoolA,PoolB> |
r["pool"]['flow']['PoolB'].tail(5)
| Balance | Principal | Interest | Prepayment | Default | Recovery | Loss | WAC | CumPrincipal | CumPrepay | CumDelinq | CumDefault | CumRecovery | CumLoss | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Date | ||||||||||||||
| 2022-04-30 | 64245.61 | 0 | 272.82 | 0 | 54.86 | 0 | 54.86 | 0.05 | 0 | 0 | 0 | 595.31 | 0 | 595.31 |
| 2022-05-31 | 64192.57 | 0 | 263.80 | 0 | 53.04 | 0 | 53.04 | 0.05 | 0 | 0 | 0 | 648.35 | 0 | 648.35 |
| 2022-06-30 | 64137.80 | 0 | 272.36 | 0 | 54.77 | 0 | 54.77 | 0.05 | 0 | 0 | 0 | 703.12 | 0 | 703.12 |
| 2022-07-31 | 64084.85 | 0 | 263.36 | 0 | 52.95 | 0 | 52.95 | 0.05 | 0 | 0 | 0 | 756.07 | 0 | 756.07 |
| 2022-08-31 | 64030.18 | 0 | 271.90 | 0 | 54.67 | 0 | 54.67 | 0.05 | 0 | 0 | 0 | 810.74 | 0 | 810.74 |
r["pool"]['flow']['PoolA'].tail(5)
| Balance | Principal | Interest | Prepayment | Default | Recovery | Loss | WAC | BorrowerNum | PrepayPenalty | CumPrincipal | CumPrepay | CumDelinq | CumDefault | CumRecovery | CumLoss | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Date | ||||||||||||||||
| 2022-04-30 | 1199.32 | 70.81 | 8.46 | 0 | 2.18 | 0 | 2.18 | 0.08 | None | None | 759.85 | 0 | 0 | 30.23 | 0 | 30.23 |
| 2022-05-31 | 1126.18 | 71.16 | 7.98 | 0 | 1.98 | 0 | 1.98 | 0.08 | None | None | 831.01 | 0 | 0 | 32.21 | 0 | 32.21 |
| 2022-06-30 | 1052.74 | 71.51 | 7.49 | 0 | 1.93 | 0 | 1.93 | 0.08 | None | None | 902.52 | 0 | 0 | 34.14 | 0 | 34.14 |
| 2022-07-31 | 979.13 | 71.87 | 7.00 | 0 | 1.74 | 0 | 1.74 | 0.08 | None | None | 974.39 | 0 | 0 | 35.88 | 0 | 35.88 |
| 2022-08-31 | 905.23 | 72.23 | 6.51 | 0 | 1.67 | 0 | 1.67 | 0.08 | None | None | 1046.62 | 0 | 0 | 37.55 | 0 | 37.55 |
Sell Pool and Buy again
Liquidate Pool A and buy asset to Pool A again
revol_asset = ["Mortgage"
,{"originBalance":2200,"originRate":["fix",0.045],"originTerm":30
,"freq":"Monthly","type":"Level","originDate":"2021-02-01"}
,{"currentBalance":2200
,"currentRate":0.08
,"remainTerm":30
,"status":"current"}]
poolToBy = (["constant",revol_asset]
,("Pool",("Mortgage",{"CDR":0.07},None,None,None)
,None
,None))
withBuyAssump = myAssump & lens['runAssump'].modify(lambda xs: xs+[ ("revolving",{"poolOne":poolToBy})])
buyAsset = ["If", ["all", ['>',"2022-11-01"], ['<',"2022-12-01"] ]
,["buyAsset2", ["Current|Defaulted", 0.5, 0], "liqAcc",None, "poolOne",'PoolA']]
sellAndBuyDeal = sellPoolADeal & lens.waterfall['Amortizing'].call_mut("insert",3,buyAsset)
r = localAPI.run(sellAndBuyDeal,**withBuyAssump)
/home/docs/checkouts/readthedocs.org/user_builds/absbox-doc/envs/stable/lib/python3.11/site-packages/urllib3/connectionpool.py:1097: InsecureRequestWarning: Unverified HTTPS request is being made to host 'absbox.org'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#tls-warnings
warnings.warn(
Warning Message from server:Account acc01 has cash to be distributed Account acc02 has cash to be distributed
r['pool']['flow']['PoolA'].tail(5)
| Balance | Principal | Interest | Prepayment | Default | Recovery | Loss | WAC | BorrowerNum | PrepayPenalty | CumPrincipal | CumPrepay | CumDelinq | CumDefault | CumRecovery | CumLoss | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Date | ||||||||||||||||
| 2025-01-20 | 224.52 | 55.20 | 1.86 | 0 | 1.72 | 0 | 1.72 | 0.08 | None | None | 1424.76 | 0.0 | 0.0 | 161.18 | 0.0 | 161.18 |
| 2025-02-20 | 167.91 | 55.24 | 1.48 | 0 | 1.37 | 0 | 1.37 | 0.08 | None | None | 1480.00 | 0.0 | 0.0 | 162.55 | 0.0 | 162.55 |
| 2025-03-20 | 111.69 | 55.29 | 1.11 | 0 | 0.93 | 0 | 0.93 | 0.08 | None | None | 1535.29 | 0.0 | 0.0 | 163.48 | 0.0 | 163.48 |
| 2025-04-20 | 55.68 | 55.33 | 0.73 | 0 | 0.68 | 0 | 0.68 | 0.08 | None | None | 1590.62 | 0.0 | 0.0 | 164.16 | 0.0 | 164.16 |
| 2025-05-20 | 0.00 | 55.35 | 0.36 | 0 | 0.33 | 0 | 0.33 | 0.08 | None | None | 1645.97 | 0.0 | 0.0 | 164.49 | 0.0 | 164.49 |
r['accounts']['liqAcc']
| balance | change | memo | |
|---|---|---|---|
| date | |||
| 2022-09-20 | 905.23 | 905.23 | <Liquidation:PoolA> |
| 2022-11-20 | 0.00 | -905.23 | <PurchaseAsset:poolOne,1810.46> |
r['accounts']['acc01'].loc["2022-11-20":"2023-03-20"]
| balance | change | memo | |
|---|---|---|---|
| date | |||
| 2022-11-30 | 0.00 | 0.00 | <PoolPoolA:CollectedCash> |
| 2022-12-31 | 66.38 | 66.38 | <PoolPoolA:CollectedCash> |
| 2023-01-20 | 0.00 | -66.38 | <PayPrin:B> |
| 2023-01-31 | 65.97 | 65.97 | <PoolPoolA:CollectedCash> |
| 2023-02-20 | 0.00 | -65.97 | <PayPrin:B> |
| 2023-02-28 | 65.57 | 65.57 | <PoolPoolA:CollectedCash> |
| 2023-03-20 | 0.00 | -65.57 | <PayPrin:B> |