{
"cells": [
{
"cell_type": "markdown",
"id": "b6a6179c",
"metadata": {},
"source": [
"### CLO IC Test (WIP)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b8d9117c",
"metadata": {},
"outputs": [],
"source": [
"import pandas as pd\n",
"pd.set_option('display.max_rows', None)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "39cc2d83",
"metadata": {},
"outputs": [],
"source": [
"from absbox import Generic\n",
"\n",
"bonds = (\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\":{\"Sequential\":None}\n",
" })\n",
" ,(\"E\",{\"balance\":500\n",
" ,\"rate\":0.0\n",
" ,\"originBalance\":500\n",
" ,\"originRate\":0.07\n",
" ,\"startDate\":\"2020-01-03\"\n",
" ,\"rateType\":{\"Fixed\":0.00}\n",
" ,\"bondType\":{\"Equity\":None}\n",
" }) \n",
")\n",
"\n",
"bond_OCs = [(\"A1\",(\"A1\",),1.1),(\"B\",(\"A1\",\"B\"),1.05)]\n",
"\n",
"OC_triggers = {f\"OC_{tName}\":\n",
" {\"condition\":((\"/\",(\"poolBalance\",)\n",
" ,(\"bondBalance\",*b))\n",
" ,\"<\"\n",
" ,threshold)\n",
" ,\"effects\":None\n",
" ,\"status\":False\n",
" ,\"curable\":True}\n",
" for (tName,b,threshold) in bond_OCs}\n",
"\n",
"bond_ICs = [(\"A\",(\"A1\",),1.05),(\"B\",(\"A1\",\"B\"),1.03)]\n",
"\n",
"IC_triggers = {f\"IC_{tName}\":\n",
" {\"condition\":[\"all\"\n",
" ,[(\"bondDueInt\",*b),\">\",0]\n",
" ,[(\"/\", (\"accountBalance\",\"intAcc\"),(\"bondDueInt\",*b))\n",
" ,\"<\"\n",
" ,threshold]\n",
" ]\n",
" ,\"effects\":None\n",
" ,\"status\":False\n",
" ,\"curable\":True}\n",
" for (tName,b,threshold) in bond_OCs}\n",
"\n",
"IC_triggerNames = list(IC_triggers.keys())\n",
"OC_triggerNames = list(OC_triggers.keys())\n",
"\n",
"\n",
"CLO_sample = Generic(\n",
" \"CLO_sample\"\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.02\n",
" ,\"remainTerm\":30\n",
" ,\"status\":\"current\"}]]}\n",
" ,((\"intAcc\",{\"balance\":0}),(\"prinAcc\",{\"balance\":0}))\n",
" ,bonds\n",
" ,((\"seniorFee\",{\"type\":{\"annualPctFee\":[(\"poolBalance\",),0.003]},\"feeStart\":\"2021-06-15\"})\n",
" ,(\"subFee\",{\"type\":{\"annualPctFee\":[(\"poolBalance\",),0.002]},\"feeStart\":\"2021-06-15\"})\n",
" ,)\n",
" ,{\"amortizing\":[\n",
" # intereset waterfall\n",
" # accrue and pay senior fee \n",
" [\"calcAndPayFee\",\"intAcc\",['seniorFee']]\n",
" # accrue interest for both bonds (NO payment) \n",
" ,[\"calcInt\",\"A1\",\"B\"]\n",
" # calculate OC and IC test\n",
" ,['runTriggers',*(IC_triggerNames)]\n",
" # payout interest of A1 \n",
" ,[\"payInt\",\"intAcc\",[\"A1\"]]\n",
" # if all IC test is passing \n",
" ,[\"IfElse\",[(\"trigger\",\"InDistribution\", \"IC_A1\"),False],\n",
" # if passing\n",
" [[\"payInt\",\"intAcc\",[\"B\"]]\n",
" ,[\"calcAndPayFee\",\"intAcc\",['subFee']]\n",
" ,[\"payIntResidual\",\"intAcc\",\"E\"]]\n",
" # if failing, redemption senior to satisfy IC\n",
" ,[[\"payPrin\",\"intAcc\",[\"A1\"]\n",
" ,{\"limit\":{\"formula\":(\"bondBalance\",\"A1\")}}\n",
" ]\n",
" # update IC test again\n",
" #,['runTriggers',*IC_triggerNames]\n",
" # if IC test is passing\n",
" ,[\"If\",[(\"trigger\",\"InDistribution\", \"IC_A1\"), False],\n",
" # pay interest of B and residual to E\n",
" [\"payInt\",\"intAcc\",[\"B\"]],\n",
" [\"calcAndPayFee\",\"intAcc\",['subFee']],\n",
" [\"payIntResidual\",\"intAcc\",\"E\"]]\n",
" ]]\n",
" # principal waterfall\n",
" ,[\"payPrinBySeq\",\"prinAcc\",[\"A1\",\"B\"]]\n",
" ,[\"payPrinResidual\",\"prinAcc\",[\"E\"]]\n",
" ]}\n",
" ,[[\"CollectedInterest\",\"intAcc\"]\n",
" ,[\"CollectedPrincipal\",\"prinAcc\"]\n",
" ,[\"CollectedPrepayment\",\"prinAcc\"]\n",
" ,[\"CollectedRecoveries\",\"prinAcc\"]]\n",
" ,None\n",
" ,None\n",
" ,None\n",
" ,{\"InDistribution\":OC_triggers | IC_triggers}\n",
" ,(\"PreClosing\",\"Amortizing\")\n",
" )"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "79adf3c9",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"
Connecting engine server -> https://absbox.org/api/dev\n",
"\n"
],
"text/plain": [
"\u001b[1;35mConnecting engine server -> \u001b[0m\u001b[1;4;35mhttps://absbox.org/api/dev\u001b[0m\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"✅Connected, local lib:0.28.7, server:0.28.11\n",
"\n"
],
"text/plain": [
"✅\u001b[1;32mConnected, local li\u001b[0m\u001b[1;32mb:0\u001b[0m\u001b[1;32m.\u001b[0m\u001b[1;32m28.7\u001b[0m\u001b[1;32m, server:\u001b[0m\u001b[1;32m0.28\u001b[0m\u001b[1;32m.\u001b[0m\u001b[1;32m11\u001b[0m\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"Warning Message from server:\n",
"Bond E is not paid off\n",
"\n"
],
"text/plain": [
"Warning Message from server:\n",
"\u001b[1;33mBond E is not paid off\u001b[0m\n"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"from absbox import API,mkDeal,EnginePath\n",
"localAPI = API(EnginePath.DEV,check=False)\n",
"\n",
"r = localAPI.run(CLO_sample\n",
" ,poolAssump = None\n",
" ,runAssump = None\n",
" ,read=True)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f748d10e",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" status | \n",
" memo | \n",
"
\n",
" \n",
" | date | \n",
" | \n",
" | \n",
"
\n",
" \n",
" \n",
" \n",
" | 2021-07-26 | \n",
" False | \n",
" <Tag:1.74 L 1.10> | \n",
"
\n",
" \n",
" | 2021-08-20 | \n",
" True | \n",
" <Tag:0.91 L 1.10> | \n",
"
\n",
" \n",
" | 2021-08-20 | \n",
" True | \n",
" <Tag:0.00 L 1.10> | \n",
"
\n",
" \n",
" | 2021-09-20 | \n",
" True | \n",
" <Tag:0.70 L 1.10> | \n",
"
\n",
" \n",
" | 2021-09-20 | \n",
" True | \n",
" <Tag:0.00 L 1.10> | \n",
"
\n",
" \n",
" | 2021-10-20 | \n",
" True | \n",
" <Tag:0.62 L 1.10> | \n",
"
\n",
" \n",
" | 2021-10-20 | \n",
" True | \n",
" <Tag:0.00 L 1.10> | \n",
"
\n",
" \n",
" | 2021-11-20 | \n",
" True | \n",
" <Tag:0.57 L 1.10> | \n",
"
\n",
" \n",
" | 2021-11-20 | \n",
" True | \n",
" <Tag:0.00 L 1.10> | \n",
"
\n",
" \n",
" | 2021-12-20 | \n",
" True | \n",
" <Tag:0.58 L 1.10> | \n",
"
\n",
" \n",
" | 2021-12-20 | \n",
" True | \n",
" <Tag:0.00 L 1.10> | \n",
"
\n",
" \n",
" | 2022-01-20 | \n",
" True | \n",
" <Tag:0.62 L 1.10> | \n",
"
\n",
" \n",
" | 2022-01-20 | \n",
" True | \n",
" <Tag:0.00 L 1.10> | \n",
"
\n",
" \n",
" | 2022-02-20 | \n",
" True | \n",
" <Tag:0.74 L 1.10> | \n",
"
\n",
" \n",
" | 2022-02-20 | \n",
" True | \n",
" <Tag:0.00 L 1.10> | \n",
"
\n",
" \n",
" | 2022-03-20 | \n",
" False | \n",
" <Tag:1.19 L 1.10> | \n",
"
\n",
" \n",
" | 2022-04-20 | \n",
" False | \n",
" <Tag:2.65 L 1.10> | \n",
"
\n",
" \n",
" | 2022-05-20 | \n",
" False | \n",
" <Tag:5.85 L 1.10> | \n",
"
\n",
" \n",
" | 2022-06-20 | \n",
" False | \n",
" <Tag:inf L 1.10> | \n",
"
\n",
" \n",
" | 2022-07-20 | \n",
" False | \n",
" <Tag:inf L 1.10> | \n",
"
\n",
" \n",
" | 2022-08-20 | \n",
" False | \n",
" <Tag:inf L 1.10> | \n",
"
\n",
" \n",
" | 2022-09-20 | \n",
" False | \n",
" <Tag:inf L 1.10> | \n",
"
\n",
" \n",
" | 2022-10-20 | \n",
" False | \n",
" <Tag:inf L 1.10> | \n",
"
\n",
" \n",
" | 2022-11-20 | \n",
" False | \n",
" <Tag:inf L 1.10> | \n",
"
\n",
" \n",
" | 2022-12-20 | \n",
" False | \n",
" <Tag:inf L 1.10> | \n",
"
\n",
" \n",
" | 2023-01-20 | \n",
" False | \n",
" <Tag:inf L 1.10> | \n",
"
\n",
" \n",
" | 2023-02-20 | \n",
" False | \n",
" <Tag:inf L 1.10> | \n",
"
\n",
" \n",
" | 2023-03-20 | \n",
" False | \n",
" <Tag:inf L 1.10> | \n",
"
\n",
" \n",
" | 2023-04-20 | \n",
" False | \n",
" <Tag:inf L 1.10> | \n",
"
\n",
" \n",
" | 2023-05-20 | \n",
" False | \n",
" <Tag:inf L 1.10> | \n",
"
\n",
" \n",
" | 2023-06-20 | \n",
" False | \n",
" <Tag:inf L 1.10> | \n",
"
\n",
" \n",
" | 2023-07-20 | \n",
" False | \n",
" <Tag:inf L 1.10> | \n",
"
\n",
" \n",
" | 2023-08-20 | \n",
" False | \n",
" <Tag:inf L 1.10> | \n",
"
\n",
" \n",
" | 2023-09-20 | \n",
" False | \n",
" <Tag:inf L 1.10> | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" status memo\n",
"date \n",
"2021-07-26 False \n",
"2021-08-20 True \n",
"2021-08-20 True \n",
"2021-09-20 True \n",
"2021-09-20 True \n",
"2021-10-20 True \n",
"2021-10-20 True \n",
"2021-11-20 True \n",
"2021-11-20 True \n",
"2021-12-20 True \n",
"2021-12-20 True \n",
"2022-01-20 True \n",
"2022-01-20 True \n",
"2022-02-20 True \n",
"2022-02-20 True \n",
"2022-03-20 False \n",
"2022-04-20 False \n",
"2022-05-20 False \n",
"2022-06-20 False \n",
"2022-07-20 False \n",
"2022-08-20 False \n",
"2022-09-20 False \n",
"2022-10-20 False \n",
"2022-11-20 False \n",
"2022-12-20 False \n",
"2023-01-20 False \n",
"2023-02-20 False \n",
"2023-03-20 False \n",
"2023-04-20 False \n",
"2023-05-20 False \n",
"2023-06-20 False \n",
"2023-07-20 False \n",
"2023-08-20 False \n",
"2023-09-20 False "
]
},
"execution_count": 65,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"r['triggers']['InWF']['IC_A1'].head(20)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ede47df5",
"metadata": {},
"outputs": [],
"source": [
"r['triggers']['InWF']['IC_A1'].head(20).loc['2021-07-26'].memo"
]
},