modelflowib 2.76__tar.gz → 2.77__tar.gz

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.
Files changed (50) hide show
  1. {modelflowib-2.76 → modelflowib-2.77}/PKG-INFO +1 -1
  2. {modelflowib-2.76 → modelflowib-2.77}/modelclass.py +51 -31
  3. {modelflowib-2.76 → modelflowib-2.77}/modelconstruct_estimation.py +10 -0
  4. {modelflowib-2.76 → modelflowib-2.77}/modelflowib.egg-info/PKG-INFO +1 -1
  5. {modelflowib-2.76 → modelflowib-2.77}/modeljupytermagic.py +5 -1
  6. {modelflowib-2.76 → modelflowib-2.77}/modelnormalize.py +31 -11
  7. {modelflowib-2.76 → modelflowib-2.77}/modelsolver_ng.py +3652 -3652
  8. {modelflowib-2.76 → modelflowib-2.77}/pyproject.toml +1 -1
  9. {modelflowib-2.76 → modelflowib-2.77}/README.md +0 -0
  10. {modelflowib-2.76 → modelflowib-2.77}/license.md +0 -0
  11. {modelflowib-2.76 → modelflowib-2.77}/modelBLfunk.py +0 -0
  12. {modelflowib-2.76 → modelflowib-2.77}/model_Excel.py +0 -0
  13. {modelflowib-2.76 → modelflowib-2.77}/model_cvx.py +0 -0
  14. {modelflowib-2.76 → modelflowib-2.77}/model_dynare.py +0 -0
  15. {modelflowib-2.76 → modelflowib-2.77}/model_financial_stability.py +0 -0
  16. {modelflowib-2.76 → modelflowib-2.77}/model_latex.py +0 -0
  17. {modelflowib-2.76 → modelflowib-2.77}/model_latex_class.py +0 -0
  18. {modelflowib-2.76 → modelflowib-2.77}/model_parquet_mixin.py +0 -0
  19. {modelflowib-2.76 → modelflowib-2.77}/modelconstruct.py +0 -0
  20. {modelflowib-2.76 → modelflowib-2.77}/modeldash.py +0 -0
  21. {modelflowib-2.76 → modelflowib-2.77}/modeldashboot.py +0 -0
  22. {modelflowib-2.76 → modelflowib-2.77}/modeldashsidebar.py +0 -0
  23. {modelflowib-2.76 → modelflowib-2.77}/modeldekom.py +0 -0
  24. {modelflowib-2.76 → modelflowib-2.77}/modeldiff.py +0 -0
  25. {modelflowib-2.76 → modelflowib-2.77}/modeldisplay.py +0 -0
  26. {modelflowib-2.76 → modelflowib-2.77}/modelestimation.py +0 -0
  27. {modelflowib-2.76 → modelflowib-2.77}/modelestimator_new.py +0 -0
  28. {modelflowib-2.76 → modelflowib-2.77}/modelflowib.egg-info/SOURCES.txt +0 -0
  29. {modelflowib-2.76 → modelflowib-2.77}/modelflowib.egg-info/dependency_links.txt +0 -0
  30. {modelflowib-2.76 → modelflowib-2.77}/modelflowib.egg-info/requires.txt +0 -0
  31. {modelflowib-2.76 → modelflowib-2.77}/modelflowib.egg-info/top_level.txt +0 -0
  32. {modelflowib-2.76 → modelflowib-2.77}/modelgrab.py +0 -0
  33. {modelflowib-2.76 → modelflowib-2.77}/modelgrabgdx.py +0 -0
  34. {modelflowib-2.76 → modelflowib-2.77}/modelgrabwf2.py +0 -0
  35. {modelflowib-2.76 → modelflowib-2.77}/modelhelp.py +0 -0
  36. {modelflowib-2.76 → modelflowib-2.77}/modelhtml.py +0 -0
  37. {modelflowib-2.76 → modelflowib-2.77}/modelinvert.py +0 -0
  38. {modelflowib-2.76 → modelflowib-2.77}/modeljupyter.py +0 -0
  39. {modelflowib-2.76 → modelflowib-2.77}/modelmacrograb.py +0 -0
  40. {modelflowib-2.76 → modelflowib-2.77}/modelmanipulation.py +0 -0
  41. {modelflowib-2.76 → modelflowib-2.77}/modelmf.py +0 -0
  42. {modelflowib-2.76 → modelflowib-2.77}/modelnet.py +0 -0
  43. {modelflowib-2.76 → modelflowib-2.77}/modelnewton.py +0 -0
  44. {modelflowib-2.76 → modelflowib-2.77}/modelpattern.py +0 -0
  45. {modelflowib-2.76 → modelflowib-2.77}/modelreport.py +0 -0
  46. {modelflowib-2.76 → modelflowib-2.77}/modeluserfunk.py +0 -0
  47. {modelflowib-2.76 → modelflowib-2.77}/modelvis.py +0 -0
  48. {modelflowib-2.76 → modelflowib-2.77}/modelwidget.py +0 -0
  49. {modelflowib-2.76 → modelflowib-2.77}/modelwidget_input.py +0 -0
  50. {modelflowib-2.76 → modelflowib-2.77}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modelflowib
