|
16 | 16 | from numba import njit
|
17 | 17 |
|
18 | 18 |
|
| 19 | +def rouwenhorst(n, ybar, sigma, rho): |
| 20 | + """ |
| 21 | + Takes as inputs n, p, q, psi. It will then construct a markov chain |
| 22 | + that estimates an AR(1) process of: |
| 23 | + y_t = \bar{y} + \rho y_{t-1} + \varepsilon_t |
| 24 | + where \varepsilon_t is i.i.d. normal of mean 0, std dev of sigma |
| 25 | +
|
| 26 | + The Rouwenhorst approximation uses the following recursive defintion |
| 27 | + for approximating a distribution: |
| 28 | +
|
| 29 | + theta_2 = [p , 1 - p] |
| 30 | + [1 - q, q ] |
| 31 | +
|
| 32 | + theta_{n+1} = p [theta_n, 0] + (1 - p) [0, theta_n] |
| 33 | + [0 , 0] [0, 0] |
| 34 | + + q [0 , 0] + (1 - q) [0, ] |
| 35 | + [theta_n , 0] [0, theta_n] |
| 36 | +
|
| 37 | + Parameters |
| 38 | + ---------- |
| 39 | + n : int |
| 40 | + The number of points to approximate the distribution |
| 41 | +
|
| 42 | + ybar : float |
| 43 | + The value \bar{y} in the process. Note that the mean of this |
| 44 | + AR(1) process, y, is simply ybar/(1 - rho) |
| 45 | +
|
| 46 | + sigma : float |
| 47 | + The value of the standard deviation of the \varepsilon process |
| 48 | +
|
| 49 | + rho : float |
| 50 | + By default this will be 0, but if you are approximating an AR(1) |
| 51 | + process then this is the autocorrelation across periods |
| 52 | +
|
| 53 | + Returns |
| 54 | + ------- |
| 55 | + |
| 56 | + mc : MarkovChain |
| 57 | + An instance of the MarkovChain class that stores the transition |
| 58 | + matrix and state values returned by the discretization method |
| 59 | + |
| 60 | + """ |
| 61 | + |
| 62 | + # Get the standard deviation of y |
| 63 | + y_sd = sqrt(sigma**2 / (1 - rho**2)) |
| 64 | + |
| 65 | + # Given the moments of our process we can find the right values |
| 66 | + # for p, q, psi because there are analytical solutions as shown in |
| 67 | + # Gianluca Violante's notes on computational methods |
| 68 | + p = (1 + rho) / 2 |
| 69 | + q = p |
| 70 | + psi = y_sd * np.sqrt(n - 1) |
| 71 | + |
| 72 | + # Find the states |
| 73 | + ubar = psi |
| 74 | + lbar = -ubar |
| 75 | + |
| 76 | + bar = np.linspace(lbar, ubar, n) |
| 77 | + |
| 78 | + def row_build_mat(n, p, q): |
| 79 | + """ |
| 80 | + This method uses the values of p and q to build the transition |
| 81 | + matrix for the rouwenhorst method |
| 82 | + """ |
| 83 | + |
| 84 | + if n == 2: |
| 85 | + theta = np.array([[p, 1 - p], [1 - q, q]]) |
| 86 | + |
| 87 | + elif n > 2: |
| 88 | + p1 = np.zeros((n, n)) |
| 89 | + p2 = np.zeros((n, n)) |
| 90 | + p3 = np.zeros((n, n)) |
| 91 | + p4 = np.zeros((n, n)) |
| 92 | + |
| 93 | + new_mat = row_build_mat(n - 1, p, q) |
| 94 | + |
| 95 | + p1[:n - 1, :n - 1] = p * new_mat |
| 96 | + p2[:n - 1, 1:] = (1 - p) * new_mat |
| 97 | + p3[1:, :-1] = (1 - q) * new_mat |
| 98 | + p4[1:, 1:] = q * new_mat |
| 99 | + |
| 100 | + theta = p1 + p2 + p3 + p4 |
| 101 | + theta[1:n - 1, :] = theta[1:n - 1, :] / 2 |
| 102 | + |
| 103 | + else: |
| 104 | + raise ValueError("The number of states must be positive " + |
| 105 | + "and greater than or equal to 2") |
| 106 | + |
| 107 | + return theta |
| 108 | + |
| 109 | + theta = row_build_mat(n, p, q) |
| 110 | + |
| 111 | + bar += ybar / (1 - rho) |
| 112 | + |
| 113 | + return MarkovChain(theta, bar) |
| 114 | + |
| 115 | + |
19 | 116 | def tauchen(rho, sigma_u, m=3, n=7):
|
20 | 117 | """
|
21 | 118 | Computes a Markov chain associated with a discretized version of
|
|
0 commit comments