
{
"cell_type": "code",
"execution_count": 66,
"id": "1e8ee62d",
"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-26 | \n",
" 13.69 | \n",
" -0.23 | \n",
" <SeqPayFee:seniorFee> | \n",
"
\n",
" \n",
" | 2021-07-26 | \n",
" 5.83 | \n",
" -7.86 | \n",
" <PayInt:A1> | \n",
"
\n",
" \n",
" | 2021-07-26 | \n",
" 5.83 | \n",
" 0.00 | \n",
" <PayInt:B> | \n",
"
\n",
" \n",
" | 2021-07-26 | \n",
" 5.68 | \n",
" -0.15 | \n",
" <SeqPayFee:subFee> | \n",
"
\n",
" \n",
" | 2021-07-26 | \n",
" 0.00 | \n",
" -5.68 | \n",
" <PayYield:E> | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" balance change memo\n",
"date \n",
"2021-07-26 13.69 -0.23 \n",
"2021-07-26 5.83 -7.86 \n",
"2021-07-26 5.83 0.00 \n",
"2021-07-26 5.68 -0.15 \n",
"2021-07-26 0.00 -5.68 "
]
},
"execution_count": 66,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"r['accounts']['intAcc'].loc[\"2021-07-26\"]"
]
},
{
"cell_type": "code",
"execution_count": 67,
"id": "08fd886d",
"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",
" 3.11 | \n",
" -0.07 | \n",
" <SeqPayFee:seniorFee> | \n",
"
\n",
" \n",
" | 2021-08-20 | \n",
" 0.00 | \n",
" -3.11 | \n",
" <PayInt:A1> | \n",
"
\n",
" \n",
" | 2021-08-20 | \n",
" 0.00 | \n",
" 0.00 | \n",
" [<PayPrin:A1>, <DS:CurrentBondBalanceOf [\"A1\"]>] | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" balance change memo\n",
"date \n",
"2021-08-20 3.11 -0.07 \n",
"2021-08-20 0.00 -3.11 \n",
"2021-08-20 0.00 0.00 [, ]"
]
},
"execution_count": 67,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"r['accounts']['intAcc'].loc[\"2021-08-20\"]"
]
},