def check(self): defaults = { 'name': 'anonymous', 'init_values': {}, 'parameters_values': {}, 'covariances': sympy.Matrix(), 'variables_ordering': [], 'parameters_ordering': [], 'shocks_ordering': [] } from collections import OrderedDict as odict equations_groups = odict() for i, eq in enumerate(self['equations']): eq.tags['eq_number'] = i if 'eq_type' in eq.tags: g = eq.tags['eq_type'] if g not in equations_groups: equations_groups[g] = [] equations_groups[g].append(eq) self['equations_groups'] = equations_groups for k in defaults: if k not in self: self[k] = defaults[k] if not self.get('equations'): raise Exception('No equations specified') for n, eq in enumerate(self['equations']): if not isinstance(eq, Equation): self['equations'][n] = Equation(eq, 0)
def solve_recursive_block(equations): from dolo.symbolic.symbolic import Equation system = {eq.lhs: eq.rhs for eq in equations} from dolo.misc.triangular_solver import solve_triangular_system sol = solve_triangular_system(system) solved_equations = [Equation(eq.lhs, sol[eq.lhs]) for eq in equations] return solved_equations
def build_lagrangian(self): vars = list(self.base_model.variables) if self.instrument_equation != None and self.instrument_equation.tags.has_key( 'ramsey_instrument'): ramsey_instrument = [ v for v in vars if v.name == self.instrument_equation.tags['ramsey_instrument'] ] ramsey_instrument = ramsey_instrument[0] self.equations.remove(self.instrument_equation) vars.remove(ramsey_instrument) # first we create one multiplicator by equation n_eq = len(self.equations) lambdas = [] for i in range(n_eq): v = Variable('Lambda_' + str(i + 1), 0) self.variables_ordering.append(v) lambdas.append(v) t_cur = self.objective + sum( [self.equations[i].gap * lambdas[i] for i in range(n_eq)]) t_fut = time_shift(t_cur, +1) t_past = time_shift(t_cur, -1) beta = self.discount lagrangian = 1 / beta * t_past + t_cur + beta * t_fut self.lagrangian = lagrangian print 'There are ' + str(len(self.equations)) + 'equations' print 'There are ' + str(len(vars)) + 'variables' if self.instrument_equation != None and self.instrument_equation.tags.has_key( 'ramsey_instrument'): # vars = [ramsey_instrument] + vars eq = lagrangian.diff(ramsey_instrument) eq = Equation(eq, 0).tag(name='Derivative of lagrangian w.r.t : ' + str(ramsey_instrument)) eq.tags.update(self.instrument_equation.tags) self.equations.append(eq) for v in vars: if v in self.ignored_variables: pass eq = lagrangian.diff(v) eq = Equation(eq, 0).tag(name='Derivative of lagrangian w.r.t : ' + str(v)) self.equations.append(eq)
def portfolios_to_deterministic(model, pf_names): ####### ####### import re regex = re.compile('.*<=(.*)<=.*') for i, eq in enumerate(model.equations_groups['arbitrage']): from dolo.symbolic.symbolic import Variable, Equation m = regex.match(eq.tags['complementarity']) vs = m.group(1).strip() if vs in pf_names: v = Variable(vs) neq = Equation(v, 0) neq.tag(**eq.tags) model.equations_groups['arbitrage'][i] = neq print('Warning : initial model changed') model.update() return model
def portfolios_to_deterministic(model,pf_names): ####### ####### import re regex = re.compile('.*<=(.*)<=.*') for i,eq in enumerate(model.equations_groups['arbitrage']): from dolo.symbolic.symbolic import Variable, Equation m = regex.match(eq.tags['complementarity']) vs = m.group(1).strip() if vs in pf_names: v = Variable(vs) neq = Equation(v,0) neq.tag(**eq.tags) model.equations_groups['arbitrage'][i] = neq print('Warning : initial model changed') model.update() return model
def parse_yaml_text(txt, verbose=False): ''' Imports the content of a modfile into the current interpreter scope ''' txt = txt.replace('..', '-') txt = txt.replace('--', '-') txt = txt.replace('^', '**') raw_dict = yaml.load(txt) if verbose == True: print('YAML file successfully parsed') declarations = raw_dict['declarations'] # check if 'controls' in declarations: variables_groups = OrderedDict() known_types = [ 'states', 'controls', 'expectations', 'auxiliary', 'auxiliary_2' ] for vtype in known_types: if vtype in declarations: variables_groups[vtype] = [ Variable(vn, 0) for vn in declarations[vtype] ] variables_ordering = sum(variables_groups.values(), []) else: vnames = declarations['variables'] variables_ordering = [Variable(vn, 0) for vn in vnames] variables_groups = None parameters_ordering = [Parameter(vn) for vn in declarations['parameters']] shocks_ordering = [Shock(vn, 0) for vn in declarations['shocks']] context = [ (s.name, s) for s in variables_ordering + parameters_ordering + shocks_ordering ] context = dict(context) # add some common functions for f in [ sympy.log, sympy.exp, sympy.sin, sympy.cos, sympy.tan, sympy.asin, sympy.acos, sympy.atan, sympy.sinh, sympy.cosh, sympy.tanh, sympy.pi ]: context[str(f)] = f context['sqrt'] = sympy.sqrt import re # we recognize two kinds of equations: # lhs = rhs # lhs | comp where comp is a complementarity condition equations = [] equations_groups = OrderedDict() raw_equations = raw_dict['equations'] if isinstance(raw_equations, dict): # tests whether there are groups of equations for groupname in raw_equations.keys(): equations_groups[groupname] = [] for raw_eq in raw_equations[ groupname]: # Modfile is supposed to represent a global model. TODO: change it teqg = raw_eq.split('|') teq = teqg[0] if '=' in teq: lhs, rhs = str.split(teq, '=') else: lhs = teq rhs = '0' try: lhs = eval(lhs, context) rhs = eval(rhs, context) except Exception as e: print('Error parsing equation : ' + teq) print str(e) raise e eq = Equation(lhs, rhs) eq.tag(eq_type=groupname) if len(teqg) > 1: comp = teqg[1] eq.tag(complementarity=comp) equations.append(eq) #equations_groups[groupname].append( eq ) else: for teq in raw_equations: if '=' in teq: lhs, rhs = str.split(teq, '=') else: lhs = teq rhs = '0' try: lhs = eval(lhs, context) rhs = eval(rhs, context) except Exception as e: print('Error parsing equations : ' + teq) print str(e) eq = Equation(lhs, rhs) equations.append(eq) equations_groups = None parameters_values = {} init_values = {} covariances = None if 'calibration' in raw_dict: calibration = raw_dict['calibration'] if 'parameters' in calibration: parameters_values = [ (Parameter(k), eval(str(v), context)) for k, v in calibration['parameters'].iteritems() ] parameters_values = dict(parameters_values) #steady_state = raw_dict['steady_state'] if 'steady_state' in calibration: init_values = [ (Variable(vn, 0), eval(str(value), context)) for vn, value in calibration['steady_state'].iteritems() ] init_values = dict(init_values) if 'covariances' in calibration: context['sympy'] = sympy covariances = eval( 'sympy.Matrix({0})'.format(calibration['covariances']), context) else: covariances = None # to avoid importing numpy model_dict = { 'variables_ordering': variables_ordering, 'parameters_ordering': parameters_ordering, 'shocks_ordering': shocks_ordering, 'variables_groups': variables_groups, 'equations_groups': equations_groups, 'equations': equations, 'parameters_values': parameters_values, 'init_values': init_values, 'covariances': covariances } if 'model_type' in raw_dict: model_dict['model_type'] = raw_dict['model_type'] model_dict['original_data'] = raw_dict model = Model(**model_dict) model.check_consistency(auto_remove_variables=False) return model
def parse_dynare_text(txt, add_model=True, full_output=False, debug=False): ''' Imports the content of a modfile into the current interpreter scope ''' # here we call "instruction group", a string finishing by a semicolon # an "instruction group" can have several lines # a line can be # - a comment //... # - an old-style tag //$... # - a new-style tag [key1='value1',..] # - macro-instruction @#... # A Modfile contains several blocks (in this order) : # - an initblock defining variables, exovariables, parameters, initialization # inside the initblock the order of declaration doesn't matter # - a model block with two special lines (model; end;) # - optional blocks (like endval, shocks) # seperated by free matlab instructions in any order; # - all other instructions are ignored otxt = txt otxt = otxt.replace("\r\n", "\n") otxt = otxt.replace("^", "**") # first, we remove end-of-line comments : they are definitely lost regex = re.compile("(.+)//[^#](.*)") def remove_end_comment(line): res = regex.search(line) if res: l = res.groups(1)[0] return (l) else: return line txt = str.join("\n", map(remove_end_comment, otxt.split("\n"))) name_regex = re.compile("//\s*fname\s*=\s*'(.*)'") m = name_regex.search(txt) if m: fname = m.group(1) else: fname = None instruction_groups = [Instruction_group(s) for s in txt.split(";")] instructions = [ig.instruction for ig in instruction_groups] if debug: print('Elementary instructions') for i in instruction_groups: print(i) try: imodel = [ re.compile('model(\(.*\)|)').match(e) is not None for e in instructions ] imodel = imodel.index(True) #imodel = instructions.index("model") #this doesn't work for "MODEL" iend = instructions.index("end") model_block = instruction_groups[imodel:(iend + 1)] init_block = instruction_groups[0:imodel] except: raise Exception('Model block could not be found.') next_instructions = instructions[(iend + 1):] next_instruction_groups = instruction_groups[(iend + 1):] if 'initval' in next_instructions: iinitval = next_instructions.index('initval') iend = next_instructions.index('end', iinitval) matlab_block_1 = next_instruction_groups[0:iinitval] initval_block = next_instruction_groups[iinitval:(iend + 1)] next_instruction_groups = next_instruction_groups[(iend + 1):] next_instructions = next_instructions[(iend + 1):] else: initval_block = None matlab_block_1 = None if 'endval' in next_instructions: iendval = next_instructions.index('endval') iend = next_instructions.index('end', iendval) matlab_block_2 = next_instruction_groups[0:iendval] endval_block = next_instruction_groups[iendval:(iend + 1)] next_instruction_groups = next_instruction_groups[(iend + 1):] next_instructions = next_instructions[(iend + 1):] else: endval_block = None matlab_block_2 = None # TODO : currently shocks block needs to follow initval, this restriction should be removed if 'shocks' in next_instructions: ishocks = next_instructions.index('shocks') iend = next_instructions.index('end', ishocks) matlab_block_3 = next_instruction_groups[0:ishocks] shocks_block = next_instruction_groups[ishocks:(iend + 1)] next_instruction_groups = next_instruction_groups[(iend + 1):] next_instructions = next_instructions[(iend + 1):] else: shocks_block = None matlab_block_3 = None try: init_regex = re.compile("(parameters |var |varexo |)(.*)") var_names = [] varexo_names = [] parameters_names = [] declarations = {} for ig in init_block: if ig.instruction != '': m = init_regex.match(ig.instruction) if not m: raise Exception("Unexpected instruction in init block : " + str(ig.instruction)) if m.group(1) == '': [lhs, rhs] = m.group(2).split("=") lhs = lhs.strip() rhs = rhs.strip() declarations[lhs] = rhs else: arg = m.group(2).replace(",", " ") names = [vn.strip() for vn in arg.split()] if m.group(1).strip() == 'var': dest = var_names elif m.group(1).strip() == 'varexo': dest = varexo_names elif m.group(1).strip() == 'parameters': dest = parameters_names for n in names: if not n in dest: dest.append(n) else: raise Exception( "symbol %s has already been defined".format(n)) except Exception as e: raise Exception('Init block could not be read : ' + str(e)) # the following instruction set the variables "variables","shocks","parameters" variables = [] for vn in var_names: v = Variable(vn) variables.append(v) shocks = [] for vn in varexo_names: s = Shock(vn) shocks.append(s) parameters = [] for vn in parameters_names: p = Parameter(vn) parameters.append(p) parse_dict = dict() for v in variables + shocks + parameters: parse_dict[v.name] = v special_symbols = [ sympy.exp, sympy.log, sympy.sin, sympy.cos, sympy.atan, sympy.tan ] for s in special_symbols: parse_dict[str(s)] = s parse_dict['sqrt'] = sympy.sqrt # Read parameters values parameters_values = {} for p in declarations: try: rhs = eval(declarations[p], parse_dict) except Exception as e: Exception("Impossible to evaluate parameter value : " + str(e)) try: lhs = eval(p, parse_dict) except Exception as e: # here we could declare p raise e parameters_values[lhs] = rhs # Now we read the model block model_tags = model_block[0].tags equations = [] for ig in model_block[1:-1]: if ig.instruction != '': teq = ig.instruction.replace('^', "**") if '=' in teq: teqlhs, teqrhs = teq.split("=") else: teqlhs = teq teqrhs = '0' eqlhs = eval(teqlhs, parse_dict) eqrhs = eval(teqrhs, parse_dict) eq = Equation(eqlhs, eqrhs) eq.tags.update(ig.tags) # if eq.tags.has_key('name'): # eq.tags[] = ig.tags['name'] equations.append(eq) # Now we read the initval block init_values = {} if initval_block != None: for ig in initval_block[1:-1]: if len(ig.instruction.strip()) > 0: try: [lhs, rhs] = ig.instruction.split("=") except Exception as e: print(ig.instruction) raise e init_values[eval(lhs, parse_dict)] = eval(rhs, parse_dict) # Now we read the endval block # I don't really care about the endval block ! end_values = {} if endval_block != None: for ig in endval_block[1:-1]: [lhs, rhs] = ig.instruction.split("=") end_values[eval(lhs)] = eval(rhs) # Now we read the shocks block covariances = None if shocks_block != None: covariances = sympy.zeros(len(shocks)) regex1 = re.compile("var (.*?),(.*?)=(.*)|var (.*?)=(.*)") for ig in shocks_block[1:-1]: m = regex1.match(ig.instruction) if not m: raise Exception("unrecognized instruction in block shocks : " + str(ig.instruction)) if m.group(1) != None: varname1 = m.group(1).strip() varname2 = m.group(2).strip() value = m.group(3).strip().replace("^", "**") elif m.group(4) != None: varname1 = m.group(4).strip() varname2 = varname1 value = m.group(5).strip().replace("^", "**") i = varexo_names.index(varname1) j = varexo_names.index(varname2) covariances[i, j] = eval(value, parse_dict) covariances[j, i] = eval(value, parse_dict) calibration = {} calibration.update(parameters_values) calibration.update(init_values) symbols = { 'variables': variables, 'shocks': shocks, 'parameters': parameters } from dolo.symbolic.model import SModel model = SModel({'dynare_block': equations}, symbols, calibration, covariances) return model
def parse_yaml_text(txt,verbose=False): ''' Imports the content of a modfile into the current interpreter scope ''' txt = txt.replace('..','-') txt = txt.replace('--','-') txt = txt.replace('^','**') raw_dict = yaml.load(txt) if verbose == True: print('YAML file successfully parsed') declarations = raw_dict['declarations'] # check if 'controls' in declarations: variables_groups = OrderedDict() known_types = ['states','controls','expectations','auxiliary','auxiliary_2'] for vtype in known_types: if vtype in declarations: variables_groups[vtype] = [Variable(vn,0) for vn in declarations[vtype]] variables_ordering = sum(variables_groups.values(),[]) else: vnames = declarations['variables'] variables_ordering = [Variable(vn,0) for vn in vnames] variables_groups = None parameters_ordering = [Parameter(vn) for vn in declarations['parameters']] shocks_ordering = [Shock(vn,0) for vn in declarations['shocks']] context = [(s.name,s) for s in variables_ordering + parameters_ordering + shocks_ordering] context = dict(context) # add some common functions for f in [sympy.log, sympy.exp, sympy.sin, sympy.cos, sympy.tan, sympy.asin, sympy.acos, sympy.atan, sympy.sinh, sympy.cosh, sympy.tanh, sympy.pi]: context[str(f)] = f context['sqrt'] = sympy.sqrt import re # we recognize two kinds of equations: # lhs = rhs # lhs | comp where comp is a complementarity condition equations = [] equations_groups = OrderedDict() raw_equations = raw_dict['equations'] if isinstance(raw_equations,dict): # tests whether there are groups of equations for groupname in raw_equations.keys(): equations_groups[groupname] = [] for raw_eq in raw_equations[groupname]: # Modfile is supposed to represent a global model. TODO: change it teqg = raw_eq.split('|') teq = teqg[0] if '=' in teq: lhs,rhs = str.split(teq,'=') else: lhs = teq rhs = '0' try: lhs = eval(lhs,context) rhs = eval(rhs,context) except Exception as e: print('Error parsing equation : ' + teq) print str(e) raise e eq = Equation(lhs,rhs) eq.tag(eq_type=groupname) if len(teqg)>1: comp = teqg[1] eq.tag(complementarity=comp) equations.append(eq) #equations_groups[groupname].append( eq ) else: for teq in raw_equations: if '=' in teq: lhs,rhs = str.split(teq,'=') else: lhs = teq rhs = '0' try: lhs = eval(lhs,context) rhs = eval(rhs,context) except Exception as e: print('Error parsing equations : ' + teq) print str(e) eq = Equation(lhs,rhs) equations.append(eq) equations_groups = None parameters_values = {} init_values = {} covariances = None if 'calibration' in raw_dict: calibration = raw_dict['calibration'] if 'parameters' in calibration: parameters_values = [ (Parameter(k), eval(str(v),context)) for k,v in calibration['parameters'].iteritems() ] parameters_values = dict(parameters_values) #steady_state = raw_dict['steady_state'] if 'steady_state' in calibration: init_values = [ (Variable(vn,0), eval(str(value),context)) for vn,value in calibration['steady_state'].iteritems() ] init_values = dict(init_values) if 'covariances' in calibration: context['sympy'] = sympy covariances = eval('sympy.Matrix({0})'.format( calibration['covariances'] ), context) else: covariances = None # to avoid importing numpy model_dict = { 'variables_ordering': variables_ordering, 'parameters_ordering': parameters_ordering, 'shocks_ordering': shocks_ordering, 'variables_groups': variables_groups, 'equations_groups': equations_groups, 'equations': equations, 'parameters_values': parameters_values, 'init_values': init_values, 'covariances': covariances } if 'model_type' in raw_dict: model_dict['model_type'] = raw_dict['model_type'] model_dict['original_data'] = raw_dict model = Model(**model_dict) model.check_consistency(auto_remove_variables=False) return model
def solve_portfolio_model(model, pf_names, order=1): pf_model = model from dolo import Variable, Parameter, Equation import re n_states = len(pf_model['variables_groups']['states']) states = pf_model['variables_groups']['states'] steady_states = [Parameter(v.name+'_bar') for v in pf_model['variables_groups']['states']] n_pfs = len(pf_names) pf_vars = [Variable(v) for v in pf_names] res_vars = [Variable('res_'+str(i)) for i in range(n_pfs)] pf_parms = [Parameter('K_'+str(i)) for i in range(n_pfs)] pf_dparms = [[Parameter('K_'+str(i)+'_'+str(j)) for j in range(n_states)] for i in range(n_pfs)] from sympy import Matrix # creation of the new model import copy print('Warning: initial model has been changed.') new_model = copy.copy(pf_model) new_model['variables_groups']['controls']+=res_vars new_model['parameters_ordering'].extend(steady_states) for p in pf_parms + Matrix(pf_dparms)[:]: new_model['parameters_ordering'].append(p) new_model.parameters_values[p] = 0 compregex = re.compile('(.*)<=(.*)<=(.*)') to_be_added = [] expressions = Matrix(pf_parms) + Matrix(pf_dparms)*( Matrix(states) - Matrix(steady_states)) for eq in new_model['equations_groups']['arbitrage']: if 'complementarity' in eq.tags: tg = eq.tags['complementarity'] [lhs,mhs,rhs] = compregex.match(tg).groups() mhs = new_model.eval_string(mhs) else: mhs = None if mhs in pf_vars: i = pf_vars.index(mhs) eq_n = eq.tags['eq_number'] neq = Equation(mhs, expressions[i]) neq.tag(**eq.tags) new_model['equations'][eq_n] = neq eq_res = Equation(eq.gap, res_vars[i]) eq_res.tag(eq_type='arbitrage') to_be_added.append(eq_res) new_model['equations'].extend(to_be_added) new_model.check() new_model.check_consistency(verbose=True) print(new_model.parameters) print(len(new_model['equations'])) print(len(new_model.equations)) print(len(new_model['equations_groups']['arbitrage'])) print('parameters_ordering') print(new_model['parameters_ordering']) print(new_model.parameters) # now, we need to solve for the optimal portfolio coefficients from dolo.numeric.perturbations_to_states import approximate_controls dr = approximate_controls(new_model) print('ok') import numpy n_controls = len(model['variables_groups']['controls']) def constant_residuals(x): for i in range(n_pfs): p = pf_parms[i] v = pf_vars[i] new_model.parameters_values[p] = x[i] new_model.init_values[v] = x[i] [X_bar, X_s, X_ss] = approximate_controls(new_model, order=2, return_dr=False) return X_bar[n_controls-n_pfs:n_controls] x0 = numpy.zeros(n_pfs) from dolo.numeric.solver import solver portfolios_0 = solver(constant_residuals, x0) print('Zero order portfolios : ') print(portfolios_0) print('Zero order: Final error:') print(constant_residuals(portfolios_0)) def dynamic_residuals(X, return_dr=False): x = X[:,0] dx = X[:,1:] for i in range(n_pfs): p = pf_parms[i] v = pf_vars[i] model.parameters_values[p] = x[i] model.init_values[v] = x[i] for j in range(n_states): model.parameters_values[pf_dparms[i][j]] = dx[i,j] if return_dr: dr = approximate_controls(new_model, order=2) return dr else: [X_bar, X_s, X_ss, X_sss] = approximate_controls(new_model, order=3, return_dr=False) crit = numpy.column_stack([ X_bar[n_controls-n_pfs:n_controls], X_s[n_controls-n_pfs:n_controls,:], ]) return crit y0 = numpy.column_stack([x0, numpy.zeros((n_pfs, n_states))]) print('Initial error:') print(dynamic_residuals(y0)) portfolios_1 = solver(dynamic_residuals, y0) print('First order portfolios : ') print(portfolios_1) print('Final error:') print(dynamic_residuals(portfolios_1)) dr = dynamic_residuals(portfolios_1, return_dr=True) return dr
def parse_yaml_text(txt,verbose=False, compiler=None): ''' Imports the content of a modfile into the current interpreter scope ''' txt = txt.replace('..','-') txt = txt.replace('--','-') txt = txt.replace('^','**') txt = txt.replace('equilibrium:','arbitrage:') txt = txt.replace('_|_','|') raw_dict = yaml.load(txt) if verbose == True: print('YAML file successfully parsed') declarations = raw_dict['declarations'] # check variables_groups = OrderedDict() for vtype in declarations.keys(): if vtype not in ('shocks','parameters'): variables_groups[vtype] = [Variable(vn) for vn in declarations[vtype]] variables_ordering = sum(variables_groups.values(),[]) # else: # vnames = declarations['variables'] # variables_ordering = [Variable(vn) for vn in vnames] # variables_groups = None parameters_ordering = [Parameter(vn) for vn in declarations['parameters']] shocks_ordering = [Shock(vn) for vn in declarations['shocks']] context = [(s.name,s) for s in variables_ordering + parameters_ordering + shocks_ordering] context = dict(context) from dolo.symbolic.symbolic import timeshift as TS # add some common functions for f in [sympy.log, sympy.exp, sympy.sin, sympy.cos, sympy.tan, sympy.asin, sympy.acos, sympy.atan, sympy.sinh, sympy.cosh, sympy.tanh, sympy.pi, sympy.sign]: context[str(f)] = f context['sqrt'] = sympy.sqrt context['TS'] = TS if 'horrible_hack' in raw_dict: tt = raw_dict['horrible_hack'] exec(tt, context) import re # we recognize two kinds of equations: # lhs = rhs # lhs | comp where comp is a complementarity condition equations = [] equations_groups = OrderedDict() raw_equations = raw_dict['equations'] if not isinstance(raw_equations,dict): raw_dict['model_type'] = 'dynare' raw_equations = {'dynare_block': raw_equations} if True: # tests whether there are groups of equations for groupname in raw_equations.keys(): equations_groups[groupname] = [] for raw_eq in raw_equations[groupname]: # Modfile is supposed to represent a global model. TODO: change it teqg = raw_eq.split('|') teq = teqg[0] if '=' in teq: lhs,rhs = str.split(teq,'=') else: lhs = teq rhs = '0' try: lhs = eval(lhs,context) rhs = eval(rhs,context) except Exception as e: print('Error parsing equation : ' + teq) print( str(e) ) raise e eq = Equation(lhs,rhs) eq.tag(eq_type=groupname) if len(teqg)>1: comp = teqg[1] eq.tag(complementarity=comp) equations.append(eq) equations_groups[groupname].append( eq ) else: for teq in raw_equations: if '=' in teq: lhs,rhs = str.split(teq,'=') else: lhs = teq rhs = '0' try: lhs = eval(lhs,context) rhs = eval(rhs,context) except Exception as e: print('Error parsing equations : ' + teq) print(str(e)) eq = Equation(lhs,rhs) equations.append(eq) equations_groups = None parameters_values = {} init_values = {} covariances = None if 'calibration' in raw_dict: calibration = raw_dict['calibration'] if 'parameters' in calibration: parameters_values = [ (Parameter(k), eval(str(v),context)) for k,v in iteritems(calibration['parameters']) ] parameters_values = dict(parameters_values) #steady_state = raw_dict['steady_state'] if 'steady_state' in calibration: init_values = [ (Variable(vn), eval(str(value),context)) for vn,value in iteritems(calibration['steady_state']) ] init_values = dict(init_values) if 'covariances' in calibration: context['sympy'] = sympy covariances = eval('sympy.Matrix({0})'.format( calibration['covariances'] ), context) else: covariances = None # to avoid importing numpy symbols = variables_groups symbols['shocks'] = shocks_ordering symbols['parameters'] = parameters_ordering calibration_s = {} calibration_s.update(parameters_values) calibration_s.update(init_values) from dolo.symbolic.model import SModel model = SModel( equations_groups, symbols, calibration_s, covariances ) model.__data__ = raw_dict return model
print('Impossible to evaluate : \n' + str(t)) raise e residuals[gname] = [float(eq.gap.subs(dd)) for eq in geqs] return residuals else: stateq = [eq.gap.subs(dd) for eq in model.equations] residuals = [float(eq) for eq in stateq] return residuals def print_residuals(model): residuals = compute_residuals(model) print('\n{:*^90}\n'.format('Residuals')) for category in residuals.keys(): res = residuals[category] print category for i, eq in enumerate(model['equations_groups'][category]): print('\t{:03.4f}\t:\t{}'.format(res[i], eq)) if __name__ == '__main__': from dolo.symbolic.symbolic import Variable, Equation v = Variable('v', 0) eq = Equation(v**2, v(1) - v(-1)) d = Model(equations=[eq])
def parse_yaml_text(txt, verbose=False, compiler=None): ''' Imports the content of a modfile into the current interpreter scope ''' txt = txt.replace('..', '-') txt = txt.replace('--', '-') txt = txt.replace('^', '**') txt = txt.replace('equilibrium:', 'arbitrage:') txt = txt.replace('_|_', '|') raw_dict = yaml.load(txt) if verbose == True: print('YAML file successfully parsed') declarations = raw_dict['declarations'] # check variables_groups = OrderedDict() for vtype in declarations.keys(): if vtype not in ('shocks', 'parameters'): variables_groups[vtype] = [ Variable(vn) for vn in declarations[vtype] ] variables_ordering = sum(variables_groups.values(), []) # else: # vnames = declarations['variables'] # variables_ordering = [Variable(vn) for vn in vnames] # variables_groups = None parameters_ordering = [Parameter(vn) for vn in declarations['parameters']] shocks_ordering = [Shock(vn) for vn in declarations['shocks']] context = [ (s.name, s) for s in variables_ordering + parameters_ordering + shocks_ordering ] context = dict(context) from dolo.symbolic.symbolic import timeshift as TS # add some common functions for f in [ sympy.log, sympy.exp, sympy.sin, sympy.cos, sympy.tan, sympy.asin, sympy.acos, sympy.atan, sympy.sinh, sympy.cosh, sympy.tanh, sympy.pi, sympy.sign ]: context[str(f)] = f context['sqrt'] = sympy.sqrt context['TS'] = TS if 'horrible_hack' in raw_dict: tt = raw_dict['horrible_hack'] exec(tt, context) import re # we recognize two kinds of equations: # lhs = rhs # lhs | comp where comp is a complementarity condition equations = [] equations_groups = OrderedDict() raw_equations = raw_dict['equations'] if not isinstance(raw_equations, dict): raw_dict['model_type'] = 'dynare' raw_equations = {'dynare_block': raw_equations} if True: # tests whether there are groups of equations for groupname in raw_equations.keys(): equations_groups[groupname] = [] for raw_eq in raw_equations[ groupname]: # Modfile is supposed to represent a global model. TODO: change it teqg = raw_eq.split('|') teq = teqg[0] if '=' in teq: lhs, rhs = str.split(teq, '=') else: lhs = teq rhs = '0' try: lhs = eval(lhs, context) rhs = eval(rhs, context) except Exception as e: print('Error parsing equation : ' + teq) print(str(e)) raise e eq = Equation(lhs, rhs) eq.tag(eq_type=groupname) if len(teqg) > 1: comp = teqg[1] eq.tag(complementarity=comp) equations.append(eq) equations_groups[groupname].append(eq) else: for teq in raw_equations: if '=' in teq: lhs, rhs = str.split(teq, '=') else: lhs = teq rhs = '0' try: lhs = eval(lhs, context) rhs = eval(rhs, context) except Exception as e: print('Error parsing equations : ' + teq) print(str(e)) eq = Equation(lhs, rhs) equations.append(eq) equations_groups = None parameters_values = {} init_values = {} covariances = None if 'calibration' in raw_dict: calibration = raw_dict['calibration'] if 'parameters' in calibration: parameters_values = [ (Parameter(k), eval(str(v), context)) for k, v in iteritems(calibration['parameters']) ] parameters_values = dict(parameters_values) #steady_state = raw_dict['steady_state'] if 'steady_state' in calibration: init_values = [ (Variable(vn), eval(str(value), context)) for vn, value in iteritems(calibration['steady_state']) ] init_values = dict(init_values) if 'covariances' in calibration: context['sympy'] = sympy covariances = eval( 'sympy.Matrix({0})'.format(calibration['covariances']), context) else: covariances = None # to avoid importing numpy symbols = variables_groups symbols['shocks'] = shocks_ordering symbols['parameters'] = parameters_ordering calibration_s = {} calibration_s.update(parameters_values) calibration_s.update(init_values) from dolo.symbolic.model import SModel model = SModel(equations_groups, symbols, calibration_s, covariances) model.__data__ = raw_dict return model
def solve_portfolio_model(model, pf_names, order=2, guess=None): from dolo.compiler.compiler_python import GModel if isinstance(model, GModel): model = model.model pf_model = model from dolo import Variable, Parameter, Equation import re n_states = len(pf_model.symbols_s['states']) states = pf_model.symbols_s['states'] steady_states = [ Parameter(v.name + '_bar') for v in pf_model.symbols_s['states'] ] n_pfs = len(pf_names) pf_vars = [Variable(v) for v in pf_names] res_vars = [Variable('res_' + str(i)) for i in range(n_pfs)] pf_parms = [Parameter('K_' + str(i)) for i in range(n_pfs)] pf_dparms = [[ Parameter('K_' + str(i) + '_' + str(j)) for j in range(n_states) ] for i in range(n_pfs)] from sympy import Matrix # creation of the new model import copy new_model = copy.copy(pf_model) new_model.symbols_s['controls'] += res_vars for v in res_vars + pf_vars: new_model.calibration_s[v] = 0 new_model.symbols_s['parameters'].extend(steady_states) for p in pf_parms + Matrix(pf_dparms)[:]: new_model.symbols_s['parameters'].append(p) new_model.calibration_s[p] = 0 compregex = re.compile('(.*)<=(.*)<=(.*)') to_be_added_1 = [] to_be_added_2 = [] expressions = Matrix(pf_parms) + Matrix(pf_dparms) * ( Matrix(states) - Matrix(steady_states)) for n, eq in enumerate(new_model.equations_groups['arbitrage']): if 'complementarity' in eq.tags: tg = eq.tags['complementarity'] [lhs, mhs, rhs] = compregex.match(tg).groups() mhs = new_model.eval_string(mhs) else: mhs = None if mhs in pf_vars: i = pf_vars.index(mhs) neq = Equation(mhs, expressions[i]) neq.tag(**eq.tags) eq_res = Equation(eq.gap, res_vars[i]) eq_res.tag(eq_type='arbitrage') to_be_added_2.append(eq_res) new_model.equations_groups['arbitrage'][n] = neq to_be_added_1.append(neq) # new_model.equations_groups['arbitrage'].extend(to_be_added_1) new_model.equations_groups['arbitrage'].extend(to_be_added_2) new_model.update() print("number of equations {}".format(len(new_model.equations))) print("number of arbitrage equations {}".format( len(new_model.equations_groups['arbitrage']))) print('parameters_ordering') print("number of parameters {}".format(new_model.symbols['parameters'])) print("number of parameters {}".format(new_model.parameters)) # now, we need to solve for the optimal portfolio coefficients from dolo.numeric.perturbations_to_states import approximate_controls dr = approximate_controls(new_model) print('ok') import numpy n_controls = len(model.symbols_s['controls']) def constant_residuals(x, return_dr=False): d = {} for i in range(n_pfs): p = pf_parms[i] v = pf_vars[i] d[p] = x[i] d[v] = x[i] new_model.set_calibration(d) # new_model.parameters_values[p] = x[i] # new_model.init_values[v] = x[i] if return_dr: dr = approximate_controls(new_model, order=1, return_dr=True) return dr X_bar, X_s, X_ss = approximate_controls(new_model, order=2, return_dr=False) return X_bar[n_controls - n_pfs:n_controls] if guess is not None: x0 = numpy.array(guess) else: x0 = numpy.zeros(n_pfs) from dolo.numeric.solver import solver portfolios_0 = solver(constant_residuals, x0) print('Zero order portfolios: {}'.format(portfolios_0)) print('Zero order portfolios: Final error: {}'.format( constant_residuals(portfolios_0))) if order == 1: dr = constant_residuals(portfolios_0, return_dr=True) return dr def dynamic_residuals(X, return_dr=False): x = X[:, 0] dx = X[:, 1:] d = {} for i in range(n_pfs): p = pf_parms[i] v = pf_vars[i] d[p] = x[i] d[v] = x[i] for j in range(n_states): d[pf_dparms[i][j]] = dx[i, j] new_model.set_calibration(d) if return_dr: dr = approximate_controls(new_model, order=2) return dr else: [X_bar, X_s, X_ss, X_sss] = approximate_controls(new_model, order=3, return_dr=False) crit = numpy.column_stack([ X_bar[n_controls - n_pfs:n_controls], X_s[n_controls - n_pfs:n_controls, :], ]) return crit y0 = numpy.column_stack([x0, numpy.zeros((n_pfs, n_states))]) print('Initial error:') print(dynamic_residuals(y0)) portfolios_1 = solver(dynamic_residuals, y0) print('First order portfolios : ') print(portfolios_1) print('Final error:') print(dynamic_residuals(portfolios_1)) dr = dynamic_residuals(portfolios_1, return_dr=True) return dr
def solve_portfolio_model(model, pf_names, order=1): pf_model = model from dolo import Variable, Parameter, Equation import re n_states = len(pf_model['variables_groups']['states']) states = pf_model['variables_groups']['states'] steady_states = [ Parameter(v.name + '_bar') for v in pf_model['variables_groups']['states'] ] n_pfs = len(pf_names) pf_vars = [Variable(v, 0) for v in pf_names] res_vars = [Variable('res_' + str(i), 0) for i in range(n_pfs)] pf_parms = [Parameter('K_' + str(i)) for i in range(n_pfs)] pf_dparms = [[ Parameter('K_' + str(i) + '_' + str(j)) for j in range(n_states) ] for i in range(n_pfs)] from sympy import Matrix # creation of the new model import copy print('Warning: initial model has been changed.') new_model = copy.copy(pf_model) new_model['variables_groups']['controls'] += res_vars new_model.check() for p in pf_parms + Matrix(pf_dparms)[:]: new_model['parameters_ordering'].append(p) new_model.parameters_values[p] = 0 compregex = re.compile('(.*)<=(.*)<=(.*)') to_be_added = [] expressions = Matrix(pf_parms) + Matrix(pf_dparms) * ( Matrix(states) - Matrix(steady_states)) for eq in new_model['equations_groups']['arbitrage']: if 'complementarity' in eq.tags: tg = eq.tags['complementarity'] [lhs, mhs, rhs] = compregex.match(tg).groups() mhs = new_model.eval_string(mhs) else: mhs = None if mhs in pf_vars: i = pf_vars.index(mhs) eq_n = eq.tags['eq_number'] neq = Equation(mhs, expressions[i]) neq.tag(**eq.tags) new_model['equations'][eq_n] = neq eq_res = Equation(eq.gap, res_vars[i]) eq_res.tag(eq_type='arbitrage') to_be_added.append(eq_res) new_model['equations'].extend(to_be_added) new_model.check() new_model.check_consistency() # now, we need to solve for the optimal portfolio coefficients from dolo.numeric.perturbations_to_states import approximate_controls import numpy n_controls = len(model['variables_groups']['controls']) def constant_residuals(x): for i in range(n_pfs): p = pf_parms[i] v = pf_vars[i] model.parameters_values[p] = x[i] model.init_values[v] = x[i] [X_bar, X_s, X_ss] = approximate_controls(new_model, order=2, return_dr=False) return X_bar[n_controls - n_pfs:n_controls] x0 = numpy.zeros(n_pfs) from dolo.numeric.solver import solver portfolios_0 = solver(constant_residuals, x0) print('Zero order portfolios : ') print(portfolios_0) print('Zero order: Final error:') print(constant_residuals(portfolios_0)) def dynamic_residuals(X, return_dr=False): x = X[:, 0] dx = X[:, 1:] for i in range(n_pfs): p = pf_parms[i] v = pf_vars[i] model.parameters_values[p] = x[i] model.init_values[v] = x[i] for j in range(n_states): model.parameters_values[pf_dparms[i][j]] = dx[i, j] if return_dr: dr = approximate_controls(new_model, order=2, return_dr=True) return dr else: [X_bar, X_s, X_ss, X_sss] = approximate_controls(new_model, order=3, return_dr=False) crit = numpy.column_stack([ X_bar[n_controls - n_pfs:n_controls], X_s[n_controls - n_pfs:n_controls, :], ]) return crit y0 = numpy.column_stack([x0, numpy.zeros((n_pfs, n_states))]) print('Initial error:') print(dynamic_residuals(y0)) portfolios_1 = solver(dynamic_residuals, y0) print('First order portfolios : ') print(portfolios_1) print('Final error:') print(dynamic_residuals(portfolios_1)) dr = dynamic_residuals(portfolios_1, return_dr=True) return dr
def read_model(self): if self.__transformed_model__: return self.__transformed_model__ dmodel = SModel(**self.model) # copy the model dmodel.check_consistency(auto_remove_variables=False) def_eqs = [eq for eq in dmodel.equations if eq.tags['eq_type'] in ('def', 'auxiliary')] from dolo.symbolic.symbolic import map_function_to_expression from dolo.symbolic.symbolic import Variable def timeshift(v,n): if isinstance(v,Variable): return v(n) else: return v import sympy #### build substitution dict def_dict = {} for eq in def_eqs: v = eq.lhs rhs = sympy.sympify( eq.rhs ) def_dict[v] = rhs def_dict[v(1)] = map_function_to_expression( lambda x: timeshift(x,1), rhs) new_equations = [] tbr = [] for i,eq in enumerate(dmodel.equations) : if not ('def' == eq.tags['eq_type']): lhs = sympy.sympify( eq.lhs ).subs(def_dict) rhs = sympy.sympify( eq.rhs ).subs(def_dict) neq = Equation(lhs,rhs).tag(**eq.tags) new_equations.append( neq ) dmodel['equations'] = new_equations dmodel.check_consistency() f_eqs = [eq for eq in dmodel.equations if eq.tags['eq_type'] in ('f','arbitrage')] g_eqs = [eq for eq in dmodel.equations if eq.tags['eq_type'] in ('g','transition')] h_eqs = [eq for eq in dmodel.equations if eq.tags['eq_type'] in ('h','expectation')] states_vars = [eq.lhs for eq in g_eqs] exp_vars = [eq.lhs for eq in h_eqs] controls = set(dmodel.variables) - set(states_vars + exp_vars) controls = list(controls) states_vars = [v for v in dmodel.variables if v in states_vars] exp_vars = [v for v in dmodel.variables if v in exp_vars] controls = [v for v in dmodel.variables if v in controls] # now we remove the left side of equations f_eqs = [eq.gap for eq in f_eqs] g_eqs = [eq.rhs for eq in g_eqs] h_eqs = [eq.rhs for eq in h_eqs] g_eqs = [map_function_to_expression(lambda x: timeshift(x,1),eq) for eq in g_eqs] #h_eqs = [map_function_to_expression(lambda x: timeshift(x,-1),eq) for eq in h_eqs] #no # sub_list[v] = v.name # read complementarity conditions compcond = {} of_eqs = [eq for eq in dmodel.equations if eq.tags['eq_type'] in ('f','arbitrage')] locals = {} import sympy locals['inf'] = sympy.Symbol('inf') locals['log'] = sympy.log # this should be more generic locals['exp'] = sympy.exp for v in dmodel.variables + dmodel.parameters: locals[v.name] = v import re compregex = re.compile('(.*)<=(.*)<=(.*)') for eq in of_eqs: tg = eq.tags['complementarity'] [lhs,mhs,rhs] = compregex.match(tg).groups() [lhs,mhs,rhs] = [dmodel.eval_string(x) for x in [lhs,mhs,rhs] ] compcond[mhs] = (lhs,rhs) complementarities = [compcond[v] for v in controls] inf_bounds = [c[0] for c in complementarities] sup_bounds = [c[1] for c in complementarities] data = { 'f_eqs': f_eqs, 'g_eqs': g_eqs, 'h_eqs': h_eqs, 'controls': controls, 'states_vars': states_vars, 'exp_vars': exp_vars, 'inf_bounds': inf_bounds, 'sup_bounds': sup_bounds } self.__transformed_model__ = data # cache computation return data
def solve_portfolio_model(model, pf_names, order=2, guess=None): from dolo.compiler.compiler_python import GModel if isinstance(model, GModel): model = model.model pf_model = model from dolo import Variable, Parameter, Equation import re n_states = len(pf_model.symbols_s['states']) states = pf_model.symbols_s['states'] steady_states = [Parameter(v.name+'_bar') for v in pf_model.symbols_s['states']] n_pfs = len(pf_names) pf_vars = [Variable(v) for v in pf_names] res_vars = [Variable('res_'+str(i)) for i in range(n_pfs)] pf_parms = [Parameter('K_'+str(i)) for i in range(n_pfs)] pf_dparms = [[Parameter('K_'+str(i)+'_'+str(j)) for j in range(n_states)] for i in range(n_pfs)] from sympy import Matrix # creation of the new model import copy new_model = copy.copy(pf_model) new_model.symbols_s['controls'] += res_vars for v in res_vars + pf_vars: new_model.calibration_s[v] = 0 new_model.symbols_s['parameters'].extend(steady_states) for p in pf_parms + Matrix(pf_dparms)[:]: new_model.symbols_s['parameters'].append(p) new_model.calibration_s[p] = 0 compregex = re.compile('(.*)<=(.*)<=(.*)') to_be_added_1 = [] to_be_added_2 = [] expressions = Matrix(pf_parms) + Matrix(pf_dparms)*( Matrix(states) - Matrix(steady_states)) for n,eq in enumerate(new_model.equations_groups['arbitrage']): if 'complementarity' in eq.tags: tg = eq.tags['complementarity'] [lhs,mhs,rhs] = compregex.match(tg).groups() mhs = new_model.eval_string(mhs) else: mhs = None if mhs in pf_vars: i = pf_vars.index(mhs) neq = Equation(mhs, expressions[i]) neq.tag(**eq.tags) eq_res = Equation(eq.gap, res_vars[i]) eq_res.tag(eq_type='arbitrage') to_be_added_2.append(eq_res) new_model.equations_groups['arbitrage'][n] = neq to_be_added_1.append(neq) # new_model.equations_groups['arbitrage'].extend(to_be_added_1) new_model.equations_groups['arbitrage'].extend(to_be_added_2) new_model.update() print("number of equations {}".format(len(new_model.equations))) print("number of arbitrage equations {}".format( len(new_model.equations_groups['arbitrage'])) ) print('parameters_ordering') print("number of parameters {}".format(new_model.symbols['parameters'])) print("number of parameters {}".format(new_model.parameters)) # now, we need to solve for the optimal portfolio coefficients from dolo.numeric.perturbations_to_states import approximate_controls dr = approximate_controls(new_model) print('ok') import numpy n_controls = len(model.symbols_s['controls']) def constant_residuals(x, return_dr=False): d = {} for i in range(n_pfs): p = pf_parms[i] v = pf_vars[i] d[p] = x[i] d[v] = x[i] new_model.set_calibration(d) # new_model.parameters_values[p] = x[i] # new_model.init_values[v] = x[i] if return_dr: dr = approximate_controls(new_model, order=1, return_dr=True) return dr X_bar, X_s, X_ss = approximate_controls(new_model, order=2, return_dr=False) return X_bar[n_controls-n_pfs:n_controls] if guess is not None: x0 = numpy.array(guess) else: x0 = numpy.zeros(n_pfs) from dolo.numeric.solver import solver portfolios_0 = solver(constant_residuals, x0) print('Zero order portfolios: {}'.format(portfolios_0)) print('Zero order portfolios: Final error: {}'.format( constant_residuals(portfolios_0) )) if order == 1: dr = constant_residuals(portfolios_0, return_dr=True) return dr def dynamic_residuals(X, return_dr=False): x = X[:,0] dx = X[:,1:] d = {} for i in range(n_pfs): p = pf_parms[i] v = pf_vars[i] d[p] = x[i] d[v] = x[i] for j in range(n_states): d[pf_dparms[i][j]] = dx[i,j] new_model.set_calibration(d) if return_dr: dr = approximate_controls(new_model, order=2) return dr else: [X_bar, X_s, X_ss, X_sss] = approximate_controls(new_model, order=3, return_dr=False) crit = numpy.column_stack([ X_bar[n_controls-n_pfs:n_controls], X_s[n_controls-n_pfs:n_controls,:], ]) return crit y0 = numpy.column_stack([x0, numpy.zeros((n_pfs, n_states))]) print('Initial error:') print(dynamic_residuals(y0)) portfolios_1 = solver(dynamic_residuals, y0) print('First order portfolios : ') print(portfolios_1) print('Final error:') print(dynamic_residuals(portfolios_1)) dr = dynamic_residuals(portfolios_1, return_dr=True) return dr