def implied_cov_expdecayshk_continuous_not_time_varying( var_expdecayshk, omega, T): ''' Calculates the covariance matrix for an exponentially decaying stochastic process, time aggregated in continuous time Doesn't allow time-varying parameters (easier to read the code!) ''' # Set up covariance matrix, initialized to zero cov_y = np.zeros((T, T)) #/* Income */ # pre-calculate covariance matrix of a stochasic process with shocks # that decay at rate omega cov_omega, components = cov_omega_theta(omega, omega) var_omega = cov_omega[2] cov_omega_1 = cov_omega[3] cov_omega_2 = cov_omega[4] for j in range(T): cov_y[j, j] = var_expdecayshk * var_omega for j in range(1, T): cov_y[j - 1, j] = var_expdecayshk * cov_omega_1 cov_y[j, j - 1] = cov_y[j - 1, j] for M in range(2, T): for j in range(M, T): cov_y[j - M, j] = var_expdecayshk * np.exp(-(M - 2) * omega) * cov_omega_2 cov_y[j, j - M] = cov_y[j - M, j] vech_indicesT = vech_indices(T) cov_y_vec = cov_y[vech_indicesT] return cov_y_vec
def parameter_estimation_by_subgroup(moments_BPP_dir, subgroup_stub, subgroup_names, T, init_params, optimize_index=None, bounds=None): subgroup_estimates = np.zeros((len(subgroup_names), 5)) subgroup_se = np.zeros((len(subgroup_names), 5)) #Just doing income for now - remove other moments income_moments = np.array([[False] * 2 * T] * 2 * T, dtype=bool) income_moments[T:, T:] = True vech_indices2T = vech_indices(2 * T) income_moments = income_moments[vech_indices2T] for i in range(len(subgroup_names)): this_empirical_moments_all = np.genfromtxt(Path( moments_BPP_dir, subgroup_stub + str(i + 1) + "c_vector.txt"), delimiter=',') this_Omega_all = np.genfromtxt(Path( moments_BPP_dir, subgroup_stub + str(i + 1) + "_omega.txt"), delimiter=',') this_empirical_moments_inc = this_empirical_moments_all[income_moments] this_Omega_inc = this_Omega_all[income_moments, :][:, income_moments] this_estimates, this_estimate_se = parameter_estimation( this_empirical_moments_inc, this_Omega_inc, T, init_params, optimize_index, bounds) subgroup_estimates[i, :] = this_estimates subgroup_se[i, :] = this_estimate_se return subgroup_estimates, subgroup_se
def implied_cov_MA1_annual(var_tran, theta, T): ''' Calculates the covariance matrix for MA(1) shocks that arrive in discrete annual periods (like BPP 2008) ''' if isinstance(var_tran, (np.floating, float)): var_tran = var_tran * np.ones(T + 1) elif len(var_tran) != T + 1: return "var_tran must be a float or array of length T+1" if isinstance(theta, (np.floating, float)): theta = theta * np.ones(T + 1) else: return "theta must be a float or array of length T+1" # Create covariance matrix cov_y = np.zeros((T, T)) #/* Income */ for j in range(T): cov_y[j, j] = var_tran[j + 1] + (1 - theta[j])**2 * var_tran[j] + theta[max( j - 1, 0)]**2 * var_tran[max(j - 1, 0)] for j in range(1, T): cov_y[j - 1, j] = -(1 - theta[j]) * var_tran[j] + theta[max( j - 1, 0)] * (1 - theta[max(j - 1, 0)]) * var_tran[max(j - 1, 0)] cov_y[j, j - 1] = cov_y[j - 1, j] for j in range(2, T): cov_y[j - 2, j] = -theta[max(j - 1, 0)] * var_tran[max(j - 1, 0)] cov_y[j, j - 2] = cov_y[j - 2, j] vech_indicesT = vech_indices(T) cov_y_vec = cov_y[vech_indicesT] return cov_y_vec
def implied_cov_permshk_annual(var_perm, T): ''' Calculates the covariance matrix for permanent shocks that arrive in discrete, annual periods (like BPP 2008) ''' if isinstance(var_perm, (np.floating, float)): var_perm = np.ones(T + 1) * var_perm # variance of permanent shock elif len(var_perm) != T + 1: return "Number of parameters must be equal to 1 or T+1" # Create covariance matrix cov_y = np.zeros((T, T)) #/* Income */ for j in range(T): cov_y[j, j] = var_perm[j + 1] vech_indicesT = vech_indices(T) cov_y_vec = cov_y[vech_indicesT] return cov_y_vec
def implied_cov_bonusshk_continuous(var_bonus, T): ''' Calculates the covariance matrix for a transitory shock with NO persistence ''' if isinstance(var_bonus, (np.floating, float)): var_bonus = var_bonus * np.ones(T + 1) elif len(var_bonus) != T + 1: return "var_bonus must be a float or array of length T+1" # Set up covariance matrix, initialized to zero cov_y = np.zeros((T, T)) for j in range(T): cov_y[j, j] = var_bonus[j - 1] + var_bonus[j] for j in range(1, T): cov_y[j - 1, j] = -var_bonus[j - 1] cov_y[j, j - 1] = cov_y[j - 1, j] vech_indicesT = vech_indices(T) cov_y_vec = cov_y[vech_indicesT] return cov_y_vec
def implied_inc_cov_monthly(impact_matrix): ''' Calculates the covariance matrix for discrete monthly process defined by the "impact_matrix" ''' T = impact_matrix.shape[0] K = impact_matrix.shape[1] cov_y = np.zeros((T, T)) for k in range(K): for i in range(T): for j in range(i + 1): cov_y[i, i - j] += impact_matrix[i, k] * impact_matrix[i - j, k] for i in range(T): for j in range(i + 1): cov_y[i - j, i] = cov_y[i, i - j] vech_indicesT = vech_indices(T) cov_y_vec = cov_y[vech_indicesT] return cov_y_vec
def implied_cov_permshk_continuous(var_perm, T): ''' Calculates the covariance matrix for permanent shocks in continuous time ''' if isinstance(var_perm, (np.floating, float)): var_perm = np.ones(T + 1) * var_perm # variance of permanent shock elif len(var_perm) != T + 1: return "Number of parameters must be equal to 1 or T+1" # Create covariance matrix cov_y = np.zeros((T, T)) #/* Income */ for j in range(T): cov_y[j, j] = 1.0 / 3.0 * var_perm[j] + 1.0 / 3.0 * var_perm[j + 1] for j in range(1, T): cov_y[j - 1, j] = 1.0 / 6.0 * var_perm[j - 1] cov_y[j, j - 1] = cov_y[j - 1, j] vech_indicesT = vech_indices(T) cov_y_vec = cov_y[vech_indicesT] return cov_y_vec
from tools import vech_indices moments_BPP_dir = Path("../../Data/BPP_moments/") ############################################################################### #First load the moments empirical_moments_all = np.genfromtxt(Path(moments_BPP_dir, "moments_all_c_vector.txt"), delimiter=',') Omega_all = np.genfromtxt(Path(moments_BPP_dir, "moments_all_omega.txt"), delimiter=',') T = 12 #Just doing income for now - remove other moments income_moments = np.array([[False] * 2 * T] * 2 * T, dtype=bool) income_moments[T:, T:] = True vech_indices2T = vech_indices(2 * T) income_moments = income_moments[vech_indices2T] empirical_moments_inc = empirical_moments_all[income_moments] Omega_inc = Omega_all[income_moments, :][:, income_moments] # set up initial guess and bounds init_params = np.array([ 0.005, #permanent variance 0.003, #transitory variance 0.5, #decay parameter of slightly persistant transitory shock 0.5, #fraction of transitory variance that has no persistence 0.0 ]) # decay parameter of perm shock optimize_index = np.array([ 0, #permanent variance 1, #transitory variance
def implied_cov_expdecayshk_continuous(var_expdecayshk, omega, T): ''' Calculates the covariance matrix for an exponentially decaying stochastic process, time aggregated in continuous time ''' time_varying_omega = False if isinstance(var_expdecayshk, (np.floating, float)): var_expdecayshk = var_expdecayshk * np.ones(T + 1) elif len(var_expdecayshk) != T + 1: return "var_expdecayshk must be a float or array of length T+1" if isinstance(omega, (np.floating, float)): omega = omega * np.ones(T + 1) if len(omega) == T + 1: time_varying_omega = (max(np.abs(np.diff(omega))) > 0.0) else: return "omega must be a float or array of length T+1" # Set up covariance matrix, initialized to zero cov_y = np.zeros((T, T)) #/* Income */ # pre-calculate covariance matrix of a stochasic process with shocks # that decay at rate omega, will be updated if omega is time-varying cov_omega, components = cov_omega_theta(omega[0], omega[0]) #first add in components of variance from shocks from before time starts for t in range(T): if t + 2 <= T - 1: for m in range(T - t - 2): cov_y[t, t + 2 + m] += var_expdecayshk[0] * components[0, 3] * np.exp( -(2 * t + m) * omega[0]) if t + 1 <= T - 1: cov_y[t, t + 1] += var_expdecayshk[0] * components[1, 3] * np.exp( -t * 2 * omega[0]) cov_y[t, t] += var_expdecayshk[0] * components[2, 3] * np.exp( -t * 2 * omega[0]) # Now add in compoments of variance for each time period (loop over k is for shock years, loop over t is the year for which we are calculating the variance/covariance) for k in np.array(range(T + 2)) - 1: param_index = max( k, 0) #Shocks before time -1 take same params at time -1 # If omega is time-varying, then update the cov_omega results to reflect parameters from the shock year (K) if time_varying_omega: cov_omega, components = cov_omega_theta(omega[param_index], omega[param_index]) # Now loop over the T years in which we measure variance/covariance, adding in the effect of shocks that originate at time k for t in range(T): if (t - k >= 2): for m in range(T - t - 2): if t + 2 + m <= T - 1: cov_y[t, t + 2 + m] += var_expdecayshk[param_index] * components[ 0, 2] * np.exp(-(2 * (t - k - 2) + m) * omega[param_index]) if t + 1 <= T - 1: cov_y[t, t + 1] += var_expdecayshk[param_index] * components[ 1, 2] * np.exp(-2 * (t - k - 2) * omega[param_index]) cov_y[t, t] += var_expdecayshk[param_index] * components[ 2, 2] * np.exp(-2 * (t - k - 2) * omega[param_index]) if (t - k == 1): for m in range(T - t - 2): if t + 2 + m <= T - 1: cov_y[t, t + 2 + m] += var_expdecayshk[param_index] * components[ 0, 1] * np.exp(-m * omega[0]) if t + 1 <= T - 1: cov_y[t, t + 1] += var_expdecayshk[param_index] * components[1, 1] cov_y[t, t] += var_expdecayshk[param_index] * components[2, 1] if (t - k == 0): for m in range(T - t - 2): if t + 2 + m <= T - 1: cov_y[t, t + 2 + m] += var_expdecayshk[param_index] * components[ 0, 0] * np.exp(-m * omega[0]) if t + 1 <= T - 1: cov_y[t, t + 1] += var_expdecayshk[param_index] * components[1, 0] cov_y[t, t] += var_expdecayshk[param_index] * components[2, 0] # So far we've created an upper triangular matrix, reflect it along diagonal: for t in np.array(range(T)): for j in np.array(range(T - t - 1)) + 1: cov_y[t + j, t] = cov_y[t, t + j] # Turn matrix into vector vech_indicesT = vech_indices(T) cov_y_vec = cov_y[vech_indicesT] return cov_y_vec