
{
"cell_type": "code",
"execution_count": 68,
"id": "b1d1f1ec",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" balance | \n",
" interest | \n",
" principal | \n",
" rate | \n",
" cash | \n",
" intDue | \n",
" intOverInt | \n",
" factor | \n",
" memo | \n",
"
\n",
" \n",
" | date | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
"
\n",
" \n",
" \n",
" \n",
" | 2021-07-26 | \n",
" 712.96 | \n",
" 7.86 | \n",
" 287.04 | \n",
" 0.07 | \n",
" 294.90 | \n",
" 0.00 | \n",
" 0 | \n",
" 0.71296 | \n",
" [<PayInt:A1>, <PayPrin:A1>] | \n",
"
\n",
" \n",
" | 2021-08-20 | \n",
" 640.90 | \n",
" 3.11 | \n",
" 72.06 | \n",
" 0.07 | \n",
" 75.17 | \n",
" 0.30 | \n",
" 0 | \n",
" 0.64090 | \n",
" [[<PayInt:A1>, <PayPrin:A1>], <PayPrin:A1>] | \n",
"
\n",
" \n",
" | 2021-09-20 | \n",
" 568.72 | \n",
" 2.90 | \n",
" 72.18 | \n",
" 0.07 | \n",
" 75.08 | \n",
" 1.21 | \n",
" 0 | \n",
" 0.56872 | \n",
" [[<PayInt:A1>, <PayPrin:A1>], <PayPrin:A1>] | \n",
"
\n",
" \n",
" | 2021-10-20 | \n",
" 496.42 | \n",
" 2.80 | \n",
" 72.30 | \n",
" 0.07 | \n",
" 75.10 | \n",
" 1.68 | \n",
" 0 | \n",
" 0.49642 | \n",
" [[<PayInt:A1>, <PayPrin:A1>], <PayPrin:A1>] | \n",
"
\n",
" \n",
" | 2021-11-20 | \n",
" 424.00 | \n",
" 2.67 | \n",
" 72.42 | \n",
" 0.07 | \n",
" 75.09 | \n",
" 1.96 | \n",
" 0 | \n",
" 0.42400 | \n",
" [[<PayInt:A1>, <PayPrin:A1>], <PayPrin:A1>] | \n",
"
\n",
" \n",
" | 2021-12-20 | \n",
" 351.46 | \n",
" 2.57 | \n",
" 72.54 | \n",
" 0.07 | \n",
" 75.11 | \n",
" 1.82 | \n",
" 0 | \n",
" 0.35146 | \n",
" [[<PayInt:A1>, <PayPrin:A1>], <PayPrin:A1>] | \n",
"
\n",
" \n",
" | 2022-01-20 | \n",
" 278.80 | \n",
" 2.44 | \n",
" 72.66 | \n",
" 0.07 | \n",
" 75.10 | \n",
" 1.46 | \n",
" 0 | \n",
" 0.27880 | \n",
" [[<PayInt:A1>, <PayPrin:A1>], <PayPrin:A1>] | \n",
"
\n",
" \n",
" | 2022-02-20 | \n",
" 206.02 | \n",
" 2.33 | \n",
" 72.78 | \n",
" 0.07 | \n",
" 75.11 | \n",
" 0.78 | \n",
" 0 | \n",
" 0.20602 | \n",
" [[<PayInt:A1>, <PayPrin:A1>], <PayPrin:A1>] | \n",
"
\n",
" \n",
" | 2022-03-20 | \n",
" 133.12 | \n",
" 1.88 | \n",
" 72.90 | \n",
" 0.07 | \n",
" 74.78 | \n",
" 0.00 | \n",
" 0 | \n",
" 0.13312 | \n",
" [<PayInt:A1>, <PayPrin:A1>] | \n",
"
\n",
" \n",
" | 2022-04-20 | \n",
" 60.11 | \n",
" 0.79 | \n",
" 73.01 | \n",
" 0.07 | \n",
" 73.80 | \n",
" 0.00 | \n",
" 0 | \n",
" 0.06011 | \n",
" [<PayInt:A1>, <PayPrin:A1>] | \n",
"
\n",
" \n",
" | 2022-05-20 | \n",
" 0.00 | \n",
" 0.34 | \n",
" 60.11 | \n",
" 0.07 | \n",
" 60.45 | \n",
" 0.00 | \n",
" 0 | \n",
" 0.00000 | \n",
" [<PayInt:A1>, <PayPrin:A1>] | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" balance interest principal rate cash intDue intOverInt \\\n",
"date \n",
"2021-07-26 712.96 7.86 287.04 0.07 294.90 0.00 0 \n",
"2021-08-20 640.90 3.11 72.06 0.07 75.17 0.30 0 \n",
"2021-09-20 568.72 2.90 72.18 0.07 75.08 1.21 0 \n",
"2021-10-20 496.42 2.80 72.30 0.07 75.10 1.68 0 \n",
"2021-11-20 424.00 2.67 72.42 0.07 75.09 1.96 0 \n",
"2021-12-20 351.46 2.57 72.54 0.07 75.11 1.82 0 \n",
"2022-01-20 278.80 2.44 72.66 0.07 75.10 1.46 0 \n",
"2022-02-20 206.02 2.33 72.78 0.07 75.11 0.78 0 \n",
"2022-03-20 133.12 1.88 72.90 0.07 74.78 0.00 0 \n",
"2022-04-20 60.11 0.79 73.01 0.07 73.80 0.00 0 \n",
"2022-05-20 0.00 0.34 60.11 0.07 60.45 0.00 0 \n",
"\n",
" factor memo \n",
"date \n",
"2021-07-26 0.71296 [, ] \n",
"2021-08-20 0.64090 [[, ], ] \n",
"2021-09-20 0.56872 [[, ], ] \n",
"2021-10-20 0.49642 [[, ], ] \n",
"2021-11-20 0.42400 [[, ], ] \n",
"2021-12-20 0.35146 [[, ], ] \n",
"2022-01-20 0.27880 [[, ], ] \n",
"2022-02-20 0.20602 [[, ], ] \n",
"2022-03-20 0.13312 [, ] \n",
"2022-04-20 0.06011 [, ] \n",
"2022-05-20 0.00000 [, ] "
]
},
"execution_count": 68,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"r['bonds']['A1']"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5a02fb0d",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "AbsBox (3.13.3)",
"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.13.3"
}
},
"nbformat": 4,
"nbformat_minor": 5
}