3
- Version: 2.76
3
+ Version: 2.77
4
4
  Summary: A tool to solve and manage dynamic economic and financial models
5
5
  Author-email: Ib Hansen <Ib.Hansen.Iv@gmail.com>
6
6
  License-Expression: MIT
@@ -3188,7 +3188,7 @@ class Modify_Mixin():
3188
3188
  newnormalisation = [l.split() for l in lines]
3189
3189
  vars_before_normalization = {beforeendo.upper() for beforeendo,afterendo in newnormalisation }
3190
3190
  frml_normalize_strip = {(beforeendo.upper(),afterendo.upper()) : self.allvar[beforeendo]['frml'].replace('$','').split(' ',2) for beforeendo,afterendo in newnormalisation }
3191
- frml_normalize_gross = {(beforeendo,afterendo) : (fname ,normal(expression,the_endo = afterendo,endo_lhs=False,add_factor=False)) for (beforeendo,afterendo),(frml,fname,expression) in frml_normalize_strip.items() }
3191
+ frml_normalize_gross = {(beforeendo,afterendo) : (fname ,normal(expression,the_endo = afterendo,endo_lhs=False,add_add_factor=False)) for (beforeendo,afterendo),(frml,fname,expression) in frml_normalize_strip.items() }
3192
3192
  frmldict_normalized = {afterendo : f'FRML {fname} {nexpression.normalized}$'
3193
3193
  for (beforeendo,afterendo),(fname,nexpression) in frml_normalize_gross.items() }
3194
3194
  # breakpoint()
@@ -3282,8 +3282,10 @@ class Modify_Mixin():
3282
3282
 
3283
3283
  Parameters
3284
3284
  ----------
3285
- updateeq : TYPE
3286
- new equations seperated by newline .
3285
+ updateeq : str or Makemodel
3286
+ new equations seperated by newline, or a Makemodel instance whose
3287
+ normalized equations (including per-equation add factors and
3288
+ fitted equations, when present) are used as the update.
3287
3289
  newfunks : TYPE, optional
3288
3290
  Additional userspecified functions. The default is [].
3289
3291
  calc_add : bool, optional
@@ -3297,32 +3299,50 @@ class Modify_Mixin():
3297
3299
  a dataframe with calculated add factors. Origin is the original models lastdf.
3298
3300
 
3299
3301
  '''
3300
-
3301
-
3302
- updatefunks=list(set(self.funks+newfunks) ) #
3303
-
3304
- newmodelname = newname if newname else self.name+' Updated'
3305
-
3306
- dfvars = set(self.lastdf.columns)
3307
-
3308
- updatemodel = mp.tofrml(updateeq) # create the moedl with the usual processing of frml's
3309
- while ' ' in updatemodel:
3310
- updatemodel = updatemodel.replace(' ', ' ')
3311
- frml2 = updatemodel.split('$')
3312
- frml2_strip = [mp.split_frml(f+'$') for f in frml2 if len(f)>2]
3313
- frml2_normal = [[frml,fname,
3314
- normal(expression[:-1],do_preprocess=do_preprocess,add_add_factor=add_add_factor,
3315
- make_fixable = pt.kw_frml_name(fname.upper(),'FIXABLE'))]
3316
- for allfrml,frml,fname,expression in frml2_strip]
3317
- frmldict_update = {nexpression.endo_var: f'{frml} {fname} {nexpression.normalized}$' for
3318
- frml,fname,nexpression in frml2_normal}
3319
-
3320
-
3321
- if add_add_factor:
3322
- frmldict_calc_add = {nexpression.endo_var: f'{frml} {fname} {nexpression.calc_add_factor}$' for
3323
- frml,fname,nexpression in frml2_normal if nexpression.endo_var in self.endogene|self.exogene|dfvars }
3324
- else:
3325
- frmldict_calc_add={}
3302
+ from modelconstruct_estimation import Makemodel # local to avoid circular import
3303
+
3304
+ updatefunks=list(set(self.funks+newfunks) ) #
3305
+
3306
+ newmodelname = newname if newname else self.name+' Updated'
3307
+
3308
+ dfvars = set(self.lastdf.columns)
3309
+ new_var_description = self.var_description
3310
+
3311
+ if isinstance(updateeq, Makemodel):
3312
+ # the Makemodel has already expanded, optionally estimated and normalized the
3313
+ # equations, and decided add factor/fixable/fitted per equation from its flags
3314
+ updatefunks = list(set(updatefunks + updateeq.funks))
3315
+ new_var_description = {**self.var_description, **updateeq.var_description}
3316
+ frml2_normal = [['FRML', fname, nexpression]
3317
+ for fname, (parts, nexpression)
3318
+ in zip(updateeq.normal_output_frmlnames, updateeq.normal)]
3319
+ frmldict_update = {nexpression.endo_var: f'{frml} {fname} {nexpression.normalized}$' for
3320
+ frml,fname,nexpression in frml2_normal}
3321
+ frmldict_update = {**frmldict_update,
3322
+ **{f'{nexpression.endo_var}_FITTED': f'FRML <FIT> {nexpression.fitted}$'
3323
+ for frml,fname,nexpression in frml2_normal if len(nexpression.fitted)}}
3324
+ frmldict_calc_add = {nexpression.endo_var: f'{frml} <CALC_ADD_FACTOR> {nexpression.calc_add_factor}$' for
3325
+ frml,fname,nexpression in frml2_normal
3326
+ if len(nexpression.calc_add_factor) and nexpression.endo_var in self.endogene|self.exogene|dfvars }
3327
+ else:
3328
+ updatemodel = mp.tofrml(updateeq) # create the moedl with the usual processing of frml's
3329
+ while ' ' in updatemodel:
3330
+ updatemodel = updatemodel.replace(' ', ' ')
3331
+ frml2 = updatemodel.split('$')
3332
+ frml2_strip = [mp.split_frml(f+'$') for f in frml2 if len(f)>2]
3333
+ frml2_normal = [[frml,fname,
3334
+ normal(expression[:-1],do_preprocess=do_preprocess,add_add_factor=add_add_factor,
3335
+ make_fixable = pt.kw_frml_name(fname.upper(),'FIXABLE'))]
3336
+ for allfrml,frml,fname,expression in frml2_strip]
3337
+ frmldict_update = {nexpression.endo_var: f'{frml} {fname} {nexpression.normalized}$' for
3338
+ frml,fname,nexpression in frml2_normal}
3339
+
3340
+
3341
+ if add_add_factor:
3342
+ frmldict_calc_add = {nexpression.endo_var: f'{frml} {fname} {nexpression.calc_add_factor}$' for
3343
+ frml,fname,nexpression in frml2_normal if nexpression.endo_var in self.endogene|self.exogene|dfvars }
3344
+ else:
3345
+ frmldict_calc_add={}
3326
3346
  # breakpoint()
3327
3347
 
3328
3348
  frmldict = {k: v['frml'] for (k,v) in self.allvar.items() if k in self.endogene } # frml's in the existing model
@@ -3331,8 +3351,8 @@ class Modify_Mixin():
3331
3351
  newfrml = '\n'.join([f for f in newfrmldict.values()])
3332
3352
  newmodel = self.__class__(newfrml,modelname = f'updated {self.name}',
3333
3353
  funks=updatefunks,
3334
- var_description=self.var_description,
3335
- model_description = self.model_description,
3354
+ var_description=new_var_description,
3355
+ model_description = self.model_description,
3336
3356
  var_groups = self.var_groups ,
3337
3357
  reports = self.reports ,
3338
3358
  substitution = self.substitution,
@@ -982,6 +982,16 @@ from IPython.display import display, Markdown, Math
982
982
  import re
983
983
  from IPython.display import display, Markdown, Math
984
984
 
985
+ class Markdown(Markdown):
986
+ """IPython Markdown, but with the markdown source as the text/plain fallback.
987
+
988
+ The stock class reprs as '<IPython.core.display.Markdown object>', and that
989
+ string is what latex/pdf exporters show, as they can not render the
990
+ text/markdown mime type and fall back to text/plain. With the source as
991
+ repr, exported documents show the model text instead."""
992
+ def __repr__(self):
993
+ return str(self.data)
994
+
985
995
  def display_model(cell: str, spec: str = "markdown"):
986
996
  """
987
997
  Display a model specification.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modelflowib
3
- Version: 2.76
3
+ Version: 2.77
4
4
  Summary: A tool to solve and manage dynamic economic and financial models
5
5
  Author-email: Ib Hansen <Ib.Hansen.Iv@gmail.com>
6
6
  License-Expression: MIT
@@ -27,6 +27,10 @@ from modelclass import model
27
27
  from modelmanipulation import explode
28
28
  from model_latex_class import a_latex_model
29
29
  from modelconstruct_estimation import Makemodel, display_model
30
+ # Markdown subclass whose text/plain fallback is the markdown source itself,
31
+ # so latex/pdf exports show the model text instead of
32
+ # '<IPython.core.display.Markdown object>'. Shadows the IPython import above.
33
+ from modelconstruct_estimation import Markdown
30
34
  from modelhelp import debug_var
31
35
  from modelreport import LatexRepo
32
36
 
@@ -589,7 +593,7 @@ try:
589
593
  if dict_name in user_ns:
590
594
  segs = list(user_ns[dict_name].keys())
591
595
  print(f"Model `{name}` built from segments: {', '.join(segs)}")
592
- print(f"✅ Created Mexplode model: {name}")
596
+ print(f"✅ Created Makemodel: {name}")
593
597
  print(emodel)
594
598
 
595
599
  return emodel
@@ -129,8 +129,19 @@ def funk_find_arg(funk_match, streng):
129
129
  return streng[:start], match[1:index], match[index + 1:]
130
130
  assert 1==2,f'Parantese mismatch in {streng}'
131
131
 
132
+ def funk_check_arg(funk,arg,udtryk,udtryk_up):
133
+ '''Guards against variables named like a function.
134
+
135
+ A lagged variable with a function name, fx DIFF(-1), matches DIFF( and would
136
+ silently be swallowed as a function call. If the argument is a pure signed
137
+ integer it must be such a lag, so raise an informative error instead.'''
138
+ if re.fullmatch(r'[+-]?\d+',arg.replace(' ','')):
139
+ raise Exception(f"A variable can not be named {funk}, as {funk}( is a function in the business language.\n"
140
+ f"{funk}({arg}) looks like a lagged variable {funk}. Rename the variable.\n"
141
+ f"Original expression: {udtryk}\n"
142
+ f"Processed so far : {udtryk_up}")
143
+
132
144
 
133
-
134
145
  def preprocess(udtryk,funks=[]):
135
146
  '''
136
147
  test processing expanding dlog,diff,movavg,pct,logit functions
@@ -146,16 +157,21 @@ def preprocess(udtryk,funks=[]):
146
157
 
147
158
  '''
148
159
  udtryk_up = udtryk.upper().replace(' ','')
160
+ udtryk_up = funk_replace('PCT','PCT_GROWTH',udtryk_up)
161
+
149
162
  while dlog_match := funk_in('DLOG',udtryk_up):
150
163
  fordlog,dlogudtryk_up,efterdlog=funk_find_arg(dlog_match,udtryk_up)
151
- udtryk_up=fordlog+'DIFF(LOG('+dlogudtryk_up+'))'+efterdlog
152
-
164
+ funk_check_arg('DLOG',dlogudtryk_up,udtryk,udtryk_up)
165
+ udtryk_up=fordlog+'DIFF(LOG('+dlogudtryk_up+'))'+efterdlog
166
+
153
167
  while logit_match := funk_in('LOGIT',udtryk_up):
154
168
  forlogit,logitudtryk_up,efterlogit=funk_find_arg(logit_match,udtryk_up)
155
- udtryk_up=forlogit+'(LOG('+logitudtryk_up+'/(1.0 -'+logitudtryk_up+')))'+efterlogit
156
-
169
+ funk_check_arg('LOGIT',logitudtryk_up,udtryk,udtryk_up)
170
+ udtryk_up=forlogit+'(LOG('+logitudtryk_up+'/(1.0 -'+logitudtryk_up+')))'+efterlogit
171
+
157
172
  while movavg_match := funk_in('MOVAVG', udtryk_up):
158
173
  forkaede,kaedeudtryk,efterkaede=funk_find_arg(movavg_match,udtryk_up)
174
+ funk_check_arg('MOVAVG',kaedeudtryk,udtryk,udtryk_up)
159
175
  arg=kaedeudtryk.split(',',1)
160
176
  avg='(('
161
177
  term=arg[0]
@@ -168,19 +184,23 @@ def preprocess(udtryk,funks=[]):
168
184
 
169
185
  while pct_match := funk_in('PCT_GROWTH',udtryk_up):
170
186
  forpc,pcudtryk,efterpc=funk_find_arg(pct_match,udtryk_up)
171
- udtryk_up=f'{forpc} (100 * ( ({pcudtryk}) / ({lagone(pcudtryk,funks=funks)}) -1)) {efterpc}'
187
+ funk_check_arg('PCT_GROWTH',pcudtryk,udtryk,udtryk_up)
188
+ udtryk_up=f'{forpc} (100 * ( ({pcudtryk}) / ({lagone(pcudtryk,funks=funks)}) -1)) {efterpc}'
172
189
 
173
190
  while pct_match := funk_in('PCY',udtryk_up):
174
191
  forpc,pcudtryk,efterpc=funk_find_arg(pct_match,udtryk_up)
175
- udtryk_up=f'{forpc} (100 * ( ({pcudtryk}) / ({lagone(pcudtryk,funks=funks,laglead=-4)}) -1)) {efterpc}'
176
-
192
+ funk_check_arg('PCY',pcudtryk,udtryk,udtryk_up)
193
+ udtryk_up=f'{forpc} (100 * ( ({pcudtryk}) / ({lagone(pcudtryk,funks=funks,laglead=-4)}) -1)) {efterpc}'
194
+
177
195
  while diff_match := funk_in('DIFF' , udtryk_up):
178
196
  fordif,difudtryk_up,efterdif=funk_find_arg(diff_match,udtryk_up)
179
- udtryk_up=fordif+'(('+difudtryk_up+')-('+lagone(difudtryk_up+'',funks=funks)+'))'+efterdif
180
-
197
+ funk_check_arg('DIFF',difudtryk_up,udtryk,udtryk_up)
198
+ udtryk_up=fordif+'(('+difudtryk_up+')-('+lagone(difudtryk_up+'',funks=funks)+'))'+efterdif
199
+
181
200
  while diff_match := funk_in('D' , udtryk_up):
182
201
  # print(f'{udtryk_up} on D')
183
202
  fordif,difudtryk_up,efterdif=funk_find_arg(diff_match,udtryk_up)
203
+ funk_check_arg('D',difudtryk_up,udtryk,udtryk_up)
184
204
  difudtryk_up = difudtryk_up.replace(' ','').replace(',0,1','') if difudtryk_up.endswith(',0,1') else difudtryk_up
185
205
  udtryk_up=fordif+'(('+difudtryk_up+')-('+lagone(difudtryk_up+'',funks=funks)+'))'+efterdif
186
206
 
@@ -407,7 +427,7 @@ if __name__ == '__main__':
407
427
  normal('a+b = c',add_add_factor=1,make_fitted=1).fprint
408
428
  normal('PCT_growth(a) = n(-1)',add_add_factor=0).fprint
409
429
  normal('a = movavg(pct(b),2)',add_add_factor=0).fprint
410
- normal('pct_growth(c) = pct_growth(d)',add_add_factor=0).fprint
430
+ normal('pct_growth(c) = pct_growth(dd)',add_add_factor=0).fprint
411
431
  normal('pct_growth(c) = z+pct(b) + pct(e)').fprint
412
432
  normal('pct_growth(c) = z+pct(b) + pct(e)').fprint
413
433
  normal('a = pct_growth(b)',add_add_factor=0).fprint