Skip to content

Commit 6aa824d

Browse files
committed
expose PSA
1 parent 7da8e9c commit 6aa824d

File tree

4 files changed

+60
-7
lines changed

4 files changed

+60
-7
lines changed

absbox/local/component.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1741,6 +1741,8 @@ def mkAssumpPrepay(x):
17411741
return mkTag(("PrepaymentCPR", vNum(r)))
17421742
case {"StressByCurve": [curve, assump]}:
17431743
return mkTag(("PrepayStressByTs", [ mkRateTs(curve), mkAssumpPrepay(assump)]))
1744+
case {"PSA": r}:
1745+
return mkTag(("PrepaymentPSA", vNum(r)))
17441746
case _ :
17451747
raise RuntimeError(f"failed to match {x}")
17461748

absbox/tests/regression/assets.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import pandas as pd
2+
from lenses import lens
3+
import toolz as tz
4+
import pytest
5+
import re, math
6+
7+
from absbox.tests.regression.assets import *
8+
9+
10+
m = ["Mortgage"
11+
,{"originBalance": 12000.0
12+
,"originRate": ["fix",0.045]
13+
,"originTerm": 80
14+
,"freq": "Monthly"
15+
,"type": "Level"
16+
,"originDate": "2021-02-01"}
17+
,{"currentBalance": 10000.0
18+
,"currentRate": 0.075
19+
,"remainTerm": 80
20+
,"status": "Current"}]

absbox/tests/regression/deals.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,4 @@
9898
,None
9999
,None
100100
,"Amortizing"
101-
)
102-
103-
test03 = tz.pipe(test01 & lens.pool
104-
105-
)
101+
)

absbox/tests/regression/main.py

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import re, math
66

77
from absbox.tests.regression.deals import *
8+
from absbox.tests.regression.assets import *
89

910
from absbox import API,EnginePath,readInspect,PickApiFrom
1011

@@ -16,7 +17,7 @@ def filterTxn(rs, f, rg):
1617

1718
@pytest.fixture
1819
def setup_api():
19-
api = API(EnginePath.DEV,check=False,lang='english')
20+
api = API(EnginePath.DEV, check=False,lang='english')
2021
return api
2122

2223
@pytest.mark.pool
@@ -99,4 +100,38 @@ def test_collect_01(setup_api):
99100
closeTo((r['pool']['flow']['PoolA'].loc[:'2021-04-15']["Principal"].values.sum() +\
100101
r['pool']['flow']['PoolB'].loc[:'2021-04-15']["Principal"].values.sum())*0.3
101102
, filterTxn( r['accounts']['acc03'].loc[:'2021-04-15'].to_dict('records'), 'memo', ".*CollectedPrincipal.*")[0]['change'])
102-
103+
104+
def toCprRates(mflow):
105+
return [ round(_, 3) for _ in (1 - (1 - mflow.Prepayment.shift(-1) / mflow.Balance)**12).to_list() ]
106+
107+
@pytest.mark.asset
108+
def test_asset_01(setup_api):
109+
""" PSA """
110+
r = setup_api.runAsset("2020-01-02"
111+
,[m]
112+
,poolAssump=("Pool"
113+
,("Mortgage", None, {"PSA":1.0}, None, None)
114+
,None
115+
,None)
116+
,read=True)
117+
118+
assert toCprRates(r[0])[:80] == ([ _/1000 for _ in range(2,62,2)] + [0.06]*50)
119+
120+
# m with 60 remaining term
121+
r = setup_api.runAsset("2020-01-02"
122+
,[m & lens[2]['remainTerm'].set(60)]
123+
,poolAssump=("Pool"
124+
,("Mortgage", None, {"PSA":1.0}, None, None)
125+
,None
126+
,None)
127+
,read=True)
128+
assert toCprRates(r[0])[:60] == ([ _/1000 for _ in range(2,62,2)][20:] + [0.06]*50)
129+
130+
r = setup_api.runAsset("2020-01-02"
131+
,[m & lens[2]['remainTerm'].set(10)]
132+
,poolAssump=("Pool"
133+
,("Mortgage", None, {"PSA":1.0}, None, None)
134+
,None
135+
,None)
136+
,read=True)
137+
assert toCprRates(r[0])[:10] == ([0.06]*10)

0 commit comments

Comments
 (0)