@@ -671,31 +671,24 @@ c_init = a_init
671671a_vec, c_vec = solve_model_time_iter(ifp, a_init, c_init)
672672assets = compute_asset_stationary(c_vec, a_vec, ifp, num_households=200_000)
673673674-# Diagnostic: Check extrapolation issues
675-print(f"\n=== Grid and Asset Diagnostics ===")
676-print(f"Grid max (s_grid[-1]): {ifp.s_grid[-1]:.2f}")
677-print(f"Endogenous grid max (a_vec.max()): {a_vec.max():.2f}")
678-print(f"Simulated assets max: {assets.max():.2f}")
679-print(f"Simulated assets mean: {assets.mean():.2f}")
680-print(f"Simulated assets median: {np.median(assets):.2f}")
681-print(f"Fraction of households beyond grid: {(assets > a_vec.max()).mean():.4f}")
682-print(f"Fraction beyond 0.9 * grid_max: {(assets > 0.9 * a_vec.max()).mean():.4f}")
683-print()
684-685674# Compute Gini coefficient for the plot
686675gini_plot = gini_coefficient(assets)
687676688-# Plot: Histogram with log-scale y-axis
677+# Plot histogram of log wealth
689678fig, ax = plt.subplots(figsize=(10, 6))
690-ax.hist(assets, bins=40, alpha=0.5, density=True)
691-ax.set_yscale('log')
692-ax.set(xlabel='assets', ylabel='density (log scale)',
693- title="Wealth Distribution")
679+ax.hist(jnp.log(assets), bins=40, alpha=0.5, density=True)
680+ax.set(xlabel='log assets', ylabel='density', title="Wealth Distribution")
694681plt.tight_layout()
695682plt.show()
696683```
697684698-The histogram shows the wealth distribution with the y-axis on a log scale, allowing us to see both the mass of households at low wealth levels and the long right tail of the distribution.
685+The histogram shows the distribution of log wealth.
686+687+Bearing in mind that we are looking at log values, the histogram suggests
688+a long right tail of the distribution.
689+690+Below we examine this in more detail.
691+699692700693701694## Wealth Inequality
@@ -751,7 +744,7 @@ We loop over different values of `a_r`, solve the model for each, simulate the w
751744752745```{code-cell} ipython3
753746# Range of a_r values to explore
754-a_r_vals = np.linspace(0.10, 0.16, 7)
747+a_r_vals = np.linspace(0.10, 0.16, 5)
755748gini_vals = []
756749757750print("Computing Gini coefficients for different return volatilities...\n")
@@ -787,7 +780,7 @@ ax.plot(a_r_vals, gini_vals, 'o-', linewidth=2, markersize=8)
787780ax.set(xlabel='Return volatility (a_r)',
788781 ylabel='Gini coefficient',
789782 title='Wealth Inequality vs Return Volatility')
790-ax.axhline(y=0.8, color='r', linestyle='--', linewidth=1,
783+ax.axhline(y=0.8, color='k', linestyle='--', linewidth=1,
791784 label='Empirical US Gini (~0.8)')
792785ax.legend()
793786plt.tight_layout()
@@ -803,5 +796,90 @@ high returns accumulate substantially more wealth than unlucky households,
803796leading to greater inequality in the wealth distribution.
804797805798799+```{solution-end}
800+```
801+802+```{exercise}
803+:label: ifp_advanced_ex2
804+805+Plot how the Gini coefficient varies with the volatility of labor income.
806+807+Specifically, compute the Gini coefficient for values of `a_y` ranging from
808+0.125 to 0.20 and plot the results. Set `a_r=0.10` for this exercise.
809+810+What does this tell you about the relationship between labor income risk and
811+wealth inequality? Can we achieve the same rise in inequality by varying labor
812+income volatility as we can by varying return volatility?
813+814+```
815+816+```{solution-start} ifp_advanced_ex2
817+:class: dropdown
818+```
819+820+We loop over different values of `a_y`, solve the model for each, simulate the wealth distribution, and compute the Gini coefficient.
821+822+```{code-cell} ipython3
823+# Range of a_y values to explore
824+a_y_vals = np.linspace(0.125, 0.20, 5)
825+gini_vals_y = []
826+827+print("Computing Gini coefficients for different labor income volatilities...\n")
828+829+for a_y in a_y_vals:
830+ print(f"a_y = {a_y:.3f}...", end=" ")
831+832+ # Create model with this a_y value and a_r=0.10
833+ ifp_temp = create_ifp(a_y=a_y, a_r=0.10, grid_max=100)
834+835+ # Solve the model
836+ s_grid_temp = ifp_temp.s_grid
837+ n_z_temp = len(ifp_temp.P)
838+ a_init_temp = s_grid_temp[:, None] * jnp.ones(n_z_temp)
839+ c_init_temp = a_init_temp
840+ a_vec_temp, c_vec_temp = solve_model_time_iter(
841+ ifp_temp, a_init_temp, c_init_temp, verbose=False
842+ )
843+844+ # Simulate households
845+ assets_temp = compute_asset_stationary(
846+ c_vec_temp, a_vec_temp, ifp_temp, num_households=200_000
847+ )
848+849+ # Compute Gini coefficient
850+ gini_temp = gini_coefficient(assets_temp)
851+ gini_vals_y.append(gini_temp)
852+ print(f"Gini = {gini_temp:.4f}")
853+854+# Plot the results
855+fig, ax = plt.subplots(figsize=(10, 6))
856+ax.plot(a_y_vals, gini_vals_y, 'o-', linewidth=2, markersize=8, color='green')
857+ax.set(xlabel='Labor income volatility (a_y)',
858+ ylabel='Gini coefficient',
859+ title='Wealth Inequality vs Labor Income Volatility')
860+ax.axhline(y=0.8, color='k', linestyle='--', linewidth=1,
861+ label='Empirical US Gini (~0.8)')
862+ax.legend()
863+plt.tight_layout()
864+plt.show()
865+```
866+867+The plot shows that wealth inequality increases with labor income volatility, but the effect is much weaker than the effect of return volatility.
868+869+Comparing the two exercises:
870+871+- When return volatility (`a_r`) varies from 0.10 to 0.16, the Gini coefficient rises dramatically from around 0.20 to 0.79
872+- When labor income volatility (`a_y`) varies from 0.125 to 0.20, a similar amount in percentage terms, the Gini coefficient increases but by a much smaller amount
873+874+This suggests that capital income risk is a more important driver of wealth inequality than labor income risk.
875+876+The intuition is that wealth accumulation compounds over time: households who
877+experience favorable returns on their assets can reinvest those returns, leading
878+to exponential growth.
879+880+In contrast, labor income shocks, while they affect current consumption and
881+savings, do not have the same compounding effect on wealth accumulation.
882+883+806884```{solution-end}
807885```