{ "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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
balancechangememo
date
2021-06-150.000.00<Pool:CollectedRecoveries>
2021-06-150.000.00<Pool:CollectedPrepayment>
2021-06-15268.63268.63<Pool:CollectedPrincipal>
2021-06-15324.6055.97<Pool:CollectedInterest>
2021-06-15324.600.00<SeqPayFee:serviceFee>
2021-06-15294.60-30.00<SeqPayFee:issuanceFee>
\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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
balancechangememo
date
2021-07-310.000.00<Pool:CollectedRecoveries>
2021-07-310.000.00<Pool:CollectedPrepayment>
2021-07-3168.2868.28<Pool:CollectedPrincipal>
2021-07-3181.1512.87<Pool:CollectedInterest>
2021-07-3177.87-3.28<SeqPayFee:serviceFee>
\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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
balancechangememo
date
2021-08-2077.61-0.26<SeqPayFee:trusteeFee>
2021-08-2074.18-3.43<PayInt:A1>
2021-08-200.00-74.18<PayPrin:A1>
2021-08-200.000.00<PayPrin:B>
2021-08-200.000.00<PayYield:B>
\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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
DateFromTo
02021-06-15PreClosingAmortizing
12023-06-20AmortizingCalled
22023-06-20DealEndClean Up
\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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
balancechangememo
date
2023-06-2080.52-0.09<SeqPayFee:trusteeFee>
2023-06-2080.520.00<PayInt:A1>
2023-06-2080.520.00<PayPrin:A1>
2023-06-2078.51-2.01<PayPrin:B>
2023-06-200.00-78.51<PayYield:B>
2023-06-20240.24240.24<Liquidation>
2023-06-200.00-240.24<PayYield:B>
\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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
DateWaterfall Location
02021-06-15<EndOfPoolCollection>
12021-06-15<OnClosingDay>
22021-06-30<EndOfPoolCollection>
32021-07-26<DistributionDay:<Amortizing>>
42021-07-31<EndOfPoolCollection>
\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 }