{
"cells": [
{
"cell_type": "markdown",
"id": "f90bbd9e",
"metadata": {},
"source": [
"### Waterfall Example\n"
]
},
{
"cell_type": "markdown",
"id": "5e882a2d",
"metadata": {},
"source": [
"A simple waterfall with actions in different places"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "f04592ed",
"metadata": {},
"outputs": [],
"source": [
"sampleWaterfall = {\n",
" \"amortizing\":[\n",
" [\"calcAndPayFee\",\"acc01\",['trusteeFee']]\n",
" ,[\"accrueAndPayInt\",\"acc01\",[\"A1\"]]\n",
" ,[\"payPrin\",\"acc01\",[\"A1\"]]\n",
" ,[\"payPrin\",\"acc01\",[\"B\"]]\n",
" ,[\"payIntResidual\",\"acc01\",\"B\"]\n",
" ],\n",
" \"endOfCollection\":[[\"calcAndPayFee\",\"acc01\",['serviceFee']],\n",
" ],\n",
" \n",
" \"cleanUp\":[[\"sellAsset\", [\"Current|Defaulted\", 1.0, 0.2],\"acc01\"]\n",
" ,[\"payIntResidual\",\"acc01\",\"B\"]\n",
" ],\n",
" \n",
" \"closingDay\":[[\"calcAndPayFee\",\"acc01\",['issuanceFee']],\n",
" ]\n",
" }"
]
},
{
"cell_type": "markdown",
"id": "1c9f68eb",
"metadata": {},
"source": [
"Plug in the waterfall into the deal object"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "0e922f1a",
"metadata": {},
"outputs": [],
"source": [
"from absbox import Generic\n",
"\n",
"test01 = Generic(\n",
" \"TEST01\"\n",
" ,{\"cutoff\":\"2021-03-01\",\"closing\":\"2021-06-15\",\"firstPay\":\"2021-07-26\"\n",
" ,\"payFreq\":[\"DayOfMonth\",20],\"poolFreq\":\"MonthEnd\",\"stated\":\"2030-01-01\"}\n",
" ,{'assets':[[\"Mortgage\"\n",
" ,{\"originBalance\":2200,\"originRate\":[\"fix\",0.045],\"originTerm\":30\n",
" ,\"freq\":\"Monthly\",\"type\":\"Level\",\"originDate\":\"2021-02-01\"}\n",
" ,{\"currentBalance\":2200\n",
" ,\"currentRate\":0.08\n",
" ,\"remainTerm\":30\n",
" ,\"status\":\"current\"}]]}\n",
" ,((\"acc01\",{\"balance\":0}),)\n",
" ,((\"A1\",{\"balance\":1000\n",
" ,\"rate\":0.07\n",
" ,\"originBalance\":1000\n",
" ,\"originRate\":0.07\n",
" ,\"startDate\":\"2020-01-03\"\n",
" ,\"rateType\":{\"Fixed\":0.08}\n",
" ,\"bondType\":{\"Sequential\":None}})\n",
" ,(\"B\",{\"balance\":1000\n",
" ,\"rate\":0.0\n",
" ,\"originBalance\":1000\n",
" ,\"originRate\":0.07\n",
" ,\"startDate\":\"2020-01-03\"\n",
" ,\"rateType\":{\"Fixed\":0.00}\n",
" ,\"bondType\":{\"Equity\":None}\n",
" }))\n",
" ,((\"issuanceFee\",{\"type\":{\"fixFee\":30},\"feeStart\":\"2021-06-15\"})\n",
" ,(\"serviceFee\",{\"type\":{\"annualPctFee\":[(\"poolBalance\",),0.02]},\"feeStart\":\"2021-06-15\"})\n",
" ,(\"trusteeFee\",{\"type\":{\"annualPctFee\":[(\"poolBalance\",),0.01]},\"feeStart\":\"2021-06-15\"})\n",
" )\n",
" ,sampleWaterfall\n",
" ,[[\"CollectedInterest\",\"acc01\"]\n",
" ,[\"CollectedPrincipal\",\"acc01\"]\n",
" ,[\"CollectedPrepayment\",\"acc01\"]\n",
" ,[\"CollectedRecoveries\",\"acc01\"]]\n",
" ,None\n",
" ,None\n",
" ,None\n",
" ,None\n",
" ,(\"PreClosing\",\"Amortizing\")\n",
" )"
]
},
{
"cell_type": "markdown",
"id": "a4939032",
"metadata": {},
"source": [
"Adding a `call` assumption to trigger the `clean up` action in the waterfall"
]
},
{
"cell_type": "code",
"execution_count": 21,
"id": "d30e0a2b",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"
Warning Message from server:\n",
"\n",
"\n"
],
"text/plain": [
"Warning Message from server:\n",
"\n"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"from absbox import API,EnginePath\n",
"localAPI = API(EnginePath.DEV,check=False)\n",
"\n",
"r = localAPI.run(test01\n",
" ,poolAssump = None\n",
" ,runAssump = [(\"call\",(\"poolBalance\",300))]\n",
" ,read=True)"
]
},
{
"cell_type": "markdown",
"id": "6ca315c0",
"metadata": {},
"source": [
"#### On Closing Day\n",
"\n",
"The action only performs on `Closing Day` for deal with `PreClosing` status"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "c094dd30",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'cutoff': '2021-03-01',\n",
" 'closing': '2021-06-15',\n",
" 'firstPay': '2021-07-26',\n",
" 'payFreq': ['DayOfMonth', 20],\n",
" 'poolFreq': 'MonthEnd',\n",
" 'stated': '2030-01-01'}"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"test01.dates"
]
},
{
"cell_type": "markdown",
"id": "b83c924c",
"metadata": {},
"source": [
"Action to be performed on `Closing Day`"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "176075dd",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[['calcAndPayFee', 'acc01', ['issuanceFee']]]"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"sampleWaterfall['closingDay']"
]
},
{
"cell_type": "markdown",
"id": "7f185e02",
"metadata": {},
"source": [
"Transaction log from the account "
]
},
{
"cell_type": "code",
"execution_count": 35,
"id": "e457ea53",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" balance | \n",
" change | \n",
" memo | \n",
"
\n",
" \n",
" | date | \n",
" | \n",
" | \n",
" | \n",
"
\n",
" \n",
" \n",
" \n",
" | 2021-06-15 | \n",
" 0.00 | \n",
" 0.00 | \n",
" <Pool:CollectedRecoveries> | \n",
"
\n",
" \n",
" | 2021-06-15 | \n",
" 0.00 | \n",
" 0.00 | \n",
" <Pool:CollectedPrepayment> | \n",
"
\n",
" \n",
" | 2021-06-15 | \n",
" 268.63 | \n",
" 268.63 | \n",
" <Pool:CollectedPrincipal> | \n",
"
\n",
" \n",
" | 2021-06-15 | \n",
" 324.60 | \n",
" 55.97 | \n",
" <Pool:CollectedInterest> | \n",
"
\n",
" \n",
" | 2021-06-15 | \n",
" 324.60 | \n",
" 0.00 | \n",
" <SeqPayFee:serviceFee> | \n",
"
\n",
" \n",
" | 2021-06-15 | \n",
" 294.60 | \n",
" -30.00 | \n",
" <SeqPayFee:issuanceFee> | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" balance change memo\n",
"date \n",
"2021-06-15 0.00 0.00 \n",
"2021-06-15 0.00 0.00 \n",
"2021-06-15 268.63 268.63 \n",
"2021-06-15 324.60 55.97 \n",
"2021-06-15 324.60 0.00 \n",
"2021-06-15 294.60 -30.00 "
]
},
"execution_count": 35,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"r['accounts']['acc01'].loc['2021-06-15']"
]
},
{
"cell_type": "markdown",
"id": "b20e6a6b",
"metadata": {},
"source": [
"#### Pool Collect Days"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "16b978e3",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'cutoff': '2021-03-01',\n",
" 'closing': '2021-06-15',\n",
" 'firstPay': '2021-07-26',\n",
" 'payFreq': ['DayOfMonth', 20],\n",
" 'poolFreq': 'MonthEnd',\n",
" 'stated': '2030-01-01'}"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"test01.dates"
]
},
{
"cell_type": "markdown",
"id": "841b5257",
"metadata": {},
"source": [
"The action in the `endOfCollection` will be performed each time when collecting proceeds from the pool\n",
"\n",
"The dates were described by `poolFreq`"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "a332671a",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[['calcAndPayFee', 'acc01', ['serviceFee']]]"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"sampleWaterfall['endOfCollection']"
]
},