!pip install --upgrade quantecon import quantecon as qe import numpy as np import matplotlib.pyplot as plt %matplotlib inline def LQ_markov_mapping(A22, C2, Ug, p1, p2, c1=0): """ Function which takes A22, C2, Ug, p_{t, t+1}, p_{t, t+2} and penalty parameter c1, and returns the required matrices for the LQMarkov model: A, B, C, R, Q, W. This version uses the condensed version of the endogenous state. """ # Make sure all matrices can be treated as 2D arrays A22 = np.atleast_2d(A22) C2 = np.atleast_2d(C2) Ug = np.atleast_2d(Ug) p1 = np.atleast_2d(p1) p2 = np.atleast_2d(p2) # Find the number of states (z) and shocks (w) nz, nw = C2.shape # Create A11, B1, S1, S2, Sg, S matrices A11 = np.zeros((2, 2)) A11[0, 1] = 1 B1 = np.eye(2) S1 = np.hstack((np.eye(1), np.zeros((1, nz+1)))) Sg = np.hstack((np.zeros((1, 2)), Ug)) S = S1 + Sg # Create M matrix M = np.hstack((-p1, -p2)) # Create A, B, C matrices A_T = np.hstack((A11, np.zeros((2, nz)))) A_B = np.hstack((np.zeros((nz, 2)), A22)) A = np.vstack((A_T, A_B)) B = np.vstack((B1, np.zeros((nz, 2)))) C = np.vstack((np.zeros((2, nw)), C2)) # Create Q^c matrix Qc = np.array([[1, -1], [-1, 1]]) # Create R, Q, W matrices R = S.T @ S Q = M.T @ M + c1 * Qc W = M.T @ S return A, B, C, R, Q, W # Model parameters β, Gbar, ρ, σ, c1 = 0.95, 5, 0.8, 1, 0 p1, p2, p3, p4 = β, β**2 - 0.02, β, β**2 + 0.02 # Basic model matrices A22 = np.array([[1, 0], [Gbar, ρ] ,]) C_2 = np.array([[0], [σ]]) Ug = np.array([[0, 1]]) A1, B1, C1, R1, Q1, W1 = LQ_markov_mapping(A22, C_2, Ug, p1, p2, c1) A2, B2, C2, R2, Q2, W2 = LQ_markov_mapping(A22, C_2, Ug, p3, p4, c1) # Small penalties on debt required to implement no-Ponzi scheme R1[0, 0] = R1[0, 0] + 1e-9 R2[0, 0] = R2[0, 0] + 1e-9 # Construct lists of matrices correspond to each state As = [A1, A2] Bs = [B1, B2] Cs = [C1, C2] Rs = [R1, R2] Qs = [Q1, Q2] Ws = [W1, W2] Π = np.array([[0.9, 0.1], [0.1, 0.9]]) # Construct and solve the model using the LQMarkov class lqm = qe.LQMarkov(Π, Qs, Rs, As, Bs, Cs=Cs, Ns=Ws, beta=β) lqm.stationary_values() # Simulate the model x0 = np.array([[100, 50, 1, 10]]) x, u, w, t = lqm.compute_sequence(x0, ts_length=300) # Plot of one and two-period debt issuance fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 4)) ax1.plot(u[0, :]) ax1.set_title('One-period debt issuance') ax1.set_xlabel('Time') ax2.plot(u[1, :]) ax2.set_title('Two-period debt issuance') ax2.set_xlabel('Time') plt.show() # Put small penalty on different issuance across maturities c1 = 0.01 A1, B1, C1, R1, Q1, W1 = LQ_markov_mapping(A22, C_2, Ug, p1, p2, c1) A2, B2, C2, R2, Q2, W2 = LQ_markov_mapping(A22, C_2, Ug, p3, p4, c1) # Small penalties on debt required to implement no-Ponzi scheme R1[0, 0] = R1[0, 0] + 1e-9 R2[0, 0] = R2[0, 0] + 1e-9 # Construct lists of matrices As = [A1, A2] Bs = [B1, B2] Cs = [C1, C2] Rs = [R1, R2] Qs = [Q1, Q2] Ws = [W1, W2] # Construct and solve the model using the LQMarkov class lqm2 = qe.LQMarkov(Π, Qs, Rs, As, Bs, Cs=Cs, Ns=Ws, beta=β) lqm2.stationary_values() # Simulate the model x, u, w, t = lqm2.compute_sequence(x0, ts_length=300) # Plot of one and two-period debt issuance fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 4)) ax1.plot(u[0, :]) ax1.set_title('One-period debt issuance') ax1.set_xlabel('Time') ax2.plot(u[1, :]) ax2.set_title('Two-period debt issuance') ax2.set_xlabel('Time') plt.show() def LQ_markov_mapping_restruct(A22, C2, Ug, T, p_t, c=0): """ Function which takes A22, C2, T, p_t, c and returns the required matrices for the LQMarkov model: A, B, C, R, Q, W Note, p_t should be a T by 1 matrix c is the rescheduling cost (a scalar) This version uses the condensed version of the endogenous state """ # Make sure all matrices can be treated as 2D arrays A22 = np.atleast_2d(A22) C2 = np.atleast_2d(C2) Ug = np.atleast_2d(Ug) p_t = np.atleast_2d(p_t) # Find the number of states (z) and shocks (w) nz, nw = C2.shape # Create Sx, tSx, Ss, S_t matrices (tSx stands for \tilde S_x) Ss = np.hstack((np.eye(T-1), np.zeros((T-1, 1)))) Sx = np.hstack((np.zeros((T-1, 1)), np.eye(T-1))) tSx = np.zeros((1, T)) tSx[0, 0] = 1 S_t = np.hstack((tSx + p_t.T @ Ss.T @ Sx, Ug)) # Create A, B, C matrices A_T = np.hstack((np.zeros((T, T)), np.zeros((T, nz)))) A_B = np.hstack((np.zeros((nz, T)), A22)) A = np.vstack((A_T, A_B)) B = np.vstack((np.eye(T), np.zeros((nz, T)))) C = np.vstack((np.zeros((T, nw)), C2)) # Create cost matrix Sc Sc = np.hstack((np.eye(T), np.zeros((T, nz)))) # Create R_t, Q_t, W_t matrices R_c = S_t.T @ S_t + c * Sc.T @ Sc Q_c = p_t @ p_t.T + c * np.eye(T) W_c = -p_t @ S_t - c * Sc return A, B, C, R_c, Q_c, W_c # New model parameters H = 3 p1 = np.array([[0.9695], [0.902], [0.8369]]) p2 = np.array([[0.9295], [0.902], [0.8769]]) Pi = np.array([[0.9, 0.1], [0.1, 0.9]]) # Put penalty on different issuance across maturities c2 = 0.5 A1, B1, C1, R1, Q1, W1 = LQ_markov_mapping_restruct(A22, C_2, Ug, H, p1, c2) A2, B2, C2, R2, Q2, W2 = LQ_markov_mapping_restruct(A22, C_2, Ug, H, p2, c2) # Small penalties on debt required to implement no-Ponzi scheme R1[0, 0] = R1[0, 0] + 1e-9 R1[1, 1] = R1[1, 1] + 1e-9 R1[2, 2] = R1[2, 2] + 1e-9 R2[0, 0] = R2[0, 0] + 1e-9 R2[1, 1] = R2[1, 1] + 1e-9 R2[2, 2] = R2[2, 2] + 1e-9 # Construct lists of matrices As = [A1, A2] Bs = [B1, B2] Cs = [C1, C2] Rs = [R1, R2] Qs = [Q1, Q2] Ws = [W1, W2] # Construct and solve the model using the LQMarkov class lqm3 = qe.LQMarkov(Π, Qs, Rs, As, Bs, Cs=Cs, Ns=Ws, beta=β) lqm3.stationary_values() x0 = np.array([[5000, 5000, 5000, 1, 10]]) x, u, w, t = lqm3.compute_sequence(x0, ts_length=300) # Plots of different maturities debt issuance fig, (ax1, ax2, ax3, ax4) = plt.subplots(1, 4, figsize=(16, 4)) ax1.plot(u[0, :]) ax1.set_title('One-period debt issuance') ax1.set_xlabel('Time') ax2.plot(u[1, :]) ax2.set_title('Two-period debt issuance') ax2.set_xlabel('Time') ax3.plot(u[2, :]) ax3.set_title('Three-period debt issuance') ax3.set_xlabel('Time') ax4.plot(u[0, :] + u[1, :] + u[2, :]) ax4.set_title('Total debt issuance') ax4.set_xlabel('Time') plt.tight_layout() plt.show() # Plot share of debt issuance that is short-term fig, ax = plt.subplots() ax.plot((u[0, :] / (u[0, :] + u[1, :] + u[2, :]))) ax.set_title('One-period debt issuance share') ax.set_xlabel('Time') plt.show()