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
modelinvert.py
ADDED
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
Created on Thu Sep 21 12:41:10 2017
|
|
4
|
+
|
|
5
|
+
@author: IBH
|
|
6
|
+
|
|
7
|
+
Class to handle general target/instrument problems.
|
|
8
|
+
|
|
9
|
+
Number of targets should be equal to number of instruments
|
|
10
|
+
|
|
11
|
+
An instrument can comprice of severeral variables
|
|
12
|
+
instruments are inputtet as a list of instruments
|
|
13
|
+
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
import pandas as pd
|
|
17
|
+
import numpy as np
|
|
18
|
+
from tqdm.auto import tqdm
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
from modelhelp import update_var
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class targets_instruments():
|
|
25
|
+
''' Class to handle general target/instrument problems.
|
|
26
|
+
Where the response is delayed specify this with delay.
|
|
27
|
+
|
|
28
|
+
Number of targets should be equal to number of instruments
|
|
29
|
+
|
|
30
|
+
An instrument can comprice of severeral variables
|
|
31
|
+
|
|
32
|
+
**Instruments** are inputtet as a list of instruments
|
|
33
|
+
|
|
34
|
+
To calculate the jacobian each instrument variable has a impuls,
|
|
35
|
+
which is used as delta when evaluating the jacobi matrix::
|
|
36
|
+
|
|
37
|
+
[ 'QO_J','TG'] Simple list each variable are shocked by the default impulse
|
|
38
|
+
[ ('QO_J',0.5), 'TG'] Here QO_J is getting its own impuls (0.5)
|
|
39
|
+
[ [('QO_J',0.5),('ORLOV',1.)] , ('TG',0.01)] here an impuls is given for each variable, and the first instrument consiste of two variables
|
|
40
|
+
|
|
41
|
+
**Targets** are list of variables
|
|
42
|
+
|
|
43
|
+
Convergence is achieved when all targets are within convergens distance from the target value
|
|
44
|
+
|
|
45
|
+
Convergencedistance can be set individual for a target variable by setting a value in <modelinstance>.targetconv
|
|
46
|
+
|
|
47
|
+
Targets and target values are provided by a dataframe.
|
|
48
|
+
|
|
49
|
+
'''
|
|
50
|
+
|
|
51
|
+
def __init__(self,databank,targets,instruments,model,defaultimpuls=0.01,defaultconv=0.01, delay=0,
|
|
52
|
+
nonlin=False,silent = True, maxiter=30,solveopt={},varimpulse=False,progressbar= True):
|
|
53
|
+
'''
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
Parameters
|
|
57
|
+
----------
|
|
58
|
+
databank : TYPE
|
|
59
|
+
values to run on .
|
|
60
|
+
targets : TYPE
|
|
61
|
+
dataframe with a column for each target.
|
|
62
|
+
instruments : TYPE
|
|
63
|
+
list of instruments .
|
|
64
|
+
model : TYPE
|
|
65
|
+
the model to use .
|
|
66
|
+
defaultimpuls : TYPE, optional
|
|
67
|
+
default delta . The default is 0.01.
|
|
68
|
+
defaultconv : TYPE, optional
|
|
69
|
+
default convergence . The default is 0.01.
|
|
70
|
+
delay : TYPE, optional
|
|
71
|
+
delay in effects . The default is 0.
|
|
72
|
+
nonlin : TYPE, optional
|
|
73
|
+
if a number the number of iterations to trigger recalculation of jacobi. The default is False.
|
|
74
|
+
silent : TYPE, optional
|
|
75
|
+
show iterations if false. The default is True.
|
|
76
|
+
maxiter : TYPE, optional
|
|
77
|
+
max newton iteration. The default is 30.
|
|
78
|
+
solveopt : TYPE, optional
|
|
79
|
+
options to bring to the solver. The default is {}.
|
|
80
|
+
varimpulse : TYPE, optional
|
|
81
|
+
if True only update the current period, else update into the future. The default is False.
|
|
82
|
+
|
|
83
|
+
Returns
|
|
84
|
+
-------
|
|
85
|
+
None.
|
|
86
|
+
|
|
87
|
+
'''
|
|
88
|
+
self.model = model
|
|
89
|
+
self.df = model.lastdf
|
|
90
|
+
self.targetvars = targets if isinstance(targets,list) else targets.columns
|
|
91
|
+
self.targetconv = {t: defaultconv for t in self.targetvars} # make sure there is a convergence criteria ]
|
|
92
|
+
self.targets = targets
|
|
93
|
+
self.instruments = {}
|
|
94
|
+
self.solveopt = {**solveopt, **{'keep':''}}
|
|
95
|
+
self.silent = silent
|
|
96
|
+
self.debug=False
|
|
97
|
+
self.maxiter = maxiter
|
|
98
|
+
self.nonlin=nonlin
|
|
99
|
+
self.databank = databank.copy()
|
|
100
|
+
self.varimpulse = varimpulse
|
|
101
|
+
self.progressbar = progressbar
|
|
102
|
+
self.savesolvearg = model.oldkwargs if hasattr(model,'oldkwargs') else {}
|
|
103
|
+
for inumber,i in enumerate(instruments):
|
|
104
|
+
vars = i if isinstance(i,list) else [i] # make it a list even if one variable
|
|
105
|
+
xx = [v if isinstance(v,tuple) else (v,defaultimpuls) for v in vars] # make sure there is a impuls
|
|
106
|
+
name = ','.join(n for n,i in xx)
|
|
107
|
+
name = f'Instrument_{inumber}' if len(name)>500 else name
|
|
108
|
+
self.instruments[inumber] = {'name':name , 'vars': xx, }
|
|
109
|
+
self.defaultimpuls = defaultimpuls
|
|
110
|
+
# breakpoint()
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def jacobi(self,per,delay=0):
|
|
114
|
+
''' Calculates a jecobi matrix of derivatives based on the instruments and targets
|
|
115
|
+
|
|
116
|
+
returns a dataframe '''
|
|
117
|
+
# breakpoint()
|
|
118
|
+
|
|
119
|
+
iper = self.df.index.get_loc(per)
|
|
120
|
+
iper_delayed = iper-delay
|
|
121
|
+
per_delayed = self.df.index[iper_delayed]
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
self.jac = jac=pd.DataFrame(0.000,index=self.targetvars, columns=[v['name'] for v in self.instruments.values()])
|
|
125
|
+
with self.model.set_smpl(per_delayed,per):
|
|
126
|
+
mul = self.model(self.df,setlast=False, **self.solveopt) # start point for this quarter
|
|
127
|
+
basis = mul.copy(deep=True) # make a reference point for the calculation the derivatives.
|
|
128
|
+
if not self.silent: print(f'Update jacobi: {per} effects from {per_delayed}')
|
|
129
|
+
oldsave = self.model.save
|
|
130
|
+
for instrument in self.instruments.values():
|
|
131
|
+
# print('instrument: ',instrument['name'])
|
|
132
|
+
# set the instrument
|
|
133
|
+
for var,impuls in instrument['vars']:
|
|
134
|
+
if self.varimpulse:
|
|
135
|
+
mul.loc[per_delayed,var] = mul.loc[per_delayed,var] + impuls # increase loan growth
|
|
136
|
+
else:
|
|
137
|
+
mul.loc[per_delayed:,var] = mul.loc[per_delayed:,var] + impuls # increase loan growth
|
|
138
|
+
# calculate the effect
|
|
139
|
+
with self.model.set_smpl(per_delayed,per):
|
|
140
|
+
|
|
141
|
+
res = self.model(mul,save=False,**self.solveopt) #antal=600,first_test=20,ljit=1) # solve model
|
|
142
|
+
|
|
143
|
+
# breakpoint()
|
|
144
|
+
jac.loc[self.targetvars,instrument['name']] = res.loc[per,self.targetvars]-basis.loc[per,self.targetvars] # store difference in original bank
|
|
145
|
+
# reset the instrument
|
|
146
|
+
for var,impuls in instrument['vars']:
|
|
147
|
+
mul.loc[per_delayed:,var]=basis.loc[per_delayed:,var]
|
|
148
|
+
self.model.oldkwargs = self.savesolvearg
|
|
149
|
+
self.model.save = oldsave
|
|
150
|
+
|
|
151
|
+
return jac
|
|
152
|
+
|
|
153
|
+
def invjacobi(self,per,diag=False,delay=0):
|
|
154
|
+
''' Calculates the inverted jacobi matrix
|
|
155
|
+
|
|
156
|
+
returns a dataframe '''
|
|
157
|
+
|
|
158
|
+
x = self.jacobi(per,delay=delay)
|
|
159
|
+
# print(x)
|
|
160
|
+
if diag:
|
|
161
|
+
out = pd.DataFrame(np.diag(1.0/x.values.diagonal()),x.columns,x.index)
|
|
162
|
+
else:
|
|
163
|
+
out= pd.DataFrame(np.linalg.inv(x),x.columns,x.index)
|
|
164
|
+
return out
|
|
165
|
+
|
|
166
|
+
def targetseek(self,databank=None,shortfall=False,ti_damp=1.0,delay=0,**kwargs):
|
|
167
|
+
''' Calculates the instruments as a function of targets '''
|
|
168
|
+
silent = kwargs.get('silent',self.silent)
|
|
169
|
+
self.maxiter = kwargs.get('maxiter',self.maxiter)
|
|
170
|
+
self.nonlin = kwargs.get('nonlin',self.nonlin)
|
|
171
|
+
progressbar = kwargs.get('progressbar',self.progressbar)
|
|
172
|
+
|
|
173
|
+
tindex = self.model.current_per.copy()
|
|
174
|
+
res = self.databank.copy()
|
|
175
|
+
# self.inv = inv = self.invjacobi(self.targets.index[0])
|
|
176
|
+
self.inv = inv = self.invjacobi(self.targets.index[0],diag=shortfall,delay=delay)
|
|
177
|
+
|
|
178
|
+
self.conv = pd.Series([self.targetconv[v] for v in self.targetvars],self.targetvars)
|
|
179
|
+
# print(inv)
|
|
180
|
+
oldsave = self.model.save
|
|
181
|
+
bars = '{desc}: {percentage:3.0f}%|{bar}| {n_fmt}/{total_fmt}'
|
|
182
|
+
|
|
183
|
+
with tqdm(total=len(self.targets.index),disable = not progressbar,desc=f'Finding instruments ',bar_format=bars) as pbar:
|
|
184
|
+
|
|
185
|
+
for per in self.targets.index:
|
|
186
|
+
|
|
187
|
+
iper = self.df.index.get_loc(per)
|
|
188
|
+
iper_delayed = iper-delay
|
|
189
|
+
per_delayed = self.df.index[iper_delayed]
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
if not silent or self.debug:
|
|
193
|
+
print('Period:',per)
|
|
194
|
+
res = self.model(res,per_delayed ,per ,save=False, **self.solveopt)
|
|
195
|
+
orgdistance = self.targets.loc[per,self.targetvars] - res.loc[per,self.targetvars]
|
|
196
|
+
shortfallvar = (shortfall * orgdistance) >= 0
|
|
197
|
+
for iterations in range(self.maxiter):
|
|
198
|
+
startdistance = self.targets.loc[per,self.targetvars] - res.loc[per,self.targetvars]
|
|
199
|
+
self.distance = distance = startdistance*shortfallvar if shortfall else startdistance
|
|
200
|
+
if not silent: print('Period:',per,' Target instrument iteration:',iterations,
|
|
201
|
+
f' Max distance: {distance.abs().max():.3f}')
|
|
202
|
+
if self.debug:
|
|
203
|
+
print(f'\nTarget instrument {per}, iteration {iterations}')
|
|
204
|
+
print(f'Distance to target :\n{startdistance}\n')
|
|
205
|
+
if shortfall:
|
|
206
|
+
print(f'Distance to shortfall target :\n{distance}\n')
|
|
207
|
+
|
|
208
|
+
if (distance.abs()>=self.conv).any():
|
|
209
|
+
if self.nonlin:
|
|
210
|
+
if type(self.nonlin) == int:
|
|
211
|
+
if iterations >= self.nonlin:
|
|
212
|
+
if not iterations%self.nonlin:
|
|
213
|
+
self.inv = inv = self.invjacobi(per,diag=shortfall,delay=delay)
|
|
214
|
+
else:
|
|
215
|
+
self.inv = inv = self.invjacobi(per,diag=shortfall,delay=delay)
|
|
216
|
+
|
|
217
|
+
update = inv.dot(distance) * ti_damp
|
|
218
|
+
if self.debug :
|
|
219
|
+
print('Update instruments:')
|
|
220
|
+
print(update)
|
|
221
|
+
for instrument in self.instruments.values():
|
|
222
|
+
for var,impuls in instrument['vars']:
|
|
223
|
+
if self.varimpulse:
|
|
224
|
+
res.loc[per_delayed,var] = res.loc[per_delayed,var] + update[instrument['name']] * impuls # increase loan growth
|
|
225
|
+
else:
|
|
226
|
+
res.loc[per_delayed:,var] = res.loc[per_delayed:,var] + update[instrument['name']] * impuls # increase loan growth
|
|
227
|
+
|
|
228
|
+
res = self.model(res,per_delayed ,per ,setlast=False,**self.solveopt)
|
|
229
|
+
else:
|
|
230
|
+
break
|
|
231
|
+
else:
|
|
232
|
+
print(f'No convergense in target instrument in {per}, maxiter={self.maxiter}')
|
|
233
|
+
raise Exception('No convergence ')
|
|
234
|
+
pbar.update()
|
|
235
|
+
self.model.lastdf = res
|
|
236
|
+
self.model.oldkwargs = self.savesolvearg
|
|
237
|
+
self.model.save = oldsave
|
|
238
|
+
self.model.current_per = tindex
|
|
239
|
+
|
|
240
|
+
return res
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
def __call__(self, *args, **kwargs ):
|
|
244
|
+
'''Uses :any:`targetseek` '''
|
|
245
|
+
return self.targetseek( *args, **kwargs)
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
#%% running
|
|
249
|
+
if __name__ == '__main__':
|
|
250
|
+
pass
|