Skip to content

Commit f5181c7

Browse files
committed
expose bond schedule index by integer
1 parent edccd54 commit f5181c7

File tree

4 files changed

+45
-6
lines changed

4 files changed

+45
-6
lines changed

absbox/local/base.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,9 @@ class SubAssetType(str, enum.Enum):
225225
Installment = "Installment"
226226
FixedAsset = "FixedAsset"
227227

228-
228+
dealStatInt = set(["BondPaidPeriod","PoolCollectedPeriod"])
229+
dealStatBool = set([])
230+
dealStatBalance = set([])
231+
dealStatRate = set([])
229232

230233
inf = 179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137216

absbox/local/component.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,8 @@ def mkBondType(x):
584584
match x:
585585
case {"固定摊还": schedule} | {"PAC": schedule}:
586586
return mkTag(("PAC", mkTag(("BalanceCurve", schedule))))
587+
case {"BalanceByPeriod": bals}:
588+
return mkTag(("AmtByPeriod", mkTag(("WithTrailVal", bals))))
587589
case {"过手摊还": None} | {"Sequential": None} | "Sequential" | "过手摊还":
588590
return mkTag(("Sequential"))
589591
case {"锁定摊还": _after} | {"Lockout": _after}:
@@ -744,7 +746,6 @@ def mkBnd(bn, x:dict):
744746
, "bndStmt": mStmt
745747
, "tag": "Bond"}
746748
case _:
747-
print(" got here",x)
748749
raise RuntimeError(f"Failed to match bond:{bn},{x}:mkBnd")
749750

750751

absbox/local/generic.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ class Generic:
4848
custom: dict = None
4949
ledgers: dict = None
5050
rateCap: dict = None
51+
stats: dict = None
5152

5253
@property
5354
def json(self) -> dict:
@@ -74,13 +75,24 @@ def json(self) -> dict:
7475
"triggers": renameKs2({k: {_k: mkTrigger(_v) for (_k,_v) in v.items() } for (k, v) in self.trigger.items()},englishDealCycle) if self.trigger else None,
7576
"liqProvider": {ln: mkLiqProvider(ln, lo | {"start":lastCloseDate} )
7677
for ln,lo in self.liqFacility.items() } if self.liqFacility else None,
77-
"ledgers": {ln: mkLedger(ln, v) for ln,v in self.ledgers.items()} if self.ledgers else None
78+
"ledgers": {ln: mkLedger(ln, v) for ln,v in self.ledgers.items()} if self.ledgers else None,
79+
"stats": self.buildStats()
7880
}
7981

8082
_dealType = identify_deal_type(_r)
8183

8284
return mkTag((_dealType, _r))
8385

86+
def buildStats(self,):
87+
if self.stats is None:
88+
return [{},{},{},{}]
89+
a = {k:v for k,v in self.stats.items() if k in dealStatBalance }
90+
b = {k:v for k,v in self.stats.items() if k in dealStatRate }
91+
c = {k:v for k,v in self.stats.items() if k in dealStatBool }
92+
d = {k:v for k,v in self.stats.items() if k in dealStatInt }
93+
94+
# bal, rate, bool, int
95+
return [a,b,c,d]
8496

8597
def read_pricing(self, pricing):
8698
return earlyReturnNone(mkPricingAssump, pricing)

docs/source/modeling.rst

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ To model them via sequential parameter ( *Not Recommend* ):
9393
,<Custom data> # optional
9494
,<Ledgers> # optional
9595
,<Rate Caps> # optional
96+
,<Deal Stats> # optional
9697
)
9798
9899
.. _Generic ABS:
@@ -2096,10 +2097,11 @@ syntax
20962097
20972098
Principal
20982099
^^^^^^^^^^^
2099-
there are 4 types of `Principal` for bonds/tranches
2100+
there are 5 types of `Principal` for bonds/tranches
21002101
21012102
* ``Sequential``: can be paid down as much as its oustanding balance
2102-
* ``PAC``: Balance of bond can only be paid down by a predefined schedule
2103+
* ``PAC``: Balance of bond can only be paid down by a predefined balance schedule
2104+
* ``BalanceByPeriod``: Balance of bond can only be paid down by a predefined balance schedule ,indexed by bond paid period
21032105
* ``Lockout``: Principal won't be paid after lockout date
21042106
* ``Equity``: No interest and shall serve as junior tranche
21052107
@@ -2123,7 +2125,7 @@ A bond with target amortize balances, it will stop recieving principal once its
21232125
21242126
21252127
.. code-block:: python
2126-
2128+
21272129
("A1",{"balance":1000
21282130
,"rate":0.07
21292131
,"originBalance":1000
@@ -2137,6 +2139,27 @@ A bond with target amortize balances, it will stop recieving principal once its
21372139
,["2021-10-20",0]
21382140
]}})
21392141
2142+
BalanceByPeriod
2143+
""""""""""""""""""
2144+
2145+
.. versionadded:: 0.42.0
2146+
2147+
.. code-block:: python
2148+
2149+
("A1",{"balance":1000
2150+
,"rate":0.07
2151+
,"originBalance":1000
2152+
,"originRate":0.07
2153+
,"startDate":"2020-01-03"
2154+
,"rateType":{"Fixed":0.08}
2155+
,"bondType":{"BalanceByPeriod":
2156+
[[0,900]
2157+
,[1,850]
2158+
,[5,800]
2159+
,[6,0]
2160+
]}
2161+
})
2162+
21402163
21412164
Lockout
21422165
"""""""""""""

0 commit comments

Comments
 (0)