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.
modelgrabwf2.py ADDED
@@ -0,0 +1,1107 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ Created on Wed Mar 30 10:06:26 2022
4
+
5
+ @author: ibhan
6
+
7
+ Module to handle models in wf1 files
8
+
9
+ #. Eviews is started and the wf1 file is loaded.
10
+
11
+ #. Some transformations are performed on data.
12
+ #. The model is unlinked.
13
+ #. The workspace is saved as a wf2 file. Same name with _modelflow appended.
14
+ #. Eviews is closed
15
+ #. The wf2 file is read as a json file.
16
+ #. Relevant objects are extracted.
17
+ #. The MFMSA variable is extracted, to be saved in the dumpfile.
18
+ #. The equations are transformed and normalized to modelflow format and classified into identities and stochastic
19
+ #. Stochastic equations are enriched by add_factor and fixing terms (dummy + fixing value)
20
+ #. For Stochastic equations new fitted variables are generated - without add add_factors and dummies.
21
+ #. A model to generate fitted variables is created
22
+ #. A model to generate add_factors is created.
23
+ #. A model encompassing the original equations, the model for fitted variables and for add_factors is created.
24
+ #. The data series and scalars are shoveled into a Pandas dataframe
25
+
26
+ #. Some special series are generated as the expression can not be incorporated into modelflow model specifications
27
+ #. The model for fitted values is simulated in the specified timespan
28
+ #. The model for add_factors is simulated in the timespan set in MFMSA
29
+ #. The data descriptions are extracted into a dictionary.
30
+ #. Data descriptions for dummies, fixed values, fitted values and add_factors are derived.
31
+ #. Now we have a model and a dataframe with all variables which are needed.
32
+
33
+
34
+ """
35
+
36
+
37
+ import pandas as pd
38
+ import re
39
+ from dataclasses import dataclass, field
40
+ import functools
41
+ from tqdm import tqdm
42
+ import json
43
+ from pathlib import Path
44
+ import gzip
45
+ import warnings
46
+
47
+
48
+ from modelclass import model
49
+ import modelmf
50
+ import modelmanipulation as mp
51
+
52
+ import modelnormalize as nz
53
+
54
+
55
+ def remove_url_and_replace_nbsp(s):
56
+ # Regular expression for matching URLs
57
+ url_pattern = r'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*(),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+'
58
+ # Replace the URL with an empty string and \xa0 with a space
59
+ return re.sub(url_pattern, '', s).replace('\xa0', ' ').strip()
60
+
61
+
62
+ def wf1_to_wf2(filename,modelname='',eviews_run_lines= []):
63
+ '''
64
+ - Opens a eviews workfile in wf1 format
65
+ - calculates the eviews_trend
66
+ - unlink a model and
67
+ - writes the workspace back to a wf2 file
68
+
69
+ Args:
70
+ filename (TYPE): DESCRIPTION.
71
+ modelname (TYPE): default '' then the three first letters of the filenames stem are asumed to be the modelname.
72
+
73
+ Returns:
74
+ None.
75
+
76
+ '''
77
+ try:
78
+ import py2eviews as evp
79
+ except:
80
+ try:
81
+ import pyeviews as evp
82
+ print('You have installed pyewiews not py2eviews it may works but try:\n'+
83
+ '!conda install py2eviews -c -c eviews -y')
84
+ except:
85
+ raise Exception('You have not py2eviews installed try:\n'+
86
+ '!conda install py2eviews -c -c eviews -y')
87
+ from pathlib import Path
88
+ wfpath = Path(filename)
89
+ if wfpath.suffix not in {'.wf1','.wf2'} :
90
+ raise Exception(f'wf1_to_wf2 expects a .wf1 file as input\nOffending:{wfpath} {wfpath.suffix} ')
91
+ else:
92
+ wf1= wfpath.absolute()
93
+ # wf2 = wf1.with_suffix('.wf2')
94
+ wf2 = (wf1.resolve().parent / (wf1.stem + '_modelflow')).with_suffix('.wf2')
95
+ # breakpoint()
96
+ eviewsapp = evp.GetEViewsApp(instance='new',showwindow=True)
97
+ print(f'\nReading {wf1}')
98
+ if modelname == '':
99
+ modelname = wf1.stem[:3].upper()
100
+ print(f'Assummed model name: {modelname}')
101
+
102
+ evp.Run(fr'wfopen "{wf1}"',eviewsapp)
103
+ evp.Run( r'smpl @all',eviewsapp)
104
+ evp.Run( r'series eviews_trend = @TREND',eviewsapp)
105
+ for eviewsline in eviews_run_lines:
106
+ print(f'Eviewsline to run :{eviewsline}')
107
+ evp.Run(eviewsline,eviewsapp)
108
+ evp.Run(f'{modelname}.unlink @all',eviewsapp)
109
+ print(f'The model: {modelname} is unlinked ')
110
+ evp.Run(fr'wfsave(jf) "{wf2}"',eviewsapp)
111
+ print(f'Writing {wf2}')
112
+
113
+ eviewsapp.hide()
114
+ eviewsapp = None
115
+ evp.Cleanup()
116
+ return wf2,modelname
117
+
118
+ def wf2_to_clean(wf2name,modelname='',save_file = False,freq='A'):
119
+ '''
120
+ Takes a eviews .wf2 file - which is in JSON format - and place a
121
+ dictionary
122
+
123
+ Args:
124
+ wf2name (TYPE): name of wf2 file .
125
+ modelname (TYPE, optional): Name og model. Defaults to ''.
126
+ save_file (TYPE, optional): save the specification, data and description in a dictionary. Defaults to False.
127
+
128
+ Returns:
129
+ model_all_about (dict): the content of the wf2 file as a dict .
130
+
131
+ '''
132
+ model_all_about = {}
133
+
134
+ if modelname == '':
135
+ modelname = wf2name.stem[:3]
136
+ print(f'Assummed model name: {modelname}')
137
+ else:
138
+ print(f'Model name: {modelname}')
139
+ # with open(wf2name) as f:
140
+ with gzip.open(wf2name, mode="rt") as f:
141
+
142
+ gen0 = f.read()
143
+ # gen0 = gen0.decode("ISO-8859-1")
144
+ all_dict = json.loads(gen0)
145
+ pages = all_dict['_pages']
146
+ matched_page = [page for page in pages
147
+ if page["frequency"]["value"]== freq]
148
+
149
+ if (len_matched_page := len(matched_page)) != 1:
150
+ raise Exception(f'{len_matched_page} pages in the workfile with frequence {freq}. Precise one is allowed')
151
+
152
+
153
+ first_page = matched_page[0]
154
+ object_all = [o for o in first_page['_objects']]
155
+ types_set = {o['_type'] for o in object_all}
156
+ object_dict = {_type : [o for o in object_all if o['_type'] == _type ] for _type in types_set}
157
+ object_namecounts = {_type: [o['_name'] for o in this_object] for _type,this_object in object_dict.items() }
158
+ # breakpoint()
159
+ # Now extract the model
160
+ try:
161
+ thismodel_dict = object_dict['model'][0]
162
+ thismodel_raw = thismodel_dict['data'][0]
163
+ # breakpoint()
164
+ thismodel_raw_list = [l for l in thismodel_raw.split('\n') if len(l) > 1]
165
+
166
+ this_clean = [l for l in thismodel_raw_list if l[:4] not in {'@INN','@ADD'}] # The original frmls
167
+ this_add_vars = [l.split()[1] for l in thismodel_raw_list if l[:4] in {'@ADD'}] # variable with add factors
168
+ this_frml = '\n'.join(this_clean)
169
+ except:
170
+ this_frml = ''
171
+ # Take all series and make a dataframe
172
+ series_list = object_dict['series_double']
173
+
174
+ if freq == 'A':
175
+ index = [int(d[:4]) for d in object_dict['index'][0]['data']]
176
+ elif freq == 'Q':
177
+ datetime_index = pd.to_datetime( object_dict['index'][0]['data'])
178
+ index = datetime_index.to_period('Q')
179
+
180
+ series_data = [pd.Series(s['data'],name=s['_name'],index=index) for s in series_list]
181
+
182
+ wf_df = pd.concat(series_data,axis=1)
183
+
184
+
185
+ var_description = {s['_name']: lab2 for s in series_list
186
+ if (lab2 := s.get('_labels',{}).get('description',''))
187
+ }
188
+
189
+ var_description = {k: remove_url_and_replace_nbsp(v) for k,v in var_description.items() }
190
+
191
+
192
+ scalar_list = object_dict['scalar']
193
+ # for scalar in scalar_list:
194
+ # if 'value' in scalar.keys():
195
+ # wf_df.loc[:,scalar['_name']] = scalar['value']
196
+ scalar_data = [pd.Series(s['value'],name=s['_name'],index=index)
197
+ for s in scalar_list if 'value' in s.keys()]
198
+ # breakpoint()
199
+ wf_df = pd.concat([wf_df]+scalar_data,axis=1)
200
+ string_list = object_dict['stringobj']
201
+ # breakpoint()
202
+ mfmsa_dict = {o['_name']:o.get('value','empty') for o in string_list if o.get('_name','').startswith('MFMSA') }
203
+ mfmsa_options = mfmsa_dict.get('MFMSAOPTIONS','')
204
+
205
+ try:
206
+ estimates = {eq['_name'].upper()+f'.@COEF({idata+1})': str(data)
207
+ for eq in object_dict['equation7'] for idata,data in enumerate(eq['results']['data']) }
208
+ except:
209
+ estimates = {}
210
+
211
+ # breakpoint()
212
+ model_all_about['modelname'] = modelname
213
+ model_all_about['frml'] = this_frml
214
+ model_all_about['mfmsa_options'] = mfmsa_options
215
+ model_all_about['var_description'] = var_description
216
+ model_all_about['data'] = wf_df
217
+ model_all_about['object_dict_from_wf'] = object_dict
218
+ model_all_about['estimates'] = estimates
219
+
220
+
221
+ if save_file:
222
+ with open(f'{wf2name.parent / modelname}_clean.frm','wt') as f:
223
+ f.writelines(this_clean)
224
+ with open(f'{wf2name.parent / modelname}_mfmsa_options','wt') as f:
225
+ f.write(mfmsa_options)
226
+ with open(f'{wf2name.parent / modelname}_var_descriptions.json','wt') as f:
227
+ json.dump(var_description,f,indent=4)
228
+ wf_df.to_excel(f'{wf2name.parent / modelname}soln.xlsx')
229
+ print(f'{wf2name.parent / modelname}.... files are saved')
230
+
231
+ return model_all_about
232
+
233
+
234
+
235
+ @dataclass
236
+ class GrabWfModel():
237
+ """
238
+ This class takes a World Bank model specification, variable data, and variable description,
239
+ and transforms it into ModelFlow business language.
240
+
241
+ Args:
242
+ filename : any = '' # wf1 name
243
+ modelname : any = ''
244
+ freq : str = 'A'
245
+ eviews_run_lines : list = field(default_factory=list)
246
+ model_all_about : dict = field(default_factory=dict)
247
+ start : any = None # start of testing if not overruled by mfmsa
248
+ end : any = None # end of testing if not overruled by mfmsa
249
+ country_trans : any = lambda x:x[:] # function which transforms model specification
250
+ country_df_trans : any = lambda x:x # function which transforms initial dataframe
251
+ make_fitted : bool = False # if True, a clean equation for fitted variables is created
252
+ fit_start : any = 2000 # start of fitted model
253
+ fit_end : any = None # end of fitted model unless overruled by mfmsa
254
+ do_add_factor_calc : bool = True # calculate the add factors
255
+ test_frml : str = '' # a test model as string; if used, no wf processing
256
+ disable_progress : bool = False # disable progress bar
257
+ save_file : bool = False # save information to file
258
+ model_description : str = '' # model description
259
+ cty : str = '' # country ISO code like PAK, defaults to first 3 letters of modelname
260
+ cty_name : str = '' # country name like Pakistan, default via ISO mapping
261
+ var_groups : dict = field(default_factory=dict, init=False) # variable groups
262
+ extra_var_descriptions : dict = field(default_factory=dict) # extra variable descriptions
263
+
264
+ Methods:
265
+ __post_init__():
266
+ Initialize and process the model, transform equations, perform syntax checks,
267
+ and set up the model and data for simulation and analysis.
268
+
269
+ print_frml(pat='*', eviews=''):
270
+ Print model equations matching a wildcard pattern and optional EViews content filter.
271
+
272
+ trans_eviews(rawmodel):
273
+ (staticmethod) Convert EViews-style equations into ModelFlow syntax.
274
+
275
+ var_description (property):
276
+ Return enriched variable descriptions combining WF1 file, WB defaults, and extras.
277
+
278
+ wb_default_descriptions (property):
279
+ Load default World Bank variable descriptions from an online repository.
280
+
281
+ mfmsa_options (property):
282
+ Return the raw MFMSA options XML string.
283
+
284
+ mfmsa_options_dict (property):
285
+ Parse and return MFMSA options as a nested dictionary.
286
+
287
+ mfmsa_start_end (property):
288
+ Retrieve start and end periods from MFMSA metadata.
289
+
290
+ mfmsa_country (property):
291
+ Retrieve the country ISO code from MFMSA metadata.
292
+
293
+ mfmsa_quasiIdentities (property):
294
+ Return a set of quasi-identity variable names from MFMSA.
295
+
296
+ var_groups_default (property):
297
+ Provide default variable groupings for World Bank models.
298
+
299
+ dfmodel (property):
300
+ Return the transformed and enriched dataframe for model calculation.
301
+
302
+ __call__():
303
+ Return the processed model object and base input dataframe.
304
+
305
+ test_model(start=None, end=None, maxvar=1_000_000, maxerr=100, tol=0.0001,
306
+ showall=False, showinput=False, nofit=True):
307
+ Compare model calculations against input data to validate model fidelity.
308
+
309
+ iso_countries (property):
310
+ Return a dictionary mapping ISO country codes to country names.
311
+ """
312
+
313
+ filename : any = '' #wf1 name
314
+ modelname : any = ''
315
+ freq : str = 'A'
316
+ eviews_run_lines : list =field(default_factory=list)
317
+ start : any = None # start of testing if not overruled by mfmsa
318
+ end : any = None # end of testing if not overruled by mfmsa
319
+ country_trans : any = lambda x:x[:] # function which transform model specification
320
+ country_df_trans : any = lambda x:x # function which transforms initial dataframe
321
+ make_fitted : bool = False # if True, a clean equation for fittet variables is created
322
+ fit_start : any = 2000 # start of fittet model
323
+ fit_end : any = None # end of fittet model unless overruled by mfmsa
324
+ do_add_factor_calc : bool = True # calculate the add factors
325
+ test_frml : str ='' # a testmodel as string if used no wf processing
326
+ disable_progress : bool = False # Disable progress bar
327
+ save_file : bool = False # save information to file
328
+ model_description : str = '' # model description
329
+ cty : str = '' # country prefix like PAK
330
+ cty_name : str = '' # country name like Pakistan
331
+ var_groups : dict = field(default_factory=dict)
332
+ extra_var_descriptions : dict = field(default_factory=dict)
333
+
334
+ model_all_about : dict = field(default_factory=dict,init=False)
335
+
336
+ def __post_init__(self):
337
+ '''Process the model'''
338
+
339
+ if self.test_frml:
340
+ self.rawmodel_org =self.test_frml
341
+ self.modelname = self.modelname if self.modelname else 'Test'
342
+ self.cty = self.cty if self.cty else 'XXX'
343
+ self.cty_name = self.cty_name if self.cty_name else 'Text country'
344
+ else:
345
+ # breakpoint()
346
+ wf2name,self.modelname = wf1_to_wf2(self.filename ,modelname=self.modelname,eviews_run_lines= self.eviews_run_lines)
347
+ self.model_all_about = wf2_to_clean(wf2name,modelname=self.modelname,save_file= self.save_file,freq=self.freq)
348
+
349
+ print(f'\nProcessing the model:{self.modelname}',flush=True)
350
+ self.rawmodel_org = self.model_all_about['frml']
351
+
352
+
353
+ eviewsline = [l.strip() for l in self.rawmodel_org.split('\n')[:] ]
354
+
355
+ if '.@coef(' in self.rawmodel_org :
356
+ print('Estimated coifficients are substituted')
357
+ self.rawmodel_org = self.rawmodel_org.upper()
358
+ for k,v in self.model_all_about['estimates'].items():
359
+ self.rawmodel_org = self.rawmodel_org.replace(k,v)
360
+
361
+ self.rawmodel = self.country_trans(self.rawmodel_org)
362
+ rawmodel6 = self.trans_eviews(self.rawmodel)
363
+ bars = '{desc}: {percentage:3.0f}%|{bar}|{n_fmt}/{total_fmt}'
364
+
365
+ orgline = rawmodel6.split('\n')
366
+ line_type = ['ident' if l.strip().startswith('@IDENTITY') else 'stoc' for l in orgline]
367
+ line = [l.replace('@IDENTITY ','').replace(' ','') for l in orgline]
368
+
369
+ # breakpoint()
370
+ print('Check for Eviews @ which are not caught in the translation')
371
+ errline1 = [(l,o,e) for l,o,e in zip(line,orgline,eviewsline) if '@' in l or '.coef' in l ]
372
+ if errline1:
373
+ print('Probably errors as @ in lines:')
374
+ for l,o,e in errline1:
375
+ print(f'\nEviews line :{e}')
376
+ print(f'Original line :{o}')
377
+ print(f'New modelflow line:{l}')
378
+ raise Exception('@ in lines ')
379
+
380
+ self.all_frml = [nz.normal(l,add_add_factor=(typ=='stoc'),make_fitted=(typ=='stoc'),make_fixable =(typ=='stoc'),eviews=e)
381
+ for l,typ,e in tqdm(zip(line,line_type,eviewsline),
382
+ desc='Normalizing model',total=len(line),bar_format=bars,disable=self.disable_progress)]
383
+
384
+ syntaxlines = [f for f in tqdm(self.all_frml,
385
+ desc='Syntax check',total=len(self.all_frml),bar_format=bars,disable=self.disable_progress)
386
+ if not mp.check_syntax_udtryk_new(f.normalized)[0]]
387
+ if len(syntaxlines):
388
+ print(f'{len(syntaxlines)} Syntax errors. In these equations: ')
389
+ for l in syntaxlines:
390
+ err,text = mp.check_syntax_udtryk_new(l.normalized)
391
+ print(text)
392
+ l.fprint
393
+ raise Exception('Syntax error in frml ')
394
+ # print(' ',flush=True)
395
+
396
+ # print([ f.normalized for f in self.all_frml ])
397
+ self.all_frml_dict = {f.endo_var: f for f in self.all_frml}
398
+ lfname = ["<QUASIIDENT> " if typ == 'stoc' and endo_var in self.mfmsa_quasiIdentities else
399
+ "<DAMP,STOC> " if typ == 'stoc' else '<IDENT> '
400
+ for typ,endo_var in zip( line_type,self.all_frml_dict.keys()) ]
401
+ self.rorg = [fname + f.normalized for f,fname in zip(self.all_frml,lfname) ]
402
+ # breakpoint()
403
+ if self.make_fitted:
404
+ self.rfitmodel = ['<FIT> ' + f.fitted for f in self.all_frml if len(f.fitted)]
405
+ self.mfitmodel = model('\n'.join(self.rfitmodel))
406
+ self.mfitmodel.modelname = self.modelname + ' calc fittet values'
407
+ else:
408
+ self.rfitmodel = []
409
+
410
+ self.rres = [f'{f.calc_add_factor}' for f in self.all_frml if len(f.calc_add_factor)]
411
+ self.rres_tomodel ='\n'.join([f'FRML <CALC_ADD_FACTOR> {f.calc_add_factor}$' for f in self.all_frml if len(f.calc_add_factor)])
412
+ # self.fmodel = mp.exounroll(mp.tofrml ('\n'.join(self.rorg+self.rfitmodel)))+self.rres_tomodel
413
+ self.fmodel = mp.tofrml ('\n'.join(self.rorg+self.rfitmodel))+self.rres_tomodel
414
+ # breakpoint()
415
+ self.fres = ('\n'.join(self.rres))
416
+
417
+ var_groups = self.var_groups if self.var_groups else self.var_groups_default
418
+
419
+ self.mmodel = model(self.fmodel,modelname =self.modelname,
420
+ var_groups = var_groups,
421
+ )
422
+ self.mmodel.eviews_dict = {v: f.eviews for v,f in self.all_frml_dict.items()}
423
+
424
+
425
+ if self.cty:
426
+ cty = self.cty
427
+
428
+ else:
429
+ try:
430
+ cty = self.mfmsa_country
431
+ except:
432
+
433
+ cty = self.modelname[:min(len(self.modelname),3)]
434
+
435
+ cty_name = ( self.cty_name if self.cty_name else
436
+ self.iso_countries.get(cty,'No Name') )
437
+ self.mmodel.substitution= {'cty' :cty,
438
+ 'cty_name' : cty_name }
439
+
440
+ self.cty = cty
441
+ self.cty_name = cty_name
442
+
443
+ print(f'Country {cty}:{cty_name}')
444
+ self.mmodel.var_description = self.var_description
445
+ self.mmodel.model_description = self.model_description
446
+
447
+ # self.mmodel.set_var_description(self.model_all_about['var_description'])
448
+
449
+ self.mres = model(self.fres,modelname = f'Calculation of add factors for {self.modelname}')
450
+ # breakpoint()
451
+ if self.test_frml:
452
+ ...
453
+ print('inspect the test model')
454
+ else:
455
+ try:
456
+ temp_start,temp_end = self.mfmsa_start_end
457
+ except:
458
+ if type(self.start) == type(None) or type(self.end) == type(None):
459
+ raise Exception('Can not read start and end from MFMSA. Provide start and end in call ')
460
+
461
+ self.missing_descriptions = [v for v in sorted(self.mmodel.allvar) if v == self.mmodel.var_description[v]]
462
+ self.start = temp_start if type(self.start) == type(None) else self.start
463
+ self.end = temp_end if type(self.end) == type(None) else self.end
464
+
465
+ try:
466
+ if self.do_add_factor_calc:
467
+ self.base_input = self.mres.res(self.dfmodel,self.start,self.end)
468
+ else:
469
+ self.base_input = self.dfmodel
470
+ except Exception as e:
471
+ import traceback
472
+ ...
473
+ print(f'We have a problem {e}')
474
+ traceback.print_exc()
475
+
476
+
477
+ def print_frml(self,pat='*',eviews=''):
478
+ """
479
+ Print the formatted representation of equations in the model whose endogenous variable
480
+ names match the specified pattern and optionally filter them based on the EViews formula specification.
481
+
482
+ Parameters:
483
+ -----------
484
+ pat : str, optional
485
+ A shell-style wildcard pattern used to filter keys in the `all_frml_dict`.
486
+ Defaults to '*' (matches all keys).
487
+
488
+ eviews : str, optional
489
+ A string used to filter equations based on their EViews formula specification.
490
+ Only equations containing the specified `eviews` string (case-insensitive) will be displayed.
491
+ If not provided, all equations matching the `pat` pattern will be shown.
492
+
493
+ Behavior:
494
+ ---------
495
+ - Retrieves endogenous variable names from the `all_frml_dict` dictionary that match the `pat` pattern.
496
+ - If the `eviews` parameter is specified, further filters equations whose EViews formula
497
+ specification contains the `eviews` string (case-insensitive).
498
+ - Calls the `fprint` method for each matching equation to display its transformations.
499
+
500
+ Output:
501
+ -------
502
+ - Prints the equations matching the specified pattern and EViews filter.
503
+ - Displays a message if no matching equations are found.
504
+ """
505
+
506
+ variables = model.list_names([k for k in self.all_frml_dict.keys()] , pat, sort=True)
507
+
508
+ if eviews:
509
+ variables = [v for v in variables if eviews.upper() in self.all_frml_dict[v].eviews.upper() ]
510
+
511
+ if len(variables):
512
+ print(f'\nEquations in the model matching :{pat}')
513
+ print(f'And where eviews eq contains :{eviews}')
514
+ for v in variables:
515
+ if v in self.var_description:
516
+ print(self.var_description[v])
517
+ self.all_frml_dict[v].fprint
518
+ print('\n')
519
+ else:
520
+ print(f'\nNo Equations in the model matching {pat}')
521
+
522
+
523
+
524
+
525
+ @staticmethod
526
+ def trans_eviews(rawmodel):
527
+ '''
528
+ Takes Eviews specifications and wrangle them into modelflow specifications
529
+
530
+ Args:
531
+ rawmodel (TYPE): a raw model .
532
+
533
+ Returns:
534
+ rawmodel6 (TYPE): a model with the appropiate eviews transformations.
535
+
536
+ '''
537
+ rawmodel0 = '\n'.join(l for l in rawmodel.upper().split('\n') if len(l.strip()) >=2)
538
+ # trailing and leading "
539
+ rawmodel1 = '\n'.join(l[1:-1] if l.startswith('"') else l for l in rawmodel0.split('\n'))
540
+ # powers
541
+ rawmodel2 = rawmodel1.replace('^','**').replace('""',' ').replace('"',' ').\
542
+ replace('@EXP','exp').replace('@RECODE','recode').replace('@MOVAV','movavg').replace('@LOGIT','logit_inverse') \
543
+ .replace('@MEAN(@PC(','@AVERAGE_GROWTH((').replace('@PCY','PCT_GROWTH').replace('@PC','PCT_GROWTH')\
544
+ .replace('@PMAX','MAX').replace('@TREND','EVIEWS_TREND').replace('@ABS','ABS').replace('@SQRT(','SQRT(')\
545
+ .replace('@PMAX(','MAX(') .replace('@CNORM(','NORMCDF(')
546
+ # @ELEM and @DURING
547
+ # @ELEM and @DURING
548
+ rawmodel3 = nz.elem_trans(rawmodel2)
549
+ rawmodel4 = re.sub(r'@DURING\( *([0-9Q]+) *\)', r'during_\1',rawmodel3)
550
+ rawmodel50 = re.sub(r'@DURING\( *([0-9Q]+) *([0-9Q]+) *\)', r'during_\1_\2',rawmodel4)
551
+ rawmodel5 = re.sub(
552
+ r"@BETWEEN\(\s*(\w+)\s*,\s*([^,]+)\s*,\s*([^)]+)\s*\)",
553
+ r"(1.0*float(\2 <= \1 <= \3))",
554
+ rawmodel50
555
+ )
556
+ #rawmodel5 = rawmodel50
557
+ # during check
558
+ ldur = '\n'.join(l for l in rawmodel5.split('\n') if '@DURING' in l)
559
+ ldur2 = '\n'.join(l for l in rawmodel5.split('\n') if 'during' in l)
560
+
561
+ # check D(
562
+ ld = '\n'.join(l for l in rawmodel5.split('\n') if re.search(r'([^A-Z]|^)D\(',l) )
563
+ ld1 = '\n'.join(l for l in rawmodel5.split('\n') if re.search(r'([^A-Z0-9_]|^)D\(',l) )
564
+ # breakpoint()
565
+ rawmodel6 = nz.funk_replace('D','DIFF',rawmodel5)
566
+ # did we get all the lines
567
+ ldif = '\n'.join(l for l in rawmodel6.split('\n') if 'DIFF(' in l )
568
+ return rawmodel6
569
+
570
+ @functools.cached_property
571
+ def var_description(self):
572
+ '''
573
+ Adds var descriptions for add factors, exogenizing dummies and exoggenizing values
574
+ '''
575
+
576
+
577
+
578
+ try:
579
+ this = {k:v for k,v in self.model_all_about['var_description'].items()
580
+ if v!='TEMP' and k in (self.mmodel.endogene | self.mmodel.exogene) }
581
+ print('Variable description in wf1 file read')
582
+ except:
583
+ print(' ')
584
+ print('*** No variable description in wf1 file',flush=True)
585
+ this = {}
586
+ generic = self.wb_default_descriptions
587
+ print(f'var_description loaded from WF {len(this)=}')
588
+
589
+ # breakpoint()
590
+ this_both = this | generic | self.extra_var_descriptions
591
+ out = self.mmodel.enrich_var_description(this_both)
592
+ return out
593
+
594
+ @property
595
+ def wb_default_descriptions(self):
596
+ import urllib.request
597
+ try:
598
+
599
+ default_url=r'https://raw.githubusercontent.com/IbHansen/modelflow-manual/main/model_repo/'
600
+ urlfile = (Path(default_url) / Path('wbvarnames.txt').name).as_posix().replace('https:/','https://')
601
+
602
+ with urllib.request.urlopen(urlfile) as f:
603
+ lines_all = f.read().decode("utf-8")
604
+
605
+
606
+ lines = lines_all.split('\n')
607
+ alldes = {line.split(' ',1)[0] : line.split(' ',1)[1] for line in lines }
608
+ var_description_this = {resvar: des for desvar, des in alldes.items() if ((resvar:= f'{self.cty}{desvar}') in self.mmodel.allvar.keys()) }
609
+ var_description_wld = {desvar: des for desvar, des in alldes.items() if desvar in self.mmodel.allvar.keys()}
610
+
611
+ var_description = {**var_description_this, **var_description_wld}
612
+ print(f'Default WB var_description loaded {self.cty=} {len(var_description)=}')
613
+ return var_description
614
+ except:
615
+ print('No default WB var_description loaded')
616
+ return {}
617
+
618
+ @property
619
+ def mfmsa_options(self):
620
+ '''Grab the mfmsa options, a world bank speciality'''
621
+ options = self.model_all_about.get('mfmsa_options','')
622
+
623
+ return options
624
+
625
+ @property
626
+ def mfmsa_options_dict(self):
627
+ import xml
628
+ def xml_to_dict(element):
629
+ if len(element) == 0: # If the element has no children
630
+ return element.text
631
+ return {child.tag: xml_to_dict(child) for child in element}
632
+ root = xml.etree.ElementTree.fromstring(self.mfmsa_options)
633
+
634
+ return xml_to_dict(root)
635
+
636
+
637
+
638
+
639
+
640
+ @property
641
+ def mfmsa_start_end(self):
642
+ '''Finds the start and end from the MFMSA entry'''
643
+ import xml
644
+ root = xml.etree.ElementTree.fromstring(self.mfmsa_options)
645
+ start = (root.find('.//SolveStart').text)
646
+ end = (root.find('.//SolveEnd').text)
647
+ return start,end
648
+
649
+ @property
650
+ def mfmsa_country(self):
651
+ '''Finds the start and end from the MFMSA entry'''
652
+ import xml
653
+ root = xml.etree.ElementTree.fromstring(self.mfmsa_options)
654
+ country = (root.find('.//iFace/country').text)
655
+ return country
656
+
657
+
658
+
659
+ @functools.cached_property
660
+ def mfmsa_quasiIdentities(self):
661
+ '''Finds the a set containing quasiidendities'''
662
+ import xml
663
+ try:
664
+ root = xml.etree.ElementTree.fromstring(self.mfmsa_options)
665
+ quasi = root.find(".//quasiIdentities").text
666
+ quasiset = {f'{self.modelname}{stem}' for stem in quasi.split()}.union(
667
+ {f'{stem}' for stem in quasi.split()})
668
+ except:
669
+ print(f'No quasiIdentities in {self.modelname}')
670
+ quasiset = set()
671
+ return quasiset
672
+
673
+ @property
674
+ def var_groups_default(self):
675
+ print('Default WB var_group loaded')
676
+
677
+ return {'Headline': '{cty}NYGDPMKTPXN {cty}NRTOTLCN {cty}LMUNRTOTL_ {cty}BFFINCABDCD {cty}BFBOPTOTLCD {cty}GGBALEXGRCN {cty}GGDBTTOTLCN {cty}BNCABLOCLCD_ {cty}FPCPITOTLXN',
678
+ 'National income accounts': '{cty}NY*',
679
+ 'National expenditure accounts': '{cty}NE*',
680
+ 'Value added accounts': '{cty}NV*',
681
+ 'Balance of payments exports': '{cty}BX*',
682
+ 'Balance of payments exports and value added ': '{cty}BX* {cty}NV*',
683
+ 'Balance of Payments Financial Account': '{cty}BF*',
684
+ 'General government fiscal accounts': '{cty}GG*',
685
+ 'World all': 'WLD*',
686
+ 'All variables' : '*'}
687
+
688
+
689
+ @functools.cached_property
690
+ def dfmodel(self):
691
+ '''The original input data enriched with during variablees, variables containing
692
+ values for specific historic years and model specific transformation '''
693
+ per_transform = lambda p: int(p) if self.freq== 'A' else p
694
+
695
+
696
+ # Now the data
697
+ df = self.model_all_about['data']
698
+ # breakpoint()
699
+
700
+
701
+ #% Now set the vars with fixedvalues
702
+ import warnings
703
+ with warnings.catch_warnings():
704
+ warnings.simplefilter(action='ignore')
705
+
706
+ value_vars = self.mmodel.vlist('*_value_*')
707
+ # print(f'{value_vars=}')
708
+ for var,val,per in (v.rsplit('_',2) for v in value_vars) :
709
+ # print(f' {var=} {val=} {per=} {int(per)=} var= {var}_{val}_{per}')
710
+ df.loc[:,f'{var}_{val}_{per}'] = df.loc[int(per) if self.freq== 'A' else per ,var]
711
+
712
+
713
+ self.showvaluevars = df[value_vars]
714
+
715
+
716
+
717
+ #% now set the values of the dummies
718
+ # breakpoint()
719
+ during_vars = self.mmodel.vlist('*during_*')
720
+ with warnings.catch_warnings():
721
+ warnings.simplefilter(action='ignore', category=pd.errors.PerformanceWarning)
722
+ for varname,(dur,per) in ((v,v.split('_',1)) for v in during_vars):
723
+ df.loc[:,varname]=0
724
+ # print(varname,dur,per)
725
+ pers = per.split('_')
726
+ if len(pers) == 1:
727
+ df.loc[per_transform(pers[0]),varname] = 1
728
+ else:
729
+ df.loc[per_transform(pers[0]):per_transform(pers[1]),varname]=1.
730
+ self.showduringvars = df[during_vars]
731
+
732
+ if self.make_fitted:
733
+ # try:
734
+ # temp_start,temp_end = self.mfmsa_start_end
735
+ # except:
736
+ # if type(self.fit_end) == type(None):
737
+ # raise Exception('Can not read end period from MFMSA. Provide fit_end in call ')
738
+
739
+ if type(self.fit_end) == type(None):
740
+ self.fit_end = self.end
741
+ if type(self.fit_start) == type(None):
742
+ self.fit_start = self.start
743
+ df = self.mfitmodel.res(df,self.fit_start,self.fit_end)
744
+
745
+ # breakpoint()
746
+ df = df.loc[:,[c for c in df.columns if c in self.mmodel.allvar_set]]
747
+ df_out = self.mmodel.insertModelVar(df).pipe(self.country_df_trans).astype('float64').fillna(0.0)
748
+
749
+
750
+ return df_out
751
+
752
+ def __call__(self):
753
+ '''returns the model and the base input'''
754
+ return self.mmodel,self.base_input
755
+
756
+ def test_model(self,start=None,end=None,maxvar=1_000_000, maxerr=100,tol=0.0001,showall=False,showinput=False,nofit=True):
757
+ '''
758
+ Compares a straight calculation with the input dataframe.
759
+
760
+ shows which variables dont have the same value
761
+
762
+ Args:
763
+ df (TYPE): dataframe to run.
764
+ start (TYPE, optional): start period. Defaults to None.
765
+ end (TYPE, optional): end period. Defaults to None.
766
+ maxvar (TYPE, optional): how many variables are to be chekked. Defaults to 1_000_000.
767
+ maxerr (TYPE, optional): how many errors to check Defaults to 100.
768
+ tol (TYPE, optional): check for absolute value of difference. Defaults to 0.0001.
769
+ showall (TYPE, optional): show more . Defaults to False.
770
+ showinput (TYPE, optional): show the input values Defaults to False.
771
+ nofit : if True dont show the fitted values.default True
772
+
773
+ Returns:
774
+ None.
775
+
776
+ '''
777
+ _start = start if start else self.start
778
+ _end = end if end else self.end
779
+ # breakpoint()
780
+
781
+ resresult = self.mmodel(self.base_input,_start,_end,reset_options=True,silent=0,solver='res')
782
+ self.mmodel.basedf = self.dfmodel
783
+ pd.options.display.float_format = '{:.10f}'.format
784
+ err=0
785
+ pd.set_option('display.max_columns', None)
786
+ pd.set_option("display.width", 1000)
787
+ print(f'\nChekking residuals for {self.mmodel.name} {_start} to {_end}')
788
+ for i,v in enumerate(self.mmodel.solveorder):
789
+ # if v.endswith('_FITTED'): continue
790
+ if i > maxvar : break
791
+ if err > maxerr : break
792
+ # print(f'{v=} {nofit=} {nofit and v.endswith("_FITTED")=}' )
793
+ if nofit and v.endswith('_FITTED'): continue
794
+ check = self.mmodel.get_values(v,pct=True).T
795
+ check.columns = ['Before check','After calculation','Difference','Pct']
796
+ # breakpoint()
797
+ if (check.Difference.abs() >= tol).any():
798
+ err=err+1
799
+ maxdiff = check.Difference.abs().max()
800
+ maxpct = check.Pct.abs().max()
801
+ # breakpoint()
802
+ if err==1 :
803
+ print('\nVariable with residuals above threshold')
804
+ print(f"{v:{self.mmodel.maxnavlen}}, Max difference:{maxdiff:15.8f} Max Pct {maxpct:15.10f}% It is number {i:5} in the solveorder and error number {err}")
805
+ if showall:
806
+ print(f'{self.mmodel.allvar[v]["frml"]}')
807
+ print(f'{self.mmodel.var_description[v]}')
808
+
809
+ print(f'\nResult of equation \n {check}\n')
810
+ if showinput:
811
+ print(f'\nEquation values before calculations: \n {self.mmodel.get_eq_values(v,last=False,showvar=1)} \n')
812
+ self.mmodel.oldkwargs = {}
813
+ pd.reset_option('max_columns')
814
+ pd.reset_option('max_columns')
815
+
816
+
817
+ @property
818
+ def iso_countries(self):
819
+ return {
820
+ "AFG": "Afghanistan",
821
+ "AGO": "Angola",
822
+ "ALB": "Albania",
823
+ "ARE": "United Arab Emirates",
824
+ "ARG": "Argentina",
825
+ "ARM": "Armenia",
826
+ "AS4": "ASEAN-4",
827
+ "ASN": "ASEAN",
828
+ "ATG": "Antigua and Barbuda",
829
+ "AUS": "Australia",
830
+ "AUT": "Austria",
831
+ "AZE": "Azerbaijan",
832
+ "BDI": "Burundi",
833
+ "BEL": "Belgium",
834
+ "BEN": "Benin",
835
+ "BFA": "Burkina Faso",
836
+ "BGD": "Bangladesh",
837
+ "BGR": "Bulgaria",
838
+ "BHR": "Bahrain",
839
+ "BHS": "Bahamas",
840
+ "BIH": "Bosnia and Herzegovina",
841
+ "BLR": "Belarus",
842
+ "BLZ": "Belize",
843
+ "BOL": "Bolivia",
844
+ "BRA": "Brazil",
845
+ "BRB": "Barbados",
846
+ "BWA": "Botswana",
847
+ "CAF": "Central African Republic",
848
+ "CAN": "Canada",
849
+ "CEE": "Central and Eastern Europe",
850
+ "CET": "Central and European Transition",
851
+ "CHE": "Switzerland",
852
+ "CHL": "Chile",
853
+ "CHN": "China",
854
+ "CIS": "Commonwealth of Independent States",
855
+ "CIV": "Cote d'Ivoire",
856
+ "CMR": "Cameroon",
857
+ "COG": "Congo, Rep.",
858
+ "COL": "Colombia",
859
+ "COM": "Comoros",
860
+ "CPV": "Cabo Verde",
861
+ "CRI": "Costa Rica",
862
+ "CYP": "Cyprus",
863
+ "CZE": "Czech Republic",
864
+ "DEU": "Germany",
865
+ "DEV": "Developing Countries",
866
+ "DJI": "Djibouti",
867
+ "DMA": "Dominica",
868
+ "DNK": "Denmark",
869
+ "DOM": "Dominican Republic",
870
+ "DZA": "Algeria",
871
+ "E10": "Euro-Area (10)",
872
+ "E27": "Euro-Area (28)",
873
+ "EAM": "EAP: Oil Importers",
874
+ "EAO": "EAP excl. China",
875
+ "EAP": "East Asia and Pacific",
876
+ "EAX": "EAP: Oil Exporters",
877
+ "ECA": "Europe and Central Asia",
878
+ "ECM": "ECA: Oil Importers",
879
+ "ECU": "Ecuador",
880
+ "ECX": "ECA: Oil Exporters",
881
+ "EGY": "Egypt, Arab Rep.",
882
+ "EMU": "Euro Area (19)",
883
+ "ERI": "Eritrea",
884
+ "ESP": "Spain",
885
+ "EST": "Estonia",
886
+ "ESU": "ECA Transition Countries",
887
+ "ETH": "Ethiopia",
888
+ "FIN": "Finland",
889
+ "FRA": "France",
890
+ "GAB": "Gabon",
891
+ "GBR": "United Kingdom",
892
+ "GCC": "MENA: GCC Countries",
893
+ "GEO": "Georgia",
894
+ "GHA": "Ghana",
895
+ "GIN": "Guinea",
896
+ "GMB": "Gambia, The",
897
+ "GNB": "Guinea-Bissau",
898
+ "GNQ": "Equatorial Guinea",
899
+ "GRC": "Greece",
900
+ "GTM": "Guatemala",
901
+ "GUY": "Guyana",
902
+ "HIY": "High Income Countries",
903
+ "HKG": "Hong Kong SAR, China",
904
+ "HND": "Honduras",
905
+ "HRV": "Croatia",
906
+ "HTI": "Haiti",
907
+ "HUN": "Hungary",
908
+ "HYO": "High Income (OECD)",
909
+ "IDN": "Indonesia",
910
+ "IND": "India",
911
+ "IRL": "Ireland",
912
+ "IRN": "Iran, Islamic Rep.",
913
+ "IRQ": "Iraq",
914
+ "ISL": "Iceland",
915
+ "ISR": "Israel",
916
+ "ITA": "Italy",
917
+ "JAM": "Jamaica",
918
+ "JOR": "Jordan",
919
+ "JPN": "Japan",
920
+ "KAZ": "Kazakhstan",
921
+ "KEN": "Kenya",
922
+ "KGZ": "Kyrgyz Republic",
923
+ "KHM": "Cambodia",
924
+ "KOR": "Korea, Rep.",
925
+ "KSV": "Kosovo (KSV)",
926
+ "XKX": "Kosovo (XKX)",
927
+ "KWT": "Kuwait",
928
+ "LAA": "LAC: Central America",
929
+ "LAC": "Latin America & Carribean",
930
+ "LAI": "LAC: Caribbean",
931
+ "LAM": "LAC: Oil Importers",
932
+ "LAO": "Lao, PDR",
933
+ "LAX": "LAC: Oil Exporters",
934
+ "LBN": "Lebanon",
935
+ "LBR": "Liberia",
936
+ "LBY": "Libya",
937
+ "LCA": "St. Lucia",
938
+ "LIC": "Low Income Countries",
939
+ "LKA": "Sri Lanka",
940
+ "LML": "Low and Middle Income: excl. China/India",
941
+ "LMX": "Low and Middle Income: excl. CEE & CIS",
942
+ "LSO": "Lesotho",
943
+ "LTD": "Limited data countries",
944
+ "LTU": "Lithuania",
945
+ "LUX": "Luxembourg",
946
+ "LVA": "Latvia",
947
+ "LXA": "LAC excl. Argentina",
948
+ "MAC": "Macau",
949
+ "MAR": "Morocco",
950
+ "MDA": "Moldova, Rep.",
951
+ "MDG": "Madagascar",
952
+ "MDV": "Maldives",
953
+ "MEX": "Mexico",
954
+ "MGR": "MENA: Maghreb",
955
+ "MIC": "Middle Income Countries",
956
+ "MKD": "North Macedonia", # "Macedonia, FYR",
957
+ "MLI": "Mali",
958
+ "MLT": "Malta",
959
+ "MNA": "Middle East and North Africa",
960
+ "MNE": "Montenegro",
961
+ "MNG": "Mongolia",
962
+ "MNX": "Middle East and North Africa: excl. Syria and",
963
+ "MOM": "MNA: Oil Importers",
964
+ "MOX": "MNA: Oil Exporters",
965
+ "MOZ": "Mozambique",
966
+ "MRT": "Mauritania",
967
+ "MSH": "MENA: Mashreq",
968
+ "MMR": "Myanmar",
969
+ "MUS": "Mauritius",
970
+ "MWI": "Malawi",
971
+ "MYS": "Malaysia",
972
+ "NAM": "Namibia",
973
+ "NER": "Niger",
974
+ "NGA": "Nigeria",
975
+ "NIC": "Nicaragua",
976
+ "NIE": "Asian High Income Non-EU",
977
+ "NLD": "Netherlands",
978
+ "NOR": "Norway",
979
+ "NPL": "Nepal",
980
+ "NZL": "New Zealand",
981
+ "OHX": "HIY: Oil Exporters",
982
+ "OHY": "HIY: Non-OECD",
983
+ "OLM": "DEV: Oil Importers",
984
+ "OLX": "DEV: Oil Exporters",
985
+ "OMN": "Oman",
986
+ "OSS": "SST excl. ZAF/NGA",
987
+ "PAK": "Pakistan",
988
+ "PAN": "Panama",
989
+ "PER": "Peru",
990
+ "PHL": "Philippines",
991
+ "PNG": "Papua New Guinea",
992
+ "POL": "Poland",
993
+ "PRT": "Portugal",
994
+ "PRY": "Paraguay",
995
+ "ROM": "Romania (ROM)",
996
+ "ROU": "Romania (ROU)",
997
+ "RUS": "Russian Federation",
998
+ "RWA": "Rwanda",
999
+ "QAT": "Qatar",
1000
+ "SAO": "Other South Asia",
1001
+ "SAS": "South Asia",
1002
+ "SAU": "Saudi Arabia",
1003
+ "SDN": "Sudan",
1004
+ "SEN": "Senegal",
1005
+ "SFA": "Sub-Saharan Africa CFA",
1006
+ "SGP": "Singapore",
1007
+ "SLB": "Solomon Islands",
1008
+ "SLE": "Sierra Leone",
1009
+ "SLV": "El Salvador",
1010
+ "SOX": "SST: Oil Exporters",
1011
+ "SRB": "Serbia",
1012
+ "SSA": "SST excl. ZAF",
1013
+ "SSM": "SST: Oil Importers",
1014
+ "SST": "Sub-Saharan Africa",
1015
+ "STP": "Sao Tome & Principe",
1016
+ "SUR": "Suriname",
1017
+ "SVK": "Slovakia",
1018
+ "SVN": "Slovenia",
1019
+ "SWE": "Sweden",
1020
+ "SWZ": "Swaziland",
1021
+ "SYC": "Seychelles",
1022
+ "SYR": "Syrian Arab Republic",
1023
+ "TCC": "Turkish Cyprus",
1024
+ "TCD": "Chad",
1025
+ "TGO": "Togo",
1026
+ "THA": "Thailand",
1027
+ "TJK": "Tajikistan",
1028
+ "TTO": "Trinidad and Tobago",
1029
+ "TUN": "Tunisia",
1030
+ "TLS": "Timor l'Este",
1031
+ "TUR": "Türkiye", # "Turkey",
1032
+ "TZA": "Tanzania, United Rep.",
1033
+ "UGA": "Uganda",
1034
+ "UKR": "Ukraine",
1035
+ "URY": "Uruguay",
1036
+ "USA": "United States",
1037
+ "UZB": "Uzbekistan",
1038
+ "VCT": "St. Vincent and the Grenadines",
1039
+ "VEN": "Venezuela, RB",
1040
+ "VNM": "Vietnam",
1041
+ "VUT": "Vanuatu",
1042
+ "WBG": "West Bank and Gaza (WBG)",
1043
+ "PSE": "West Bank and Gaza (PSE)",
1044
+ "WLT": "World (WBG Members)",
1045
+ "YEM": "Yemen, Rep.",
1046
+ "ZAF": "South Africa",
1047
+ "ZAR": "Congo, Dem. Rep. (ZAR)",
1048
+ "COD": "Congo, Dem. Rep. (COD)",
1049
+ "ZMB": "Zambia",
1050
+ "ZWE": "Zimbabwe",
1051
+ }
1052
+
1053
+
1054
+
1055
+ if __name__ == '__main__':
1056
+
1057
+
1058
+ #%% Testing
1059
+ if 1:
1060
+ pak_trans = lambda input : input.replace('- 01*D(','-1*D(')
1061
+
1062
+
1063
+ ago_trans = lambda input : input.replace('@MEAN(AGOBNCABFUNDCD/AGONYGDPMKTPCD,"2000 2020")','MEAN_AGOBNCABFUNDCD_DIV_AGONYGDPMKTPCD')
1064
+ ago_eviews_run_lines = ['smpl @ALL','series MEAN_AGOBNCABFUNDCD_DIV_AGONYGDPMKTPCD = @MEAN(AGOBNCABFUNDCD/AGONYGDPMKTPCD,"2000 2020")']
1065
+
1066
+ mda_trans = lambda input: input.replace('_MDAsbbrev.@coef(2)','_MDASBBREV_at_COEF_2')
1067
+ mda_eviews_run_lines = ['Scalar _MDASBBREV_at_COEF_2 = _MDASBBREV.@COEF(+2)']
1068
+
1069
+
1070
+ filedict = {f.stem[:3].lower():f for f in Path(r'C:\wb new\Modelflow\ib\developement\original').glob('*.wf1')}
1071
+ filedict = {f.stem[:3].lower():f for f in Path(r'C:\wb new\Modelflow\ib\developement\original').glob('*.wf2')}
1072
+ modelname = 'pak'
1073
+ filename = filedict[modelname]
1074
+
1075
+
1076
+ eviews_run_lines= globals().get(f'{modelname}_eviews_run_lines',[])
1077
+ country_trans = globals().get(f'{modelname}_trans' ,lambda x : x[:])
1078
+ country_df_trans = globals().get(f'{modelname}_df_trans',lambda x : x)
1079
+
1080
+
1081
+ cmodel = GrabWfModel(filename,
1082
+ # eviews_run_lines= eviews_run_lines,
1083
+ freq='A',
1084
+ country_trans = country_trans,
1085
+ country_df_trans = country_df_trans,
1086
+ make_fitted = True,
1087
+ do_add_factor_calc=True,
1088
+ start = 2020,
1089
+ end = 2100,
1090
+ fit_start = 2000, # Start of calculation of fittet model in baseline
1091
+ fit_end = 2030 # end of calc for fittted model, if None taken from mdmfsa options
1092
+ )
1093
+ # assert 1==2
1094
+ if 0:
1095
+ cmodel.test_model(cmodel.start,cmodel.end,maxerr=100,tol=0.001,showall=0)
1096
+
1097
+
1098
+ grab_lookat = cmodel
1099
+ mlookat = grab_lookat.mmodel
1100
+ lookat_des = mlookat.var_description
1101
+ lookat_equations = mlookat.equations
1102
+ lookat_all_frml_dict = grab_lookat.all_frml_dict
1103
+ base_input = cmodel.base_input
1104
+ mlookat(base_input,2020,2022)
1105
+
1106
+ #%%
1107
+ re.sub(r'@DURING\( *([0-9q]+) *\)', r'during_\1','0.755095546689654*@DURING("2020q4")'.replace('"',' '))