def solve_portfolio_model(model, pf_names, order=2, lambda_name='lam', 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 trash.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, lambda_name='lam') return dr X_bar, X_s, X_ss = approximate_controls(new_model, order=2, return_dr=False, lambda_name="lam") return X_bar[n_controls-n_pfs:n_controls] if guess is not None: x0 = numpy.array(guess) else: x0 = numpy.zeros(n_pfs) print('Zero order portfolios') print('Initial guess: {}'.format(x0)) print('Initial error: {}'.format( constant_residuals(x0) )) portfolios_0 = solver(constant_residuals, x0) print('Solution: {}'.format(portfolios_0)) print('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, lambda_name='lam') return dr else: [X_bar, X_s, X_ss, X_sss] = approximate_controls(new_model, order=3, return_dr=False, lambda_name='lam') 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:') err = (dynamic_residuals(y0)) print( abs(err).max() ) 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) # TODO: remove coefficients of criteria return dr
def solve_risky_ss(model, X_bar, X_s, verbose=False): import numpy from dolo.compiler.function_compiler import compile_function import time from dolo.compiler.compiler_functions import simple_global_representation parms = model.calibration['parameters'] sigma = model.calibration['covariances'] sgm = simple_global_representation(model) states = sgm['states'] controls = sgm['controls'] shocks = sgm['shocks'] parameters = sgm['parameters'] f_eqs = sgm['f_eqs'] g_eqs = sgm['g_eqs'] g_args = [s(-1) for s in states] + [c(-1) for c in controls] + shocks f_args = states + controls + [v(1) for v in states] + [v(1) for v in controls] p_args = parameters g_fun = compile_function(g_eqs, g_args, p_args, 2) f_fun = compile_function(f_eqs, f_args, p_args, 3) epsilons_0 = np.zeros((sigma.shape[0])) from numpy import dot from dolo.numeric.tensor import sdot, mdot def residuals(X, sigma, parms, g_fun, f_fun): import numpy dummy_x = X[0:1, 0] X_bar = X[1:, 0] S_bar = X[0, 1:] X_s = X[1:, 1:] [n_x, n_s] = X_s.shape n_e = sigma.shape[0] xx = np.concatenate([S_bar, X_bar, epsilons_0]) [g_0, g_1, g_2] = g_fun(xx, parms) [f_0, f_1, f_2, f_3] = f_fun(np.concatenate([S_bar, X_bar, S_bar, X_bar]), parms) res_g = g_0 - S_bar # g is a first order function g_s = g_1[:, :n_s] g_x = g_1[:, n_s:n_s + n_x] g_e = g_1[:, n_s + n_x:] g_se = g_2[:, :n_s, n_s + n_x:] g_xe = g_2[:, n_s:n_s + n_x, n_s + n_x:] # S(s,e) = g(s,x,e) S_s = g_s + dot(g_x, X_s) S_e = g_e S_se = g_se + mdot(g_xe, [X_s, numpy.eye(n_e)]) # V(s,e) = [ g(s,x,e) ; x( g(s,x,e) ) ] V_s = np.row_stack([S_s, dot(X_s, S_s)]) # *** V_e = np.row_stack([S_e, dot(X_s, S_e)]) V_se = np.row_stack([S_se, dot(X_s, S_se)]) # v(s) = [s, x(s)] v_s = np.row_stack([numpy.eye(n_s), X_s]) # W(s,e) = [xx(s,e); yy(s,e)] W_s = np.row_stack([v_s, V_s]) #return nn = n_s + n_x f_v = f_1[:, :nn] f_V = f_1[:, nn:] f_1V = f_2[:, :, nn:] f_VV = f_2[:, nn:, nn:] f_1VV = f_3[:, :, nn:, nn:] # E = lambda v: np.tensordot(v, sigma, axes=((2,3),(0,1)) ) # expectation operator F = f_0 + 0.5 * np.tensordot( mdot(f_VV, [V_e, V_e]), sigma, axes=((1, 2), (0, 1))) F_s = sdot(f_1, W_s) f_see = mdot(f_1VV, [W_s, V_e, V_e]) + 2 * mdot(f_VV, [V_se, V_e]) F_s += 0.5 * np.tensordot(f_see, sigma, axes=( (2, 3), (0, 1))) # second order correction resp = np.row_stack( [np.concatenate([dummy_x, res_g]), np.column_stack([F, F_s])]) return resp # S_bar = s_fun_init( numpy.atleast_2d(X_bar).T ,parms).flatten() # S_bar = S_bar.flatten() S_bar = model.calibration['states'] S_bar = np.array(S_bar) X0 = np.row_stack( [np.concatenate([np.zeros(1), S_bar]), np.column_stack([X_bar, X_s])]) fobj = lambda X: residuals(X, sigma, parms, g_fun, f_fun) if verbose: val = fobj(X0) print('val') print(val) # exit() t = time.time() sol = solver(fobj, X0, method='lmmcp', verbose=verbose, options={ 'preprocess': False, 'eps1': 1e-15, 'eps2': 1e-15 }) if verbose: print('initial guess') print(X0) print('solution') print sol print('initial residuals') print(fobj(X0)) print('residuals') print fobj(sol) s = time.time() if verbose: print('Elapsed : {0}'.format(s - t)) #sol = solver(fobj,X0, method='fsolve', verbose=True, options={'preprocessor':False}) norm = lambda x: numpy.linalg.norm(x, numpy.inf) if verbose: print("Initial error: {0}".format(norm(fobj(X0)))) print("Final error: {0}".format(norm(fobj(sol)))) print("Solution") print(sol) X_bar = sol[1:, 0] S_bar = sol[0, 1:] X_s = sol[1:, 1:] # compute transitions n_s = len(states) n_x = len(controls) [g, dg, junk] = g_fun(np.concatenate([S_bar, X_bar, epsilons_0]), parms) g_s = dg[:, :n_s] g_x = dg[:, n_s:n_s + n_x] P = g_s + dot(g_x, X_s) if verbose: eigenvalues = numpy.linalg.eigvals(P) print eigenvalues eigenvalues = [abs(e) for e in eigenvalues] eigenvalues.sort() print(eigenvalues) return [S_bar, X_bar, X_s, P]
def solve_risky_ss(model, X_bar, X_s, verbose=False): import numpy from dolo.compiler.function_compiler import compile_function import time from dolo.compiler.compiler_functions import simple_global_representation parms = model.calibration['parameters'] sigma = model.calibration['covariances'] sgm = simple_global_representation(model) states = sgm['states'] controls = sgm['controls'] shocks = sgm['shocks'] parameters = sgm['parameters'] f_eqs = sgm['f_eqs'] g_eqs = sgm['g_eqs'] g_args = [s(-1) for s in states] + [c(-1) for c in controls] + shocks f_args = states + controls + [v(1) for v in states] + [v(1) for v in controls] p_args = parameters g_fun = compile_function(g_eqs, g_args, p_args, 2) f_fun = compile_function(f_eqs, f_args, p_args, 3) epsilons_0 = np.zeros((sigma.shape[0])) from numpy import dot from dolo.numeric.tensor import sdot,mdot def residuals(X, sigma, parms, g_fun, f_fun): import numpy dummy_x = X[0:1,0] X_bar = X[1:,0] S_bar = X[0,1:] X_s = X[1:,1:] [n_x,n_s] = X_s.shape n_e = sigma.shape[0] xx = np.concatenate([S_bar, X_bar, epsilons_0]) [g_0, g_1, g_2] = g_fun(xx, parms) [f_0,f_1,f_2,f_3] = f_fun( np.concatenate([S_bar, X_bar, S_bar, X_bar]), parms) res_g = g_0 - S_bar # g is a first order function g_s = g_1[:,:n_s] g_x = g_1[:,n_s:n_s+n_x] g_e = g_1[:,n_s+n_x:] g_se = g_2[:,:n_s,n_s+n_x:] g_xe = g_2[:, n_s:n_s+n_x, n_s+n_x:] # S(s,e) = g(s,x,e) S_s = g_s + dot(g_x, X_s) S_e = g_e S_se = g_se + mdot(g_xe,[X_s, numpy.eye(n_e)]) # V(s,e) = [ g(s,x,e) ; x( g(s,x,e) ) ] V_s = np.row_stack([ S_s, dot( X_s, S_s ) ]) # *** V_e = np.row_stack([ S_e, dot( X_s, S_e ) ]) V_se = np.row_stack([ S_se, dot( X_s, S_se ) ]) # v(s) = [s, x(s)] v_s = np.row_stack([ numpy.eye(n_s), X_s ]) # W(s,e) = [xx(s,e); yy(s,e)] W_s = np.row_stack([ v_s, V_s ]) #return nn = n_s + n_x f_v = f_1[:,:nn] f_V = f_1[:,nn:] f_1V = f_2[:,:,nn:] f_VV = f_2[:,nn:,nn:] f_1VV = f_3[:,:,nn:,nn:] # E = lambda v: np.tensordot(v, sigma, axes=((2,3),(0,1)) ) # expectation operator F = f_0 + 0.5*np.tensordot( mdot(f_VV,[V_e,V_e]), sigma, axes=((1,2),(0,1)) ) F_s = sdot(f_1, W_s) f_see = mdot(f_1VV, [W_s, V_e, V_e]) + 2*mdot(f_VV, [V_se, V_e]) F_s += 0.5 * np.tensordot(f_see, sigma, axes=((2,3),(0,1)) ) # second order correction resp = np.row_stack([ np.concatenate([dummy_x,res_g]), np.column_stack([F,F_s]) ]) return resp # S_bar = s_fun_init( numpy.atleast_2d(X_bar).T ,parms).flatten() # S_bar = S_bar.flatten() S_bar = model.calibration['states'] S_bar = np.array(S_bar) X0 = np.row_stack([ np.concatenate([np.zeros(1),S_bar]), np.column_stack([X_bar,X_s]) ]) fobj = lambda X: residuals(X, sigma, parms, g_fun, f_fun) if verbose: val = fobj(X0) print('val') print(val) # exit() t = time.time() sol = solver(fobj,X0, method='lmmcp', verbose=verbose, options={'preprocess':False, 'eps1':1e-15, 'eps2': 1e-15}) if verbose: print('initial guess') print(X0) print('solution') print sol print('initial residuals') print(fobj(X0)) print('residuals') print fobj(sol) s = time.time() if verbose: print('Elapsed : {0}'.format(s-t)) #sol = solver(fobj,X0, method='fsolve', verbose=True, options={'preprocessor':False}) norm = lambda x: numpy.linalg.norm(x,numpy.inf) if verbose: print( "Initial error: {0}".format( norm( fobj(X0)) ) ) print( "Final error: {0}".format( norm( fobj(sol) ) ) ) print("Solution") print(sol) X_bar = sol[1:,0] S_bar = sol[0,1:] X_s = sol[1:,1:] # compute transitions n_s = len(states) n_x = len(controls) [g, dg, junk] = g_fun( np.concatenate( [S_bar, X_bar, epsilons_0] ), parms) g_s = dg[:,:n_s] g_x = dg[:,n_s:n_s+n_x] P = g_s + dot(g_x, X_s) if verbose: eigenvalues = numpy.linalg.eigvals(P) print eigenvalues eigenvalues = [abs(e) for e in eigenvalues] eigenvalues.sort() print(eigenvalues) return [S_bar, X_bar, X_s, P]