
{
"cell_type": "code",
"execution_count": 34,
"id": "1864db4b",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" balance | \n",
" change | \n",
" memo | \n",
"
\n",
" \n",
" | date | \n",
" | \n",
" | \n",
" | \n",
"
\n",
" \n",
" \n",
" \n",
" | 2021-07-31 | \n",
" 0.00 | \n",
" 0.00 | \n",
" <Pool:CollectedRecoveries> | \n",
"
\n",
" \n",
" | 2021-07-31 | \n",
" 0.00 | \n",
" 0.00 | \n",
" <Pool:CollectedPrepayment> | \n",
"
\n",
" \n",
" | 2021-07-31 | \n",
" 68.28 | \n",
" 68.28 | \n",
" <Pool:CollectedPrincipal> | \n",
"
\n",
" \n",
" | 2021-07-31 | \n",
" 81.15 | \n",
" 12.87 | \n",
" <Pool:CollectedInterest> | \n",
"
\n",
" \n",
" | 2021-07-31 | \n",
" 77.87 | \n",
" -3.28 | \n",
" <SeqPayFee:serviceFee> | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" balance change memo\n",
"date \n",
"2021-07-31 0.00 0.00 \n",
"2021-07-31 0.00 0.00 \n",
"2021-07-31 68.28 68.28 \n",
"2021-07-31 81.15 12.87 \n",
"2021-07-31 77.87 -3.28 "
]
},
"execution_count": 34,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"r['accounts']['acc01'].loc['2021-07-31']"
]
},
{
"cell_type": "markdown",
"id": "683a27a4",
"metadata": {},
"source": [
"#### Distribution Day"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "d3e6a6fe",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'cutoff': '2021-03-01',\n",
" 'closing': '2021-06-15',\n",
" 'firstPay': '2021-07-26',\n",
" 'payFreq': ['DayOfMonth', 20],\n",
" 'poolFreq': 'MonthEnd',\n",
" 'stated': '2030-01-01'}"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"test01.dates"
]
},
{
"cell_type": "markdown",
"id": "80459ae8",
"metadata": {},
"source": [
"The action in the `amortizing` will be performed each time on the dates were described by `payFreq`"
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "ca9e922a",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[['calcAndPayFee', 'acc01', ['trusteeFee']],\n",
" ['accrueAndPayInt', 'acc01', ['A1']],\n",
" ['payPrin', 'acc01', ['A1']],\n",
" ['payPrin', 'acc01', ['B']],\n",
" ['payIntResidual', 'acc01', 'B']]"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"sampleWaterfall['amortizing']"
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "abf4bde0",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" balance | \n",
" change | \n",
" memo | \n",
"
\n",
" \n",
" | date | \n",
" | \n",
" | \n",
" | \n",
"
\n",
" \n",
" \n",
" \n",
" | 2021-08-20 | \n",
" 77.61 | \n",
" -0.26 | \n",
" <SeqPayFee:trusteeFee> | \n",
"
\n",
" \n",
" | 2021-08-20 | \n",
" 74.18 | \n",
" -3.43 | \n",
" <PayInt:A1> | \n",
"
\n",
" \n",
" | 2021-08-20 | \n",
" 0.00 | \n",
" -74.18 | \n",
" <PayPrin:A1> | \n",
"
\n",
" \n",
" | 2021-08-20 | \n",
" 0.00 | \n",
" 0.00 | \n",
" <PayPrin:B> | \n",
"
\n",
" \n",
" | 2021-08-20 | \n",
" 0.00 | \n",
" 0.00 | \n",
" <PayYield:B> | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" balance change memo\n",
"date \n",
"2021-08-20 77.61 -0.26 \n",
"2021-08-20 74.18 -3.43 \n",
"2021-08-20 0.00 -74.18 \n",
"2021-08-20 0.00 0.00 \n",
"2021-08-20 0.00 0.00 "
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"r['accounts']['acc01'].loc['2021-08-20']"
]
},
{
"cell_type": "markdown",
"id": "754cc678",
"metadata": {},
"source": [
"#### Clean Up\n",
"\n",
"The `clean up` waterfall only perform when the deal met the conditin from `runAssump` assumption\n",
"\n",
"In this case, the `clean up` happens at date `2023-06-20`,we can inspect that via `result``status`"
]
},