modelflowib 2.73__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- modelBLfunk.py +180 -0
- model_Excel.py +332 -0
- model_cvx.py +139 -0
- model_dynare.py +173 -0
- model_financial_stability.py +88 -0
- model_latex.py +497 -0
- model_latex_class.py +808 -0
- model_parquet_mixin.py +424 -0
- modelclass.py +9828 -0
- modelconstruct.py +1496 -0
- modelconstruct_estimation.py +2872 -0
- modeldash.py +265 -0
- modeldashboot.py +202 -0
- modeldashsidebar.py +456 -0
- modeldekom.py +651 -0
- modeldiff.py +561 -0
- modeldisplay.py +550 -0
- modelestimation.py +1776 -0
- modelestimator_new.py +2613 -0
- modelflowib-2.73.dist-info/METADATA +156 -0
- modelflowib-2.73.dist-info/RECORD +44 -0
- modelflowib-2.73.dist-info/WHEEL +5 -0
- modelflowib-2.73.dist-info/licenses/license.md +10 -0
- modelflowib-2.73.dist-info/top_level.txt +39 -0
- modelgrab.py +318 -0
- modelgrabgdx.py +584 -0
- modelgrabwf2.py +1107 -0
- modelhelp.py +543 -0
- modelhtml.py +606 -0
- modelinvert.py +250 -0
- modeljupyter.py +824 -0
- modeljupytermagic.py +813 -0
- modelmacrograb.py +98 -0
- modelmanipulation.py +1461 -0
- modelmf.py +349 -0
- modelnet.py +114 -0
- modelnewton.py +2178 -0
- modelnormalize.py +430 -0
- modelpattern.py +428 -0
- modelreport.py +2187 -0
- modeluserfunk.py +97 -0
- modelvis.py +1038 -0
- modelwidget.py +718 -0
- modelwidget_input.py +1933 -0
model_dynare.py
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
Created on Wed Jan 9 16:05:56 2019
|
|
4
|
+
Reads a list of expanded modfile (outputtet from dynare)
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@author: hanseni
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import re
|
|
11
|
+
import pandas as pd
|
|
12
|
+
import sys
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
import modelclass as mc
|
|
17
|
+
import modelmanipulation as mp
|
|
18
|
+
import modelpattern as pt
|
|
19
|
+
|
|
20
|
+
class grap_modfile():
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
'''Accept filenames as argument. The first file is asumed to be the main model
|
|
24
|
+
and gives the model its name
|
|
25
|
+
|
|
26
|
+
Instead of filenames a string with a .mod file can be accepted
|
|
27
|
+
|
|
28
|
+
:savepath: (path of first file ) Where to save
|
|
29
|
+
:save: (True) save the frm and mod files
|
|
30
|
+
:modelname: (name from first model file else "testmodel" for strings), name of model
|
|
31
|
+
|
|
32
|
+
The class contains among other:
|
|
33
|
+
|
|
34
|
+
:mthismodel: The actual model
|
|
35
|
+
:mresmodel: A model to calculate the _res variables before the actual calculations
|
|
36
|
+
:mparamodel: A model to inject parameter values into a dataframe before calculation
|
|
37
|
+
:fthismodel: String with the model
|
|
38
|
+
:fresmodel: String with the model for calculating residuals
|
|
39
|
+
:fparamodel: String with the model for injecting parameters
|
|
40
|
+
:modout: String with the consolidated .mod file
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
creates 5 files:
|
|
44
|
+
|
|
45
|
+
:{modelname}.frm: Formulas in modelflow business language
|
|
46
|
+
:{modelname}_res.frm: Formulas for mresmodel
|
|
47
|
+
:{modelname}_para.frm: Formulas for mparamodel
|
|
48
|
+
:{modelname}_cons.mod: A consolidated .mod file defining the model and parameters
|
|
49
|
+
:{modelname}.inf: A with model information - also displayes after execution
|
|
50
|
+
'''
|
|
51
|
+
def __init__(self, files,save=False,savepath='',modelname = 'testmodel'):
|
|
52
|
+
''' initialize a model'''
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
if type(files) == list:
|
|
56
|
+
modfilenames = [f for f in files if f.endswith('.mod')]
|
|
57
|
+
self.filenames = [f for f in modfilenames if not f.endswith('param.mod') ]
|
|
58
|
+
self.parafilenames = [f for f in modfilenames if f.endswith('param.mod') ]
|
|
59
|
+
|
|
60
|
+
self.alllines = ''
|
|
61
|
+
self.alllines= ' '.join([open(f,'rt').read() for f in self.filenames]).upper()
|
|
62
|
+
self.paralines= ' '.join([open(f,'rt').read() for f in self.parafilenames]).upper()
|
|
63
|
+
file_path = Path(self.filenames[0])
|
|
64
|
+
# self.path,self.modelname=self.filenames[0][:-4].rsplit('\\',1)
|
|
65
|
+
# self.savepath = savepath if savepath else self.path
|
|
66
|
+
else:
|
|
67
|
+
self.filenames = files
|
|
68
|
+
self.alllines = open(file_path := Path(files),'rt').read() # we got a string
|
|
69
|
+
self.paralines = ''
|
|
70
|
+
|
|
71
|
+
self.path = str(file_path.parent)
|
|
72
|
+
self.modelname = file_path.stem
|
|
73
|
+
self.savepath = savepath if savepath else Path(self.path)
|
|
74
|
+
|
|
75
|
+
#%% get rid of comments
|
|
76
|
+
rest = [l.split(r'//')[0].strip() for l in self.alllines.split('\n')
|
|
77
|
+
if 0 != len(l.split(r'//')[0].strip())]
|
|
78
|
+
|
|
79
|
+
#%% get the model and make it
|
|
80
|
+
restmod = ' '.join(rest)
|
|
81
|
+
modelpat = r'model\(no_static\);(.*?)end'
|
|
82
|
+
modellist = re.findall(modelpat,restmod) # extract all model segments
|
|
83
|
+
# breakpoint()
|
|
84
|
+
|
|
85
|
+
assert len(modellist) == len([l for l in rest if 'model' in l.lower()]),'Some model segments missing'
|
|
86
|
+
|
|
87
|
+
lthismodel = [f'frml <> {f} $' for f in ''.join(modellist).split(';')
|
|
88
|
+
if 0 != len(f.strip())]
|
|
89
|
+
self.fthismodel = '\n'.join(lthismodel).replace('^','**')
|
|
90
|
+
|
|
91
|
+
assert pt.check_syntax_model(self.fthismodel),'Syntax error in file'
|
|
92
|
+
|
|
93
|
+
self.mthismodel = mc.model(self.fthismodel,modelname = self.modelname)
|
|
94
|
+
|
|
95
|
+
#%% get the resmodel
|
|
96
|
+
self.fresmodel = mp.find_res_dynare_new(self.fthismodel)
|
|
97
|
+
self.mresmodel = mc.model(self.fresmodel,modelname=self.modelname+'_res')
|
|
98
|
+
|
|
99
|
+
modelresvar = [v for v in self.mthismodel.allvar if v.endswith('_RES')]
|
|
100
|
+
resmodelresvar = [v for v in self.mresmodel.endogene]
|
|
101
|
+
assert set(modelresvar)==set(resmodelresvar),'Residual model does not match residuals in the model'
|
|
102
|
+
|
|
103
|
+
# breakpoint()
|
|
104
|
+
#%% get a model for injecting parameters
|
|
105
|
+
parampat = r'parameters(.*?)(?:(?:model)|(?:var)|(?:exovar)|(?:$))'
|
|
106
|
+
paramlist = re.findall(parampat,restmod)+[self.paralines]
|
|
107
|
+
# assert len(paramlist)-1 == len([l for l in rest if 'parameters'.upper() in l]),'Some parameter segments missing'
|
|
108
|
+
|
|
109
|
+
#new get all the parameter settings and make a model for injecting theese
|
|
110
|
+
self.paravalues = sorted(set([re.sub(r'\s+','',f) for f in ''.join(paramlist).split(';') if 0 != len(f.strip()) and '=' in f ]))
|
|
111
|
+
self.fparamodel = '\n'.join( [f'frml <> {f} $' for f in self.paravalues ])
|
|
112
|
+
self.mparamodel = mc.model(self.fparamodel,modelname=self.modelname+'_para')
|
|
113
|
+
|
|
114
|
+
# now get all the parameter names:
|
|
115
|
+
llparavars = ' '.join([f.split('=')[0] for f in ''.join(paramlist).split(';') ])
|
|
116
|
+
self.paravars = sorted({re.sub(r'\s+','',p) for p in llparavars.split(' ') if 0 != len(p.strip())})
|
|
117
|
+
|
|
118
|
+
##% Variables
|
|
119
|
+
varpat = r'var[^e](.*?);'
|
|
120
|
+
varlist = re.findall(varpat,restmod)
|
|
121
|
+
vars = {v for v in ' '.join(varlist).split(' ') if 0 !=len(v)}
|
|
122
|
+
assert len(vars)==len(self.mthismodel.endogene),'Not all endogenous variables are declared'
|
|
123
|
+
|
|
124
|
+
exovarpat = r'varexo(.*?);'
|
|
125
|
+
exovarlist = re.findall(exovarpat,restmod)
|
|
126
|
+
exovars = {v.upper() for v in ' '.join(exovarlist).split(' ') if 0 !=len(v)}
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
#%% Output model
|
|
131
|
+
|
|
132
|
+
self.modout = self.mthismodel.todynare(self.paravars,self.paravalues)
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
#%%
|
|
136
|
+
newline='\n'
|
|
137
|
+
self.inf= (
|
|
138
|
+
f'Model file(s) : {self.filenames} \n'
|
|
139
|
+
+f'Contemporaneous feedback (simultaneous) : {not self.mthismodel.istopo} \n'
|
|
140
|
+
+f'Var equal to left hand variables : {self.mthismodel.endogene == set(vars)} \n'
|
|
141
|
+
+f'Number of endogeneous : {len(self.mthismodel.endogene)} \n'
|
|
142
|
+
+f'Number of exogenous : {len(self.mthismodel.exogene)} \n'
|
|
143
|
+
+f'Parameters : {len(self.paravars)} \n'
|
|
144
|
+
+f'Parameters set to values : {len(self.paravalues)} \n'
|
|
145
|
+
# +f'Exovar not in model : { set(exovars)- self.mthismodel.exogene} \n'
|
|
146
|
+
+f'Model exogenous not in exovar or parameter: {len(self.mthismodel.exogene- (set(exovars)|set(self.paravars)))} \n'
|
|
147
|
+
+f'Parameters also in exovar : {len(set(exovars) & set(self.paravars))} \n'
|
|
148
|
+
# +f'Parameters not in model : \n{newline.join(sorted(set(self.paravars)- self.mthismodel.exogene))} \n'
|
|
149
|
+
)
|
|
150
|
+
print(self.inf)
|
|
151
|
+
if save:
|
|
152
|
+
with open(f'{self.savepath}/{self.modelname}.inf','wt') as inffile:
|
|
153
|
+
inffile.write(self.inf)
|
|
154
|
+
with open(f'{self.savepath}/{self.modelname}.frm','wt') as frmfile:
|
|
155
|
+
frmfile.write(self.fthismodel)
|
|
156
|
+
with open(f'{self.savepath}/{self.modelname}_para.frm','wt') as frmfile:
|
|
157
|
+
frmfile.write(self.fparamodel)
|
|
158
|
+
with open(f'{self.savepath}/{self.modelname}_res.frm','wt') as frmfile:
|
|
159
|
+
frmfile.write(self.fresmodel)
|
|
160
|
+
with open(f'{self.savepath}/{self.modelname}_cons.mod','wt') as consfile:
|
|
161
|
+
consfile.write(self.modout)
|
|
162
|
+
|
|
163
|
+
if __name__ == '__main__' :
|
|
164
|
+
if 1:
|
|
165
|
+
dmodel = grap_modfile(r'C:/mfmodeller_raw/beast/MA-macroexp.mod')
|
|
166
|
+
modmod = dmodel.modout
|
|
167
|
+
|
|
168
|
+
#%%
|
|
169
|
+
if 0:
|
|
170
|
+
#%%
|
|
171
|
+
dmodel.mthismodel.AT_SHOCK1.draw(down=2,up=100,pdf=1,browser=0,HR=0,endo=True)
|
|
172
|
+
dmodel.mthismodel.TR_13_HHCC_AT_DENLG.draw(down=2,up=3,pdf=1,HR=0,endo=False)
|
|
173
|
+
dmodel.mthismodel.LOANSUPPLY_HHCC_AT_ATVLK.draw(down=2,up=3,pdf=1,HR=0,endo=0)
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
Created on Sun Feb 21 16:59:39 2021
|
|
4
|
+
|
|
5
|
+
@author: bruger
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import pandas as pd
|
|
9
|
+
import numpy as np
|
|
10
|
+
|
|
11
|
+
def lifetime_credit_loss(maturity,discount_rate,lgd,PDefault,debug=False):
|
|
12
|
+
'''
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
Parameters
|
|
16
|
+
----------
|
|
17
|
+
maturity : integer or float
|
|
18
|
+
maturity over which the exposure is amortised - by equal instalments.
|
|
19
|
+
discount_rate : float
|
|
20
|
+
discount rate
|
|
21
|
+
lgd : array of float
|
|
22
|
+
list of loss given default
|
|
23
|
+
PDefault : array of float
|
|
24
|
+
propability of defaults
|
|
25
|
+
debug : bool, optional
|
|
26
|
+
calculate a intermidiately dataframes . The default is False.
|
|
27
|
+
|
|
28
|
+
Returns
|
|
29
|
+
-------
|
|
30
|
+
float the long term credit loss in percent
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
'''
|
|
34
|
+
startstock = 100
|
|
35
|
+
_mat = float(int(maturity))
|
|
36
|
+
time = list(range(int(_mat)+1))
|
|
37
|
+
cashflow = pd.Series(float(startstock)/_mat,index=time,name='cashflow')
|
|
38
|
+
accumulated_cashflow = cashflow.cumsum().shift(fill_value=0.0)
|
|
39
|
+
accumulated_cashflow.name='accumulated_cashflow'
|
|
40
|
+
|
|
41
|
+
stock = startstock-accumulated_cashflow
|
|
42
|
+
stock.name = 'Outstanding'
|
|
43
|
+
|
|
44
|
+
stock_lag = stock.shift().fillna(0.0)
|
|
45
|
+
stock_lag.name = 'outstanding_lagged'
|
|
46
|
+
|
|
47
|
+
stock_average = stock.rolling(2).mean().fillna(0)
|
|
48
|
+
stock_average.name = 'Outstanding average'
|
|
49
|
+
|
|
50
|
+
assert cashflow.sum() != startstock,'Amortisation does not match outstanding '
|
|
51
|
+
discount_series = pd.Series([1./(discount_rate+1)**t for t in time],index=time,name='discount')
|
|
52
|
+
|
|
53
|
+
lgd_series = pd.Series(lgd[:len(cashflow)] if type(lgd) == np.ndarray else lgd,index = time,name='lgd')
|
|
54
|
+
pd_series = pd.Series(PDefault[:len(cashflow)] if type(PDefault) == np.ndarray else PDefault, index=time,name='pd')
|
|
55
|
+
pd_series[0] = 0.0
|
|
56
|
+
# breakpoint()
|
|
57
|
+
|
|
58
|
+
pd_survival = 1-pd_series
|
|
59
|
+
pd_survival.name = 'pd_survival'
|
|
60
|
+
|
|
61
|
+
pd_incremental = pd_series*pd_survival.shift().cumprod()
|
|
62
|
+
pd_incremental.name = 'pd_incremental'
|
|
63
|
+
|
|
64
|
+
lgd_decay = stock_average*lgd_series/100.
|
|
65
|
+
lgd_decay.name = 'lgd_decay '
|
|
66
|
+
|
|
67
|
+
lt_loss = pd_incremental* lgd_decay*stock_lag
|
|
68
|
+
lt_loss.name='Loss'
|
|
69
|
+
|
|
70
|
+
lt_loss_discounted = lt_loss*discount_series
|
|
71
|
+
lt_loss_discounted.name = 'Discounted Loss'
|
|
72
|
+
|
|
73
|
+
lt_loss_discounted_sum = lt_loss_discounted.sum()
|
|
74
|
+
# breakpoint()
|
|
75
|
+
if debug:
|
|
76
|
+
debugout = pd.concat([stock,stock_average,pd_series,pd_survival,pd_incremental,
|
|
77
|
+
lgd_series,lgd_decay,lt_loss,discount_series,lt_loss_discounted],axis=1)
|
|
78
|
+
print(f'Values:\n{debugout}')
|
|
79
|
+
return lt_loss_discounted_sum/startstock
|
|
80
|
+
|
|
81
|
+
if __name__ == '__main__':
|
|
82
|
+
pd_fut = np.append([0],np.full(20,0.006831))
|
|
83
|
+
lgd_fut = np.full(20,0.2)
|
|
84
|
+
|
|
85
|
+
pd_ser = pd.Series(pd_fut)
|
|
86
|
+
xx = lifetime_credit_loss(maturity=5,discount_rate=0.015,lgd=lgd_fut,PDefault=pd_fut,debug=1)
|
|
87
|
+
yy = lifetime_credit_loss(maturity=5,discount_rate=0.015,lgd=0.2, PDefault=0.006831,debug=1)
|
|
88
|
+
zz = lifetime_credit_loss(maturity=5,discount_rate=0.015,lgd=0.2, PDefault=pd_ser,debug=1)
|