
{
"cell_type": "code",
"execution_count": 25,
"id": "6e6a080a",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" Date | \n",
" From | \n",
" To | \n",
"
\n",
" \n",
" \n",
" \n",
" | 0 | \n",
" 2021-06-15 | \n",
" PreClosing | \n",
" Amortizing | \n",
"
\n",
" \n",
" | 1 | \n",
" 2023-06-20 | \n",
" Amortizing | \n",
" Called | \n",
"
\n",
" \n",
" | 2 | \n",
" 2023-06-20 | \n",
" DealEnd | \n",
" Clean Up | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Date From To\n",
"0 2021-06-15 PreClosing Amortizing\n",
"1 2023-06-20 Amortizing Called\n",
"2 2023-06-20 DealEnd Clean Up"
]
},
"execution_count": 25,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"r['result']['status']"
]
},
{
"cell_type": "markdown",
"id": "08c07600",
"metadata": {},
"source": [
"We are able to identify the actions via account transaction"
]
},
{
"cell_type": "code",
"execution_count": 24,
"id": "be0d08eb",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" balance | \n",
" change | \n",
" memo | \n",
"
\n",
" \n",
" | date | \n",
" | \n",
" | \n",
" | \n",
"
\n",
" \n",
" \n",
" \n",
" | 2023-06-20 | \n",
" 80.52 | \n",
" -0.09 | \n",
" <SeqPayFee:trusteeFee> | \n",
"
\n",
" \n",
" | 2023-06-20 | \n",
" 80.52 | \n",
" 0.00 | \n",
" <PayInt:A1> | \n",
"
\n",
" \n",
" | 2023-06-20 | \n",
" 80.52 | \n",
" 0.00 | \n",
" <PayPrin:A1> | \n",
"
\n",
" \n",
" | 2023-06-20 | \n",
" 78.51 | \n",
" -2.01 | \n",
" <PayPrin:B> | \n",
"
\n",
" \n",
" | 2023-06-20 | \n",
" 0.00 | \n",
" -78.51 | \n",
" <PayYield:B> | \n",
"
\n",
" \n",
" | 2023-06-20 | \n",
" 240.24 | \n",
" 240.24 | \n",
" <Liquidation> | \n",
"
\n",
" \n",
" | 2023-06-20 | \n",
" 0.00 | \n",
" -240.24 | \n",
" <PayYield:B> | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" balance change memo\n",
"date \n",
"2023-06-20 80.52 -0.09 \n",
"2023-06-20 80.52 0.00 \n",
"2023-06-20 80.52 0.00 \n",
"2023-06-20 78.51 -2.01 \n",
"2023-06-20 0.00 -78.51 \n",
"2023-06-20 240.24 240.24 \n",
"2023-06-20 0.00 -240.24 "
]
},
"execution_count": 24,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"r['accounts']['acc01'].loc['2023-06-20']"
]
},
{
"cell_type": "markdown",
"id": "70602b3b",
"metadata": {},
"source": [
"#### Summary Via `[result][waterfall]`\n",
"\n",
"There is a function that would summaries which waterfall actions are being executed by dates"
]
},
{
"cell_type": "code",
"execution_count": 28,
"id": "de26588b",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" Date | \n",
" Waterfall Location | \n",
"
\n",
" \n",
" \n",
" \n",
" | 0 | \n",
" 2021-06-15 | \n",
" <EndOfPoolCollection> | \n",
"
\n",
" \n",
" | 1 | \n",
" 2021-06-15 | \n",
" <OnClosingDay> | \n",
"
\n",
" \n",
" | 2 | \n",
" 2021-06-30 | \n",
" <EndOfPoolCollection> | \n",
"
\n",
" \n",
" | 3 | \n",
" 2021-07-26 | \n",
" <DistributionDay:<Amortizing>> | \n",
"
\n",
" \n",
" | 4 | \n",
" 2021-07-31 | \n",
" <EndOfPoolCollection> | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Date Waterfall Location\n",
"0 2021-06-15 \n",
"1 2021-06-15 \n",
"2 2021-06-30 \n",
"3 2021-07-26 >\n",
"4 2021-07-31 "
]
},
"execution_count": 28,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"r['result']['waterfall'].head()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.9"
}
},
"nbformat": 4,
"nbformat_minor": 5
}